Tool use & function calling
Let a model call your functions — fetch data, do math, take actions — instead of guessing.
Prerequisites
- Structured output with schemas
- Calling an LLM API
You will learn
- Describe a tool to a model so it knows when and how to call it
- Run the request-execute-respond loop correctly
- Decide what belongs in a tool versus the prompt
Models are bad at exact math and have no live data. Tool use fixes both by letting the model call functions you provide. The model does not run your code — it asks you to, with structured arguments, and you run it and hand back the result. This is the mechanism behind every useful AI agent.
Overview
You give the model a list of tools, each described by a name, a description, and an input schema. When a request would benefit from a tool, the model returns a tool-use request — the tool name and arguments — instead of a final answer. Your code executes the tool, sends the result back, and the model continues, often producing a natural-language reply that uses the result.
Key ideas
Describe the tool clearly
The description and schema are how the model decides when to call the tool and what to pass. Write them as carefully as you write prompts.
tools = [{
"name": "get_order_status",
"description": "Look up the delivery status of a customer order by its ID.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "The order ID, e.g. ORD-1234"},
},
"required": ["order_id"],
},
}]The request-execute-respond loop
The model asks; you execute; you return the result; the model finishes.
from anthropic import Anthropic
client = Anthropic()
def get_order_status(order_id):
# Your real database call goes here
return {"order_id": order_id, "status": "out for delivery", "eta": "today 6pm"}
messages = [{"role": "user", "content": "Where is order ORD-1234?"}]
response = client.messages.create(
model="claude-sonnet-4-6", max_tokens=400, tools=tools, messages=messages,
)
# The model asked to use a tool
if response.stop_reason == "tool_use":
tool_call = next(b for b in response.content if b.type == "tool_use")
result = get_order_status(**tool_call.input)
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_call.id,
"content": str(result),
}],
})
final = client.messages.create(
model="claude-sonnet-4-6", max_tokens=400, tools=tools, messages=messages,
)
print(final.content[0].text)What belongs in a tool
Put anything the model cannot do reliably from memory behind a tool: live data (orders, weather, prices), exact computation, and actions that change the world (send an email, create a record). Keep reasoning and language tasks in the prompt. A good rule: if a wrong answer is costly and a real system already knows the right one, expose that system as a tool.
Quick recap
- Tool use lets the model call your functions with structured arguments; you run them.
- Each tool needs a clear name, description, and input schema.
- The loop is request, execute, return result, continue.
- Use tools for live data, exact math, and real-world actions; keep reasoning in the prompt.
- Treat tool arguments as untrusted and guard destructive actions.