Lesson 4 of 6 in Foundations
What is a tool? (Function calling)
Why models need tools
By itself, an LLM is a very well-read person locked in a windowless room. It can reason, write, and remember things it saw during training — but it can't check today's weather, query your database, or send an email. Tools solve this. A tool is a function YOU provide that the model can decide to call. The model itself doesn't execute code — it outputs a structured request to call your function; your code runs it and returns the result.
The tool schema
You define each tool with: name (what to call it), description (what it does — this is the routing signal), and input_schema (a JSON Schema describing its parameters). The description is critical: the model reads it to decide when to use this tool. Vague descriptions = vague behavior.
{
"name": "get_weather",
"description": "Get the current weather for a city. Returns temperature in Celsius and a text summary.",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g., 'Toronto'"}
},
"required": ["city"]
}
}The tool_use / tool_result cycle
You send Claude a message with the tools available. If Claude decides to use one, its response contains a tool_use block with the tool name and the input. YOU execute the tool. YOU send back a new user message containing a tool_result block with matching tool_use_id. Then Claude continues, using the result. This full round-trip is one 'tool call cycle.'
The round-trip in code
Here's a full weather-tool exchange, end to end.
# 1. First call — Claude decides to use the tool
r = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=[weather_tool],
messages=[{"role":"user","content":"Weather in Toronto?"}]
)
# r.stop_reason == "tool_use"
# r.content[0] is a tool_use block
# 2. Execute the tool ourselves
tool_use = r.content[0]
result = get_weather(tool_use.input["city"]) # our function
# 3. Send the result back
r2 = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=[weather_tool],
messages=[
{"role":"user","content":"Weather in Toronto?"},
{"role":"assistant","content":r.content},
{"role":"user","content":[{
"type":"tool_result",
"tool_use_id":tool_use.id,
"content":str(result)
}]}
]
)
# r2 is Claude's final answer using the resultWhat the model actually does
The model doesn't 'run' anything. It outputs structured text that says 'I want to call this tool with these arguments.' You are 100% in control of whether and how that tool actually executes. Tools are a way for the model to REQUEST an action, not to perform one directly.
Tool use = the foundation of agents
One tool call cycle isn't yet an agent. But loop it — keep sending tool results back and letting the model decide the next action — and you have one. Every agentic system on the exam is built on top of this basic tool_use / tool_result mechanic.
Takeaways
- Tools let LLMs act on the world; the LLM itself only produces text
- You define tools with name, description, input_schema
- Cycle: Claude asks (tool_use) → you execute → you reply (tool_result)
- Description is the routing signal — vague = misuse
- Loop this cycle and you have an agent