Build a Real AI Agent · Part 2

Five Lines to Talk to a Model (and Why It Forgets You)

Ayman Hamed· 10 November 2026· 4 min read
Part 2 of 4Build a Real AI Agent
  1. Your AI Can’t Check the Weather (Yet): What Is an AI Agent?
  2. Five Lines to Talk to a Model (and Why It Forgets You)
  3. Why AI Types Word by Word
  4. The Model Has No Hands
AI AgentsLLMPythonBeginners

Before an agent can act, it has to talk. So step one is the smallest program that sends a message to a model and prints the reply. But first, a place to run it.

Set up your lab (about 10 minutes, once)

You need two tools. That's the whole lab.

  • uv manages Python for you: it installs Python, creates the project, and adds packages. One tool instead of python
    • venv + pip.
  • Ollama runs AI models on your own machine. Free, no account, no API key.

1. Install uv

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Close and reopen your terminal, then check: uv --version.

2. Install Ollama and pull a model

Download Ollama from ollama.com/download (macOS and Windows), or on Linux run curl -fsSL https://ollama.com/install.sh | sh. Then:

ollama pull qwen2.5     # about 4.7 GB, one time
ollama run qwen2.5 "Say hi in five words"

If it answers, your model works.

3. Create the project

uv init agent-lab
cd agent-lab
uv add ollama

uv init makes the folder and a pyproject.toml; uv add installs the ollama Python package into the project's own environment. You don't need to install Python first: uv fetches it if it's missing.

You'll run every example in this series the same way: save the code as a file inside agent-lab, then uv run hello.py.

New to the terminal, uv or Git? Two free guides on this site walk through it step by step: Git & uv Quick Start (16 pages) and The AI Agent Developer's Toolbelt (terminal, uv, Ollama, Git, secrets and more).

Hello, model

Save this as hello.py:

import ollama

messages = [
    {"role": "system", "content": "You are a friendly assistant. Keep answers short."},
    {"role": "user", "content": "Tell me a very short joke about AI."},
]

response = ollama.chat(model="qwen2.5", messages=messages)
print(response.message.content)

Run it with uv run hello.py. You'll get something like:

Why did the AI break up with the calculator? It felt like it was being taken for granted — every single time.

Okay, the joke is bad. But look at what just happened: your Python code had a conversation with an AI. No website, no account, no magic.

A conversation is just a list

The most important thing on that page is not the chat call. It's this:

messages = [ {...}, {...} ]

A conversation, to a model, is a plain Python list of messages. Each message has a role and some content:

RoleWho's speakingExample
systemYou, the developer — setting the rules"Keep answers short."
userThe human"Tell me a joke."
assistantThe model's earlier replies"Why did the AI…"

That's it. Every chat app you've ever used — however shiny — is building a list like this behind the scenes and sending it to a model.

The experiment that surprises everyone

Let's have a two-message conversation. Two separate calls:

import ollama

ollama.chat(model="qwen2.5", messages=[
    {"role": "user", "content": "Hi! My name is Sara."},
])

reply = ollama.chat(model="qwen2.5", messages=[
    {"role": "user", "content": "What's my name?"},
])
print(reply.message.content)

The answer?

I'm sorry, I don't know your name. Could you tell me?

Sara told it her name one second ago. Gone.

The model is stateless

This is the single most important fact about LLMs, and almost nobody tells beginners:

The model remembers nothing between calls.

Every call is a brand-new brain that has never met you. The only thing it knows is the list you send it right now.

So how does ChatGPT remember what you said three messages ago? Simple: the app sends the whole conversation again, every single time. Let's do the same:

import ollama

messages = [{"role": "user", "content": "Hi! My name is Sara."}]
first = ollama.chat(model="qwen2.5", messages=messages)
messages.append(first.message)                     # keep the model's reply

messages.append({"role": "user", "content": "What's my name?"})
second = ollama.chat(model="qwen2.5", messages=messages)
print(second.message.content)                      # "Your name is Sara!"

Now it "remembers." But notice: the model didn't remember anything. Your list did. You are the memory.

Hold on to that idea. It comes back in a big way later in the series, when we give our agent a memory that survives even after you close the program.

Three things to keep

  1. A conversation is a list of messages with roles.
  2. The model is stateless — it forgets everything between calls.
  3. "Memory" in a chat is just your code sending the history again.

What's next

Our program works, but it's awkward: you stare at a blank screen until the whole answer arrives at once. Real AI chats type word by word. In the next article, we find out why — and make ours do it too, with one tiny change.

Continue: Why AI Types Word by Word
ShareXLinkedInWhatsApp

Comments

Loading comments…