Claude Tool Use for Multi-Step Workflows: A Guide
Claude's tool use (function calling) lets the model decide when to call external functions, read their results, and decide what to do next. A "multi-step workflow" is any task where one tool call isn't enough — Claude needs to call a tool, look at the result, maybe call another tool, and keep going until it has enough information to answer or complete an action. Think: search a database, then fetch a record, then update it, then send a confirmation.
The core challenge isn't getting Claude to call one tool correctly — that part is well documented. It's building the loop around Claude that keeps state, feeds results back in the right format, decides when to stop, and handles the failure cases that show up once you chain three or four calls together. This article covers how that loop should be structured, what usually goes wrong, and how to keep it reliable in production.
How Claude's tool use loop actually works
Every multi-step workflow with Claude follows the same pattern:
- You send a message with a list of available
toolsand the conversation so far. - Claude replies with either a text answer, or a
tool_usecontent block (sometimes several in one turn). - Your code executes the requested tool(s) and sends the results back as
tool_resultblocks in a new user message. - Claude reads the results and either calls another tool or produces a final answer.
You repeat step 3–4 until Claude stops requesting tools. There is no built-in "run until done" mode — your application code owns the loop. That's the part people underestimate: Claude doesn't execute anything itself, it only requests execution, so the reliability of a multi-step workflow depends almost entirely on how well you've built the harness around it.
A minimal loop looks like this:
let messages = [{ role: "user", content: userPrompt }];
while (true) {
const response = await client.messages.create({
model: "claude-opus-4-5",
max_tokens: 1024,
tools,
messages,
});
messages.push({ role: "assistant", content: response.content });
const toolUses = response.content.filter(b => b.type === "tool_use");
if (toolUses.length === 0) break; // final answer, stop looping
const toolResults = await Promise.all(
toolUses.map(async (block) => ({
type: "tool_result",
tool_use_id: block.id,
content: await runTool(block.name, block.input),
}))
);
messages.push({ role: "user", content: toolResults });
}
This structure works whether you're calling Anthropic directly or through SubToAPI's /v1/messages endpoint — the request/response shape for tool use is the same either way, so existing agent code doesn't need rewriting. See /docs/tools and /docs/messages for the exact payload format.
Designing tools for chaining, not just single calls
Multi-step workflows fail more often because of tool design than model behavior. A few practices that make chaining reliable:
- Return structured, minimal results. If a tool returns a huge JSON blob, Claude has to parse more context on every subsequent turn, which increases cost and the chance of misreading a field. Return only what the next step needs.
- Make tool names and descriptions unambiguous. If
get_userandget_accountoverlap in purpose, Claude will sometimes pick the wrong one mid-chain, and the error only surfaces two steps later. - Include IDs Claude can pass forward. If step one returns an
order_id, make sure step two's tool schema explicitly asks fororder_idas input — don't rely on Claude inferring it from free text. - Design for partial failure. A tool result should be able to say "not found" or "invalid input" as content, not throw. Claude can reason about a structured error and try a different tool or ask a clarifying question — it can't reason about your server crashing.
Handling state and stopping conditions
The two things that break multi-step workflows in production are unbounded loops and lost context.
Unbounded loops happen when Claude keeps calling tools without converging, usually because a tool result doesn't give it what it needs to decide it's done. Always cap the loop with a max iteration count (5–10 is reasonable for most workflows) and treat hitting the cap as a failure state to log and investigate, not silently truncate.
Lost context happens when the conversation grows past a useful length and earlier tool results fall out of relevance, or you're trimming history to save tokens and cut something Claude still needed. For workflows with many steps, consider summarizing intermediate results into a compact running state object that you pass back explicitly, rather than relying on Claude to re-derive it from a long transcript.
A practical middle ground: after each tool result, check if response.stop_reason is end_turn (Claude is done) versus tool_use (it wants to continue). Log both the stop reason and iteration count per workflow run — this is the single most useful piece of debugging data when a workflow doesn't behave as expected.
Parallel vs sequential tool calls
Claude can request multiple tool calls in a single turn when they're independent — for example, fetching weather for three cities at once. Your loop should execute these concurrently and return all results together in one tool_result batch, matched by tool_use_id. Don't force sequential execution of independent calls; it adds latency for no benefit and doesn't change correctness.
Sequential steps (where step two depends on step one's output) can't be parallelized — that dependency is exactly what makes it a multi-step workflow rather than a single batch of calls.
Monitoring workflows in production
Once a workflow is live, you want visibility into how many turns each run takes, which tools get called most, and where failures cluster. This is where per-key usage data helps: if you're running these workflows through SubToAPI, each sub_live_... key gives you usage metadata per request in the dashboard, so you can see token and call volume per workflow or per customer without building your own logging layer from scratch. Combined with streaming (see /docs/streaming) you can also surface intermediate tool calls to users in real time instead of showing a blank loading state during a five-step chain.
If you're just getting a tool-use loop working for the first time, start with /docs/quickstart and a single tool before adding chaining logic — get the request/response cycle right, then extend to multiple steps.
questions
Do I need a special API mode for multi-step tool use? No. Multi-step workflows use the same /v1/messages endpoint and tools parameter as single-call tool use. The multi-step behavior comes from your application loop re-sending tool results, not from a different API mode.
How many tool-call steps can a workflow have? There's no hard limit from the API, but practically you should cap iterations (5–10 is typical) to avoid unbounded loops from a tool that never gives Claude enough to finish.
Can Claude call two tools at once in a multi-step workflow? Yes, when the calls are independent Claude can request multiple tool_use blocks in one turn. Execute them concurrently and return all results in a single batch keyed by tool_use_id.