
Cut Agent Round-Trips in Half: Parallel Tool Calls in the Claude API
Chris Harper
2 min read
Jul 22, 2026 · 12:05 UTC
TL;DR: Claude returns multiple tool_use blocks in one turn — run them all with asyncio.gather, send back all tool_results in a single user message, and your agent loop makes far fewer API calls.
Most agentic loops treat tool calls as serial: Claude responds → you call one tool → you reply → Claude responds again. But Claude's API can return multiple tool_use blocks in a single assistant message. When you process them in parallel and fold all results into one reply turn, independent lookups that previously cost three round-trips cost one. For read-heavy agent work — fetching docs, querying APIs, running parallel checks — this is an easy 2–4× latency win.
How it works
Claude's response has stop_reason = "tool_use" and its content is a list. When it decides to parallelize, you'll see several tool_use blocks — each with its own id, name, and input:
import asyncio
import anthropic
client = anthropic.Anthropic()
async def run_tool(block) -> dict:
result = await YOUR_TOOL_REGISTRY[block.name](**block.input)
return {
"type": "tool_result",
"tool_use_id": block.id,
"content": str(result),
}
async def agent_loop(messages: list) -> str:
while True:
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=4096,
tools=TOOLS,
messages=messages,
)
if response.stop_reason != "tool_use":
return response.content[0].text
tool_blocks = [b for b in response.content if b.type == "tool_use"]
# Run all tool calls concurrently
results = await asyncio.gather(*[run_tool(b) for b in tool_blocks])
# Critical: all tool_result blocks go in ONE user message
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": list(results)})
The critical formatting rule
All tool_result entries must go in a single user message — one entry per tool_use id. If you reply with them in separate messages the API will error or Claude will lose track of which result maps to which call.
When to parallelize vs. serialize
- ✅ Parallel: independent read-only lookups, fetching multiple docs, calling separate APIs
- ⚠️ Sequential: writes that build on each other, tools with shared state, file edits that must happen in order
Claude naturally clusters independent calls together — your job is to handle the multiple tool_use blocks in the response rather than assuming there's always one.
Sources: Parallel Tool Use — Claude Platform Docs · How Tool Use Works — Claude Platform Docs