CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
Claude Can Call Multiple Tools in One Turn — Process Them in Parallel With asyncio.gather

Claude Can Call Multiple Tools in One Turn — Process Them in Parallel With asyncio.gather

Chris Harper

2 min read

Aug 3, 2026 · 04:04 UTC

AI
Workflow
Agents
Best Practices

When Claude's response includes multiple tool_use blocks, running them with asyncio.gather instead of sequentially cuts your agent's wall time to the slowest single call — a one-function change to any client loop.

When you define multiple tools, Claude sometimes returns several tool_use blocks in a single turn — each an independent function call it wants to make simultaneously. Most client loops process them sequentially. That leaves latency on the table.

Anthropic's parallel tool use docs make this explicit: collect all blocks, execute them concurrently, then return all results together in a single user turn.

The pattern

import asyncio
import anthropic

client = anthropic.AsyncAnthropic()

async def run_tool(name: str, tool_input: dict) -> str:
    match name:
        case "search_web": return await web_search(tool_input["query"])
        case "read_file":  return await read_file(tool_input["path"])
        case "fetch_url":  return await fetch_url(tool_input["url"])
    raise ValueError(f"unknown tool: {name}")

async def agent_loop(messages: list, tools: list) -> str:
    while True:
        response = await client.messages.create(
            model="claude-sonnet-5-20261001",
            max_tokens=4096,
            tools=tools,
            messages=messages,
        )

        if response.stop_reason != "tool_use":
            return next(b.text for b in response.content if hasattr(b, "text"))

        tool_uses = [b for b in response.content if b.type == "tool_use"]

        # Run all tool calls concurrently, not sequentially
        results = await asyncio.gather(
            *[run_tool(tu.name, tu.input) for tu in tool_uses]
        )

        # Return all results in one user turn
        messages.append({"role": "assistant", "content": response.content})
        messages.append({
            "role": "user",
            "content": [
                {"type": "tool_result", "tool_use_id": tu.id, "content": result}
                for tu, result in zip(tool_uses, results)
            ],
        })

Why it matters

A search + file read that each take 200 ms sequentially takes 400 ms. In parallel: 200 ms. The speedup compounds over agents that make many tool calls per turn.

One caveat: only parallelize independent operations. Tools with ordering requirements or shared side effects (write a file then read it; increment a counter twice) should run sequentially — extract those into a separate sequential pass.

Sources: Parallel Tool Use — Anthropic Platform Docs · Implementing Async Tool Execution — CodeSignal · Parallel Tool Execution with Claude — Medium