← Blog

Claude API Parallel Tool Calling Example (With Code)

2026-10-22 · 5 min read · SubToAPI Team

When Claude decides it needs more than one tool to answer a request, it can return multiple tool_use blocks in a single response instead of asking for them one at a time. This is parallel tool calling, and it's how you avoid round-tripping to the model for every individual function call. Instead of "call tool A, wait, call tool B, wait, call tool C," Claude says "I need A, B, and C" in one message, and your code executes them together.

This matters for anything that fans out to multiple data sources: checking weather for three cities, pulling stock prices for a watchlist, querying a database and a search API at the same time. Below is a full working example of how parallel tool calling looks in practice, what the request/response shapes are, and how to handle execution and results correctly.

How parallel tool calling works

The flow is the same as single tool use, with one difference: the assistant's response can contain an array of tool_use content blocks instead of just one. Your job is to:

  1. Send a message with tools defined and a user prompt that naturally requires multiple tool calls.
  2. Check the response for stop_reason: "tool_use" and iterate over all tool_use blocks, not just the first.
  3. Execute each tool (concurrently if they're independent, like async HTTP calls).
  4. Return all results as tool_result blocks in a single follow-up user message, matched by tool_use_id.
  5. Send that back to continue the conversation.

Claude decides on its own whether a task needs one tool call or several — you don't need to request parallel behavior explicitly, though your tool descriptions and prompt structure influence how aggressively it batches calls.

Example: weather for multiple cities

Here's a minimal tool definition and the kind of response you'd get back when a user asks about several cities at once.

{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "tools": [
    {
      "name": "get_weather",
      "description": "Get current weather for a city",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": { "type": "string" }
        },
        "required": ["city"]
      }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "What's the weather in Berlin, Tokyo, and São Paulo right now?"
    }
  ]
}

A parallel tool call response looks like this — note the three separate tool_use blocks in one content array:

{
  "stop_reason": "tool_use",
  "content": [
    { "type": "text", "text": "I'll check the weather in all three cities." },
    { "type": "tool_use", "id": "toolu_01A", "name": "get_weather", "input": { "city": "Berlin" } },
    { "type": "tool_use", "id": "toolu_01B", "name": "get_weather", "input": { "city": "Tokyo" } },
    { "type": "tool_use", "id": "toolu_01C", "name": "get_weather", "input": { "city": "São Paulo" } }
  ]
}

Executing multiple tool calls concurrently

The key implementation detail is running all requested tools concurrently where possible, then packaging every result into the same follow-up message:

const toolUseBlocks = response.content.filter(b => b.type === "tool_use");

const results = await Promise.all(
  toolUseBlocks.map(async (block) => {
    const data = await getWeather(block.input.city);
    return {
      type: "tool_result",
      tool_use_id: block.id,
      content: JSON.stringify(data)
    };
  })
);

// Send all results back in one message
const followUp = {
  model: "claude-sonnet-4-5",
  max_tokens: 1024,
  tools: [/* same tool definitions */],
  messages: [
    ...previousMessages,
    { role: "assistant", content: response.content },
    { role: "user", content: results }
  ]
};

A common mistake is sending each tool_result back as a separate API call. Don't — Claude expects all results for the batch in a single user message, matched by tool_use_id. Sending them one at a time breaks the conversation state and causes errors or confused follow-up responses.

Using the same pattern through SubToAPI

If you're already calling Claude through SubToAPI, parallel tool calling works identically — it's the same tools schema and the same tool_use/tool_result lifecycle, just proxied through your sub_live_... application key instead of a raw Anthropic key. That means you get the same multi-tool response shapes, plus per-key usage metadata so you can see which application or team is driving the most tool-heavy requests.

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": 1024,
    "tools": [{ "name": "get_weather", "description": "...", "input_schema": {} }],
    "messages": [{ "role": "user", "content": "Weather in Berlin and Tokyo?" }]
  }'

This is useful when multiple engineers or services share one Claude subscription — each gets a scoped API key, and tool-heavy workloads (which can spike token usage fast) are visible per key instead of buried in one shared bill. See the tool use docs and quickstart for the full request format, or check pricing if you're evaluating plans for a team.

Practical tips for reliable parallel calls

Questions

Does Claude always call tools in parallel when multiple are needed? No. Claude decides based on whether tasks are independent. Sequential, dependent tasks (where output of one feeds into another) will still come back one tool call at a time across multiple turns.

Can I force Claude to only use one tool at a time? Yes — if your workflow requires sequential execution, say so explicitly in your system prompt or tool descriptions, or structure the tools so later calls depend on earlier outputs.

What happens if I don't return all tool_result blocks for a batch? The conversation will error or stall — Claude expects a matching tool_result for every tool_use_id it issued in that turn before it can continue.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →