The loop
Read · 1 of 3
Everything comes together
You have every piece: messages, tools, tool results. The agent loop just repeats them:
1. Send the messages. 2. Add the reply to the messages. 3. If stop_reason is end_turn, the model is done. 4. Otherwise run every tool_use, send the results back as a user message, and go to 1.
That's it. Every agent you've heard of (coding agents, research agents, customer-support agents) is this loop with better tools, better prompts and more safety checks.
Read this lesson as text
Twenty lines that turn a model into an agent.
Everything comes together
You have every piece: messages, tools, tool results. The agent loop just repeats them:
1. Send the messages. 2. Add the reply to the messages. 3. If stop_reason is end_turn, the model is done. 4. Otherwise run every tool_use, send the results back as a user message, and go to 1.
That's it. Every agent you've heard of (coding agents, research agents, customer-support agents) is this loop with better tools, better prompts and more safety checks.
Watch an agent think
def calculator(op, a, b):
return a * b if op == "mul" else a + b
client = Client(calc_brain)
messages = [{"role": "user", "content": "What is 2 + 3 * 4?"}]
while True:
reply = client.messages.create(model="stand-in", max_tokens=500, messages=messages)
messages.append({"role": "assistant", "content": reply.content})
if reply.stop_reason == "end_turn":
break
outputs = []
for block in reply.content:
if block.type == "tool_use":
value = calculator(**block.input)
print("tool:", block.input["op"], block.input["a"], block.input["b"], "->", value)
outputs.append({"type": "tool_result", "tool_use_id": block.id, "content": str(value)})
messages.append({"role": "user", "content": outputs})
print(reply.content[0].text)- Line 5: The goal: a question that needs two calculations, in the right order.
- Line 7: Call 1. The model decides to multiply first (3 × 4), so it replies with a tool_use.
- Line 8: The reply joins the conversation, tool request and all.
- Line 9: `tool_use`, not `end_turn`: the model is waiting for us.
- Line 14: Our code does the maths. The model never runs anything itself.
- Line 15: We log each tool call. Logs are how you'll debug agents.
- Line 17: The result goes back, tagged with the tool_use id it answers.
- Line 7: Call 2. Now the model knows 3 × 4 = 12, so it asks to add 2.
- Line 15: Second tool call.
- Line 7: Call 3. With both results in hand, the model answers. No tool this time.
- Line 10: `end_turn`: the loop stops.
- Line 18: Three model calls, two tools, one answer.
How many calls?
def calculator(op, a, b):
return a * b if op == "mul" else a + b
client = Client(calc_brain)
messages = [{"role": "user", "content": "What is 1 + 5 * 6?"}]
while True:
reply = client.messages.create(model="stand-in", max_tokens=500, messages=messages)
messages.append({"role": "assistant", "content": reply.content})
if reply.stop_reason == "end_turn":
break
outputs = []
for block in reply.content:
if block.type == "tool_use":
value = calculator(**block.input)
pass
outputs.append({"type": "tool_result", "tool_use_id": block.id, "content": str(value)})
messages.append({"role": "user", "content": outputs})
print(client.calls)Same loop, new question, and now it prints how many times the model was called. What does it print?
- 2
- 3
- 4
Show the answer
3 One call asks for the multiplication, one asks for the addition, and one gives the answer. Every tool round costs a model call, which is why agents are slower and pricier than a single chat reply.