A real agent
Read · 1 of 2
The swap
This is the loop you wrote in module 4. Three things changed: anthropic.Anthropic() replaces the stand-in, the tools are passed as definitions (module 3) in tools=, and the stop check is != "tool_use", so it also stops cleanly if the model hits max_tokens.
Run it with python3 agent.py and watch a real model plan the calculation, call your tool, read the result and answer.
1import anthropic23client = anthropic.Anthropic()45TOOLS = [{6 "name": "calculator",7 "description": "Add or multiply two numbers. Use it for every calculation instead of doing maths yourself.",8 "input_schema": {9 "type": "object",10 "properties": {11 "op": {"type": "string", "enum": ["add", "mul"]},12 "a": {"type": "number"},13 "b": {"type": "number"},14 },15 "required": ["op", "a", "b"],16 },17}]1819def calculator(op, a, b):20 return a * b if op == "mul" else a + b2122messages = [{"role": "user", "content": "What is 17 + 23 * 41? Use the calculator."}]23for _ in range(10): # a turn limit, as in module 424 reply = client.messages.create(model="claude-sonnet-5-5", max_tokens=1000, tools=TOOLS, messages=messages)25 messages.append({"role": "assistant", "content": reply.content})26 if reply.stop_reason != "tool_use":27 break28 outputs = []29 for block in reply.content:30 if block.type == "tool_use":31 try:32 content = str(calculator(**block.input))33 except Exception as e:34 content = "ERROR " + str(e)35 print("tool:", block.name, block.input, "->", content)36 outputs.append({"type": "tool_result", "tool_use_id": block.id, "content": content})37 messages.append({"role": "user", "content": outputs})38print(reply.content[-1].text)
python3 agent.pyRead this lesson as text
Your module 4 loop with a real model and a real tool definition.
The swap
This is the loop you wrote in module 4. Three things changed: anthropic.Anthropic() replaces the stand-in, the tools are passed as definitions (module 3) in tools=, and the stop check is != "tool_use", so it also stops cleanly if the model hits max_tokens.
Run it with python3 agent.py and watch a real model plan the calculation, call your tool, read the result and answer.
import anthropic
client = anthropic.Anthropic()
TOOLS = [{
"name": "calculator",
"description": "Add or multiply two numbers. Use it for every calculation instead of doing maths yourself.",
"input_schema": {
"type": "object",
"properties": {
"op": {"type": "string", "enum": ["add", "mul"]},
"a": {"type": "number"},
"b": {"type": "number"},
},
"required": ["op", "a", "b"],
},
}]
def calculator(op, a, b):
return a * b if op == "mul" else a + b
messages = [{"role": "user", "content": "What is 17 + 23 * 41? Use the calculator."}]
for _ in range(10): # a turn limit, as in module 4
reply = client.messages.create(model="claude-sonnet-5-5", max_tokens=1000, tools=TOOLS, messages=messages)
messages.append({"role": "assistant", "content": reply.content})
if reply.stop_reason != "tool_use":
break
outputs = []
for block in reply.content:
if block.type == "tool_use":
try:
content = str(calculator(**block.input))
except Exception as e:
content = "ERROR " + str(e)
print("tool:", block.name, block.input, "->", content)
outputs.append({"type": "tool_result", "tool_use_id": block.id, "content": content})
messages.append({"role": "user", "content": outputs})
print(reply.content[-1].text)python3 agent.py
Before you ship anything
Log every call: the messages, the tool calls and the token usage. When an agent does something odd, the log is how you find out why.
Run your evals (module 10) against the real model, several times each (pass@k): real models vary between runs in a way the stand-in never did.
Keep the guards: turn limits, budgets, input checks and approval gates (modules 4, 8 and 9). A real model will eventually do something you didn't expect.