Tool Calling Basics
Tool calling is how agents take action in the real world. You define tools as JSON schemas, Claude decides when to use them, and your code executes them. Here is the complete pattern with production code.
How Tool Calling Works
Tool calling is a three-step conversation between your code and Claude:
Tell Claude what tools exist using JSON schemas — name, description, and parameters.
Based on the user's request, Claude returns a tool_use block with the tool name and filled-in parameters.
You run the actual function, then send the result back to Claude as a tool_result message.
Step 1: Define Your Tools
A tool definition is a JSON schema that tells Claude what the tool does and what parameters it accepts. The better your description, the better Claude's tool selection:
tools = [
{
"name": "search_knowledge_base",
"description": "Search the company knowledge base for help articles. Use when the customer asks a question about how to use the product, troubleshoot an issue, or understand a feature.",
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query describing the customer's issue"
}
},
"required": ["query"]
}
},
{
"name": "lookup_customer",
"description": "Look up a customer's account details by email. Use when you need to check their plan, billing status, or account history.",
"input_schema": {
"type": "object",
"properties": {
"email": {
"type": "string",
"description": "Customer email address"
}
},
"required": ["email"]
}
},
{
"name": "create_ticket",
"description": "Create a support ticket for issues that need human follow-up. Use when the issue cannot be resolved automatically.",
"input_schema": {
"type": "object",
"properties": {
"subject": { "type": "string" },
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"]
},
"description": { "type": "string" }
},
"required": ["subject", "priority", "description"]
}
}
]
Claude uses the tool description to decide when to call it. Vague descriptions like "search stuff" lead to wrong tool selection. Be specific about what the tool does and when to use it.
Step 2: Claude Decides to Call a Tool
When you send a message with tools defined, Claude reads the user's request and decides if any tool would help. If so, it returns a tool_use content block:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[{
"role": "user",
"content": "I was charged twice for my Pro plan. My email is jane@acme.co"
}]
)
# Claude responds with a tool_use block:
# response.stop_reason = "tool_use"
# response.content = [
# TextBlock("Let me look up your account..."),
# ToolUseBlock(
# id="toolu_abc123",
# name="lookup_customer",
# input={"email": "jane@acme.co"}
# )
# ]
Claude extracted the email from the user's message and decided lookup_customer is the right tool. It filled in the parameters automatically.
Step 3: Execute and Return Results
Your code runs the actual tool, then sends the result back to Claude. Claude uses the result to continue reasoning:
def execute_tool(name, params):
if name == "lookup_customer":
return db.query("SELECT * FROM customers WHERE email = %s", params["email"])
elif name == "search_knowledge_base":
return kb.search(params["query"])
elif name == "create_ticket":
return tickets.create(**params)
# Get the tool use block from the response
tool_block = next(b for b in response.content if b.type == "tool_use")
result = execute_tool(tool_block.name, tool_block.input)
# Send the result back to Claude
follow_up = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "I was charged twice..."},
{"role": "assistant", "content": response.content},
{"role": "user", "content": [{
"type": "tool_result",
"tool_use_id": tool_block.id,
"content": json.dumps(result)
}]}
]
)
# Claude now has the customer data and can respond intelligently
print(follow_up.content[0].text)
# "I can see your account, Jane. You're on the Pro plan at $49/mo.
# I see two charges on March 15. Let me create a ticket for the
# billing team to refund the duplicate charge."
This lesson is for Pro members
Unlock all 520+ lessons across 52 courses with Academy Pro.
Already a member? Sign in to access your lessons.