Claude API Tool Use for Multi-Step Reasoning
Why tool use matters for multi-step reasoning
When developers search for "Claude API tool use multi step reasoning," they're usually trying to solve the same problem: a single prompt isn't enough. The task requires Claude to look something up, think about the result, maybe call another function, and only then produce a final answer. This is exactly what Claude's tool use (function calling) feature is designed for — it lets the model pause mid-reasoning, request external data or computation, and incorporate the result before continuing.
The short answer is: you build a loop. You send a message, Claude either answers directly or returns a tool_use block, you execute that tool, send the result back as a tool_result, and repeat until Claude returns a final text response with no further tool calls. This article walks through that loop in detail, with code, common failure modes, and patterns for keeping multi-step chains reliable.
The basic tool-use loop
Multi-step reasoning with tools isn't a single API call — it's a conversation. Each turn adds to the message history, and Claude decides whether it has enough information to answer or needs another tool call.
const tools = [
{
name: "get_stock_price",
description: "Get the current price of a stock by ticker symbol",
input_schema: {
type: "object",
properties: { ticker: { type: "string" } },
required: ["ticker"]
}
},
{
name: "calculate",
description: "Evaluate a basic math expression",
input_schema: {
type: "object",
properties: { expression: { type: "string" } },
required: ["expression"]
}
}
];
let messages = [
{ role: "user", content: "If AAPL goes up 8%, what's the new price?" }
];
while (true) {
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"content-type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 1024,
tools,
messages
})
}).then(r => r.json());
messages.push({ role: "assistant", content: response.content });
const toolCalls = response.content.filter(b => b.type === "tool_use");
if (toolCalls.length === 0) {
console.log(response.content.find(b => b.type === "text")?.text);
break;
}
const toolResults = [];
for (const call of toolCalls) {
const result = await runTool(call.name, call.input);
toolResults.push({
type: "tool_result",
tool_use_id: call.id,
content: JSON.stringify(result)
});
}
messages.push({ role: "user", content: toolResults });
}
Notice the pattern: each loop iteration is a full round trip, and the entire history accumulates. Claude doesn't just see the last tool result — it sees the whole chain, which is what allows genuine multi-step reasoning rather than isolated lookups. If you're new to this feature, the tools documentation covers schema definitions in more depth, and the messages endpoint docs explain the content block structure that tool_use and tool_result build on.
Designing tools for multi-step chains
Tool design directly affects how well Claude chains steps together. A few practical rules:
- Keep tools narrow and composable. A
search_databasetool that returns raw rows is more reusable across reasoning steps than one gianthandle_everythingtool. Claude reasons better when it can combine small, predictable operations. - Return structured data, not prose. Tool results should be JSON the model can parse and reference, not a paragraph summary. This reduces hallucinated details in later steps.
- Describe failure cases in the schema description. If a lookup can return "not found," say so. Claude will handle that branch in its next step instead of assuming success.
- Cap the number of parallel tool calls you expect. Claude can request multiple tools in one turn. Design your execution code to handle that (as in the loop above) rather than assuming one call per turn.
Handling errors inside the chain
A common mistake is treating tool failures as exceptions that break the loop. Instead, feed the error back to Claude as a tool_result with an error flag:
toolResults.push({
type: "tool_result",
tool_use_id: call.id,
content: JSON.stringify({ error: "Ticker not found" }),
is_error: true
});
Claude will typically adjust its next step — asking a clarifying question, trying an alternative tool, or explaining the limitation to the user — rather than silently producing a wrong answer. This is one of the biggest reliability gains in multi-step tool use: the model is reasoning over the error, not just the happy path.
Controlling loop length and cost
Multi-step chains can run longer than expected if a tool keeps returning ambiguous results. Two practical guards:
- Set a max iteration count in your loop (5–8 is usually generous) and break with a fallback message if exceeded.
- Track token usage per turn. Each round trip resends the full message history, so token cost grows with chain length. If you're running this at scale, routing requests through SubToAPI gives you per-request usage metadata so you can see exactly how much a multi-step chain costs before it becomes a surprise on your bill.
Streaming and tool use together
If your application needs to show progress during a long reasoning chain (e.g., "Looking up stock price…" then "Calculating…"), you can combine streaming with tool use. Claude streams text and tool-use blocks as they're generated, so your UI can react to each step rather than waiting for the full chain to finish. Details on event types and partial JSON handling for tool inputs are in the streaming docs.
Getting started
If you're setting this up for the first time, the quickstart guide walks through authentication and your first request, and signup includes a free trial so you can test a multi-step tool chain against real API responses before committing to a plan.
questions
Does Claude decide on its own when to call a tool, or do I have to force it? By default Claude decides based on the conversation and the tool descriptions you provide. You can also force a specific tool choice via the tool_choice parameter if you need deterministic behavior for a given step.
How many steps can a multi-step reasoning chain have? There's no hard limit from the API, but practically you should cap loop iterations in your own code (5–8 is typical) to avoid runaway costs or infinite loops caused by ambiguous tool results.
Can Claude call multiple tools in a single turn? Yes. A single response can include several tool_use blocks if the model determines it needs multiple pieces of information before continuing, so your execution code should loop over all tool calls in a turn, not just the first one.