Claude Tool Use: Multiple Tools Example That Works
When you give Claude more than one tool, two things change compared to a single-tool setup: Claude has to decide which tool (or tools) to call based on the user's message, and in some cases it will request several tool calls in a single turn. This article walks through a real multi-tool example — a weather tool and a calculator tool — showing the request, Claude's response, how to execute both calls, and how to send the results back correctly.
The short answer to "how do I use multiple tools with Claude" is: define each tool as a separate object in the tools array with its own name, description, and input_schema, send them all in the same request, then check stop_reason: "tool_use" and loop over every block in content with type: "tool_use" — not just the first one — because Claude can return more than one tool call per response.
Defining multiple tools in one request
Each tool is an independent schema. Claude reads the descriptions to decide which tool (if any) applies to the user's message.
{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "Get the current weather for a given city",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name" }
},
"required": ["city"]
}
},
{
"name": "calculate",
"description": "Evaluate a basic arithmetic expression",
"input_schema": {
"type": "object",
"properties": {
"expression": { "type": "string", "description": "e.g. 12 * 7" }
},
"required": ["expression"]
}
}
],
"messages": [
{
"role": "user",
"content": "What's the weather in Lisbon, and what is 340 * 12?"
}
]
}
Because the user's question needs both tools, Claude typically returns two tool_use blocks in one response rather than asking you to go back and forth twice.
What Claude's response looks like
{
"id": "msg_01abc",
"role": "assistant",
"stop_reason": "tool_use",
"content": [
{
"type": "text",
"text": "I'll check the weather and do the math."
},
{
"type": "tool_use",
"id": "toolu_01weather",
"name": "get_weather",
"input": { "city": "Lisbon" }
},
{
"type": "tool_use",
"id": "toolu_02calc",
"name": "calculate",
"input": { "expression": "340 * 12" }
}
]
}
Notice there's an optional text block before the tool calls, and then two distinct tool_use blocks each with their own id and name. Your code needs to handle both, in the order they appear, and keep track of each id — it's what links the result back to the specific call.
Executing the calls and sending results back
For each tool_use block, run your own matching function and return a tool_result with the same tool_use_id. If there are multiple tool calls, you send multiple tool_result blocks in a single follow-up user message — not separate requests.
const toolHandlers = {
get_weather: (input) => `18°C, partly cloudy in ${input.city}`,
calculate: (input) => String(eval(input.expression)) // demo only, don't eval in prod
};
const toolResults = response.content
.filter((block) => block.type === "tool_use")
.map((block) => ({
type: "tool_result",
tool_use_id: block.id,
content: toolHandlers[block.name](block.input)
}));
const followUp = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
tools: [...], // same tools array as before
messages: [
{ role: "user", content: "What's the weather in Lisbon, and what is 340 * 12?" },
{ role: "assistant", content: response.content },
{ role: "user", content: toolResults }
]
})
});
Claude then reads both results and produces a final natural-language answer combining them, something like: "It's 18°C and partly cloudy in Lisbon. 340 × 12 is 4,080."
Common mistakes with multiple tools
- Only reading the first
tool_useblock. If you loopcontent[0]instead of filtering by type, you'll silently drop the second tool call and get an incomplete answer. - Mismatched
tool_use_id. Eachtool_resultmust reference the exact id from the correspondingtool_useblock, in any order — but it must match. - Vague tool descriptions. If
get_weatherandcalculatehave overlapping or unclear descriptions, Claude may call the wrong one or call both unnecessarily. Be specific about what each tool does and doesn't handle. - Forgetting to resend the
toolsarray. The follow-up request needs the same tool definitions as the original call, or Claude loses context on what the tools do.
Running this through SubToAPI
If you're calling Claude from a product rather than a script, this exact flow — multiple tools, parallel tool_use blocks, result matching — works unchanged against SubToAPI's /v1/messages endpoint. You get a sub_live_... key, usage metadata per request, and team seats for sharing access, without managing Anthropic billing directly. See the tool use docs for the full schema reference, quickstart to get a key, or pricing for plan details.
questions
Can Claude call more than two tools in one response? Yes. There's no hard limit on how many tool_use blocks can appear in one response — it depends on how many distinct actions the model determines it needs to answer the request.
Does the order of tool calls in content matter? The order reflects the sequence Claude reasoned through them, but you can execute and return results in any order as long as each tool_result has the correct tool_use_id.
What if one of my tools doesn't apply to the user's message? Claude simply won't call it. Having extra tools defined doesn't force usage — it only picks the ones relevant to the current input based on the descriptions you provide.