Parallel Tool Calls: Running Agent Tools Concurrently
When a request needs several independent lookups ("compare the weather in Delhi, Mumbai and Bengaluru"), the model can return multiple tool_use blocks in a single response. Running them one after another wastes time.
Execute in parallel
const toolUses = response.content.filter(
(b): b is Anthropic.ToolUseBlock => b.type === 'tool_use'
);
const results: Anthropic.ToolResultBlockParam[] = await Promise.all(
toolUses.map(async (tu) => {
try {
return { type: 'tool_result', tool_use_id: tu.id, content: await runTool(tu.name, tu.input) };
} catch (err) {
return { type: 'tool_result', tool_use_id: tu.id, content: String(err), is_error: true };
}
})
);
messages.push({ role: 'assistant', content: response.content });
messages.push({ role: 'user', content: results }); // ALL results in ONE message
Python with asyncio
import asyncio, json
async def run_all(tool_uses):
async def one(tu):
try:
return {"type": "tool_result", "tool_use_id": tu.id,
"content": json.dumps(await run_tool(tu.name, tu.input))}
except Exception as e:
return {"type": "tool_result", "tool_use_id": tu.id,
"content": str(e), "is_error": True}
return await asyncio.gather(*(one(tu) for tu in tool_uses))
Important rules
- Send every result for one turn in a single user message. Splitting them across several messages teaches the model to stop making parallel calls.
- Don't drop failed calls; return them with
is_error: true. - Order doesn't matter: results are matched by
tool_use_id.
When to turn it off
If tools have side effects that must happen in order, set disable_parallel_tool_use: true in tool_choice, so the model makes at most one call per turn:
tool_choice: { type: 'auto', disable_parallel_tool_use: true }
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.