AI Chatbot with Python

In the last lesson, Web Scraper Project, you gathered data from the open web. This is the final project of the whole course, and we are ending big. We are going to build an AI chatbot, a program you can actually talk to, powered by a large language model. It brings together so much of what you have learned: functions, loops, lists, input, error handling, and APIs, plus the LLM ideas from the AI module. By the end you will have a chatbot that holds a real conversation. Let’s finish strong.

🤔 How does a chatbot work?

A chatbot feels clever, but the loop behind it is simple. It repeats the same few steps over and over.

Each turn of a chat does this:

  • Read what the user typed.
  • Send that message to a large language model, along with the chat so far.
  • Get the model’s reply back.
  • Show the reply, and remember it for next time.

The one new idea here is conversation history: the chatbot must remember what was already said, or it would forget the start of the chat. Each new message is sent along with all the previous ones, so the model has the full context. We keep that history in a list. Everything else you already know.

🔌 The tool: the Claude API

We will use Claude, a leading large language model from Anthropic, through its Python library. As you learned in the LLM lesson, you do not run the model yourself. You send your messages to it over an API and read its reply.

You install the library once. You also need a free API key from the Anthropic website, which identifies you:

Terminal window
pip install anthropic

Here is the smallest possible call, to remind you of the shape from the LLM lesson:

import anthropic
client = anthropic.Anthropic(api_key="YOUR_API_KEY_HERE")
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=200,
messages=[
{"role": "user", "content": "Say hello in one short sentence."}
]
)
print(response.content[0].text)

Output

Hello there, it is great to meet you!

So you send a list of messages and read the reply from response.content[0].text. The key piece for a chatbot is that messages list. To remember the conversation, we keep adding to it.

Caution

Never paste a real API key into code you share or upload. Keep it in an environment variable and read it in your program, the safe habit you learned in API authentication. The "YOUR_API_KEY_HERE" placeholder here is just to show where it goes.

🧩 Step 1: Keeping the conversation history

The trick to a real conversation is the messages list. Each message is a dictionary with a role ("user" for you, "assistant" for the bot) and the content. We add to this list every turn, so the model always sees the whole chat.

This shows how the history grows over a couple of turns:

messages = []
# user says something
messages.append({"role": "user", "content": "My name is Alex."})
# the bot replies, and we save its reply too
messages.append({"role": "assistant", "content": "Nice to meet you, Alex!"})
# user asks a follow-up
messages.append({"role": "user", "content": "What is my name?"})

Because the whole list is sent each time, the model can look back and answer “What is my name?” correctly with “Alex”, even though that was said earlier. If we only ever sent the latest message, the bot would have no memory and could not answer. So the growing list is the chatbot’s memory.

💬 Step 2: Getting a reply

We wrap the API call in a function. It takes the history, sends it, gets the reply, and returns the text.

This function sends the conversation and returns the bot’s reply:

import anthropic
client = anthropic.Anthropic(api_key="YOUR_API_KEY_HERE")
def get_reply(messages):
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=300,
messages=messages
)
return response.content[0].text

Read what it does:

  • It takes the whole messages list, the full conversation so far.
  • client.messages.create(...) sends it to the model. max_tokens=300 caps the reply length so it does not run on too long.
  • It pulls the reply text out of the response and returns it.

So this one function is the bridge to the AI: hand it the conversation, get back the next reply.

🖥️ Step 3: The complete chatbot

Now we put it in a loop so you can chat back and forth. Each turn we read your message, add it to the history, get the reply, add that too, and show it. Save it as chatbot.py and run it.

import anthropic
client = anthropic.Anthropic(api_key="YOUR_API_KEY_HERE")
def get_reply(messages):
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=300,
messages=messages
)
return response.content[0].text
def main():
print("AI Chatbot (type 'quit' to leave)")
messages = []
while True:
user_input = input("\nYou: ")
if user_input.lower() == "quit":
print("Bot: Goodbye!")
break
messages.append({"role": "user", "content": user_input})
try:
reply = get_reply(messages)
except anthropic.APIError:
print("Bot: Sorry, I had a problem reaching the AI. Try again.")
continue
messages.append({"role": "assistant", "content": reply})
print("Bot:", reply)
main()

Here is a sample chat, showing that the bot remembers:

Output

AI Chatbot (type 'quit' to leave)
You: Hi! My name is Alex.
Bot: Hi Alex, nice to meet you. How can I help you today?
You: What is my name?
Bot: Your name is Alex.
You: quit
Bot: Goodbye!

Look closely at the second answer. The bot knew the name was Alex because we kept the history and sent it every turn. That memory is what turns single questions into a real conversation. You just built a working AI chatbot, and you understand every line of it.

⚠️ Common Mistakes

A few traps in this project:

  • Not saving the conversation history. If you only send the latest message, the bot forgets everything and cannot follow the chat. Always append both the user message and the reply.
  • Forgetting to add the bot’s reply to the history. You must append the assistant message too, not just the user’s, or the model loses half the conversation.
  • Putting a real API key in shared code. Keep it secret, in an environment variable. A leaked key can be used by others on your account.
  • Not handling API errors. The network or the service can fail. Wrapping the call in try / except keeps the chat alive instead of crashing.

✅ Best Practices

Habits this project teaches:

  • Keep the full conversation in a messages list, appending every user message and every reply, so the bot remembers.
  • Read your API key from an environment variable, never hard-coded in shared code.
  • Set a sensible max_tokens so replies stay the length you want and costs stay predictable.
  • Handle API and network errors gracefully, so a single hiccup does not end the conversation.

🧩 What You’ve Learned

✅ You built a working AI chatbot that holds a real, remembered conversation.

✅ A chatbot loops: read input, send the history to the model, get a reply, show it, and remember it.

✅ Conversation history is a messages list of user and assistant turns, sent in full each time so the model has context.

client.messages.create(...) calls the Claude API, and you read the reply from response.content[0].text.

✅ Keep your API key secret and handle errors, so the chatbot is safe and reliable.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Why does the chatbot keep a conversation history in a list?

    Why: Sending the full history each turn gives the model context, so it can remember earlier details like the user's name and follow the conversation.

  2. 2

    What two roles appear in the messages list?

    Why: Each message has a role: 'user' for what the person says and 'assistant' for the bot's replies. Both are appended to keep the full chat.

  3. 3

    What happens if you forget to append the bot's reply to the history?

    Why: The history must include both sides. If the assistant replies are missing, the model only sees the user's lines and loses the thread of the chat.

  4. 4

    Why wrap the API call in try / except anthropic.APIError?

    Why: Calls over the internet can fail. Catching the error lets the chatbot show a friendly message and keep running instead of crashing.

🚀 What’s Next?

That is it. You built an AI chatbot, and with it you have finished the entire Python course, from your very first print statement all the way to working with large language models. You now know variables, functions, loops, OOP, files, APIs, data analysis, machine learning, and real projects. The best next step is to keep building. Pick an idea you care about, start small, and grow it. You have every tool you need.

Back to the Python Course

Share & Connect