Your Chapter 7 helper had two limits: it forgot everything between questions, and it could only talk — it couldn't do anything. In this chapter you fix both. This is the leap from chatbot to agent.
Remember the agent loop from Chapter 1? Think → Act → Check. You're about to build it for real.
Part 1 — Memory
An AI has no memory on its own. The trick: keep a list of the whole conversation and send it every time. Each turn, you add the new message to the list.
history = []
def chat(user_message):
history.append({"role": "user", "content": user_message})
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=300,
system="You are a friendly assistant who remembers our whole conversation.",
messages=history, # send the FULL history every time
)
reply = message.content[0].text
history.append({"role": "assistant", "content": reply}) # remember the reply too
return reply
print(chat("My name is Sam and I love space."))
print(chat("What's my name and what do I love?"))
The second answer knows your name — because the whole history travelled with the prompt. That list is the memory.
Tip
This is exactly how every chatbot "remembers" — there's no magic. It re-reads the conversation each time. (Real apps eventually shorten very long histories so they don't get too big — but the idea is the same.)
Part 2 — Tools turn a chatbot into an agent
A chatbot only makes words. An agent can use tools to take actions — exactly the "Act" step from Chapter 1. You give Claude a tool, and it decides when to use it.
Let's build a roll_dice tool. First, the real function that does the work:
import random
def roll_dice(sides, count):
return [random.randint(1, sides) for _ in range(count)]
Then we describe the tool to Claude so it knows when to reach for it (just like a clear tool description from your prompting lessons):
tools = [
{
"name": "roll_dice",
"description": "Roll dice. Use this whenever the user wants a random dice roll.",
"input_schema": {
"type": "object",
"properties": {
"sides": {"type": "integer", "description": "Number of sides per die"},
"count": {"type": "integer", "description": "How many dice to roll"},
},
"required": ["sides", "count"],
},
}
]
The agent loop in code
Here's the whole think → act → check loop. Read the comments — you've seen this idea since Chapter 1:
def run_agent(user_message):
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=400,
tools=tools,
messages=messages,
)
if response.stop_reason == "tool_use":
# THINK: Claude decided it needs a tool.
messages.append({"role": "assistant", "content": response.content})
results = []
for block in response.content:
if block.type == "tool_use" and block.name == "roll_dice":
# ACT: we run the real tool with Claude's chosen inputs.
rolled = roll_dice(block.input["sides"], block.input["count"])
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(rolled),
})
# CHECK: send the result back so Claude can use it.
messages.append({"role": "user", "content": results})
else:
# Done — return the final answer.
for block in response.content:
if block.type == "text":
return block.text
print(run_agent("Roll three 6-sided dice and tell me the total!"))
Run it. Claude chooses to call your roll_dice tool, your code rolls real
dice, Claude reads the result and writes the final answer. That's an agent. 🤖
Stay safe
Tools give your agent the power to actually do things — so be a careful engineer:
- Only give your agent tools you wrote and understand. Never run tool code copied from a stranger.
- Keep tools safe and small — a dice roller is great; anything that deletes files or spends money is not a beginner project.
- All the API-key rules from Chapter 7 still apply — keep it secret, and an agent can make several calls per task, so watch your usage.
Check yourself
- How does an AI "remember" a conversation?
- In one sentence, what's the difference between a chatbot and an agent?
- In the loop, which line is the Act step (running the real tool)?
Project — Build your mini agent 🛠️
-
Get the dice agent above running and try different requests: "roll two 20-sided dice", "flip a coin" (watch it adapt the dice tool!).
-
Add a second tool. Give your agent a new power, like a coin flip:
def flip_coin(): return random.choice(["Heads", "Tails"])Add a matching description to your
toolslist (no inputs needed), and handleblock.name == "flip_coin"in the loop. Now your agent has two abilities and picks the right one. -
Test it with a tricky request like "flip a coin, and if it's heads roll a die."
Your turn
Invent a fun tool for your agent — a pick_random_name, a get_lucky_number, or
a rock_paper_scissors. The pattern is always the same: write the function,
describe it, handle it in the loop. Agents are just this, repeated.
Make it simpler · ages 9–11
Focus on Part 1 (memory) with a grown-up. Tell the assistant three facts about yourself across three messages, then ask it to repeat them back. Seeing it remember is the magic — the tools part can wait for another day.
Level up · ages 13–16
Give your agent a system prompt persona and a goal, then a tool that helps it
reach the goal — for example a "Game Master" persona with a roll_dice tool for a
mini text adventure. Notice how a persona (Chapter 3) + memory + tools starts to
feel like a real character that does things. That combination is the heart of
every AI agent and app being built today.
What you learned
- Memory = keeping and re-sending the conversation history.
- A tool lets the AI take actions — turning a chatbot into an agent.
- The agent runs the think → act → check loop you met in Chapter 1.
- You built a working agent that chooses and uses a tool. 🎉
You've earned the Agent Architect badge. 🏅
Your agent works in code — but only you can run it. Next, you'll wrap it in a real interface so anyone can use it. That's Chapter 9: Build an Interface People Can Use.