How to use Claude's tool use (function calling) API. Define tools in JSON schema, handle tool_use responses, and close the loop in Python and JavaScript.
Claude's tool use API (also called function calling) lets Claude decide when to call an external function, construct the correct arguments, and integrate the result into its response. This page walks through the complete request-response loop in Python and TypeScript.
tool_use instead of text.messages turn.import anthropic, json
client = anthropic.Anthropic()
tools = [
{
"name": "get_weather",
"description": "Return current temperature and conditions for a city.",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g. London"}
},
"required": ["city"]
}
}
]
messages = [{"role": "user", "content": "What is the weather in Tokyo?"}]
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=messages
)
if response.stop_reason == "tool_use":
tool_block = next(b for b in response.content if b.type == "tool_use")
city = tool_block.input["city"]
# Call your real function here
weather_result = {"city": city, "temp_c": 22, "conditions": "Sunny"}
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_block.id,
"content": json.dumps(weather_result)
}]
})
final = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=messages
)
print(final.content[0].text)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const tools: Anthropic.Tool[] = [{
name: "get_weather",
description: "Return current temperature and conditions for a city.",
input_schema: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"]
}
}];
let messages: Anthropic.MessageParam[] = [
{ role: "user", content: "What is the weather in Tokyo?" }
];
const r1 = await client.messages.create({
model: "claude-sonnet-4-6", max_tokens: 1024, tools, messages
});
if (r1.stop_reason === "tool_use") {
const toolBlock = r1.content.find(b => b.type === "tool_use") as Anthropic.ToolUseBlock;
const weatherResult = { city: toolBlock.input.city, temp_c: 22, conditions: "Sunny" };
messages = [
...messages,
{ role: "assistant", content: r1.content },
{ role: "user", content: [{ type: "tool_result", tool_use_id: toolBlock.id, content: JSON.stringify(weatherResult) }] }
];
const r2 = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 1024, tools, messages });
console.log((r2.content[0] as Anthropic.TextBlock).text);
}
| tool_choice | Behaviour | When to use |
|---|---|---|
auto (default) | Claude picks whether to call a tool or respond in text | Most cases |
{"type":"any"} | Claude must call at least one tool | Forcing structured extraction |
{"type":"tool","name":"..."} | Claude must call this specific tool | Guaranteed JSON schema output |
Tool definitions and tool_result messages count as input tokens. A complex tool schema with 5 tools adds ~500–1,000 input tokens per request. Use the Claude Cost Calculator to model the incremental cost, and the Prompt-Pricing Recommender to decide whether Haiku or Sonnet is right for your tool-use workflow.
stop_reason: "tool_use", you must return a tool_result message or the next request will error.response.content as an assistant message before adding the user tool_result.