Claude Tool Use Limit for This Turn: What It Means
When you see a message about a "tool use limit for this turn," it usually means Claude stopped mid-conversation because it hit the maximum number of tool calls (or output tokens) it's allowed to make in a single response cycle, before handing control back to your application. This isn't a subscription cap or a rate limit — it's a per-turn boundary built into how the API's agentic tool-use loop works, and it shows up in the stop_reason field of the response.
The short answer: if stop_reason comes back as tool_use, Claude isn't done — it's asking you to execute the tool(s) it requested and send the results back so it can continue. If you're seeing truncated or cut-off tool calls, the real cause is almost always max_tokens being too low for the response, not a hidden "tool limit" separate from that. There is no fixed number like "5 tools per turn" documented anywhere — the constraint is token budget and how many tool_use blocks fit inside it.
How the tool-use turn actually works
Each time you call the Messages API with tools defined, Claude can respond with one of three general shapes:
- Plain text with
stop_reason: "end_turn"— no tools needed, conversation continues normally. - One or more
tool_usecontent blocks withstop_reason: "tool_use"— Claude wants you to run something and return the result. - A response cut short by
stop_reason: "max_tokens"— the model ran out of room before finishing, which can happen mid-tool-call ifmax_tokensis set too low.
The "limit for this turn" people search for is almost always that third case, or confusion about the fact that Claude can request multiple tools in a single turn but then stops and waits for you to return results before doing anything else. It doesn't keep calling tools indefinitely inside one response — it pauses, you execute, you send results back as a new user turn, and the loop continues.
{
"stop_reason": "tool_use",
"content": [
{ "type": "text", "text": "Let me check the weather." },
{ "type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": { "city": "Lisbon" } }
]
}
Your job is to execute get_weather, then send a follow-up message containing a tool_result block with that same id. That's the entire mechanism — there's no separate quota counter for "tool calls per turn" beyond normal token limits.
Why responses get cut off mid-tool-call
If Claude's tool_use block looks incomplete — truncated JSON in input, or the response just stops — check these first:
max_tokensis too low. Tool schemas and multi-step reasoning consume tokens just like text. Bump it up (2048–4096 is a safe starting point for tool-heavy tasks).- Too many tools defined at once. A huge
toolsarray with verbose descriptions eats into your context budget before generation even starts. - You're not looping correctly. Some implementations treat
tool_useas an error and give up instead of feeding the result back — which looks like Claude "hit a limit" when really the conversation just needs another round trip.
async function runWithTools(messages, tools) {
let response = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 4096,
tools,
messages,
});
while (response.stop_reason === "tool_use") {
const toolResults = [];
for (const block of response.content) {
if (block.type === "tool_use") {
const result = await executeTool(block.name, block.input);
toolResults.push({
type: "tool_result",
tool_use_id: block.id,
content: JSON.stringify(result),
});
}
}
messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: toolResults });
response = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 4096,
tools,
messages,
});
}
return response;
}
Setting your own safety limit
Because Claude will keep requesting tools turn after turn until it's satisfied (or you cap it), you should always add your own ceiling — otherwise a stuck agent loop can burn tokens indefinitely.
const MAX_TURNS = 8;
let turns = 0;
while (response.stop_reason === "tool_use" && turns < MAX_TURNS) {
turns++;
// ...execute tools, append results, call again
}
if (turns === MAX_TURNS) {
console.warn("Hit local turn cap — inspect the loop before retrying.");
}
This is good practice regardless of provider: bound your agentic loops, log every tool call, and alert on unusually long chains. It also protects your budget — every turn is a full API call with its own token cost.
If you're running Claude-based tools behind an API for a team or product, tracking exactly how many turns and tokens each agentic loop consumes matters for cost control. SubToAPI sits between your app and Claude with application-scoped sub_live_... keys, so you can see per-key usage across tool-heavy workflows instead of guessing from a single shared account. The tool use docs cover the exact request/response shape for tool_result blocks, and the streaming docs show how to handle tool_use blocks that arrive incrementally over SSE.
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 4096,
"tools": [{"name": "get_weather", "input_schema": {...}}],
"messages": [{"role": "user", "content": "Weather in Lisbon?"}]
}'
The response format and stop_reason behavior are identical to calling Claude directly, so any loop you already built will work without changes — see the quickstart if you're setting this up for the first time.
questions
Is there a hard limit on how many tools Claude can call in one turn? No fixed number is enforced — the practical limit is your max_tokens budget and context window. A single turn can include multiple tool_use blocks, but generation stops once tokens run out or Claude decides it has enough information.
Why does my tool call look truncated? This almost always means max_tokens was set too low for the response. Increase it, especially when tool schemas or expected outputs are large, and check stop_reason — "max_tokens" confirms truncation versus "tool_use" which is a normal pause waiting for results.
Do I need to build my own retry logic for tool use? Yes. The API pauses after a tool_use response and expects you to send back tool_result blocks in a new message. There's no automatic continuation, so your application needs a loop (with its own turn cap) to keep the conversation moving.