← Blog

Claude API Tool Use: Parallel Calls Example

2026-10-05 · 4 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 making you round-trip one tool call at a time. This is what people mean by "parallel tool calls" — Claude doesn't execute them concurrently itself, but it asks for several tool invocations at once, and your code is responsible for running them (ideally in parallel) and sending all the results back together.

This matters because sequential tool calling is slow: if a user asks "what's the weather in Paris and Tokyo, and convert 100 USD to EUR," a naive implementation makes three separate requests to Claude, each waiting on the last. With parallel tool use, Claude emits three tool_use blocks in one turn, you execute all three tools concurrently in your backend, and you send one message back with all three tool_result blocks. Below is a complete, working example.

How parallel tool calls actually work

The flow has four steps:

  1. You send a message with tools defined and the user's request.
  2. Claude responds with stop_reason: "tool_use" and a content array that may contain more than one tool_use block.
  3. You execute every tool call (in parallel, using Promise.all or similar), matching each result to its tool_use_id.
  4. You send a new message back with a user role containing one tool_result block per tool call, in any order — Claude matches them by ID, not position.

Claude decides on its own whether a request needs parallel calls. You can't force it, but you increase the odds by defining independent, narrowly-scoped tools and phrasing prompts that clearly require multiple pieces of information.

Full example: weather + currency lookups

Tool definitions:

[
  {
    "name": "get_weather",
    "description": "Get current weather for a city",
    "input_schema": {
      "type": "object",
      "properties": {
        "city": { "type": "string" }
      },
      "required": ["city"]
    }
  },
  {
    "name": "convert_currency",
    "description": "Convert an amount from one currency to another",
    "input_schema": {
      "type": "object",
      "properties": {
        "amount": { "type": "number" },
        "from": { "type": "string" },
        "to": { "type": "string" }
      },
      "required": ["amount", "from", "to"]
    }
  }
]

Initial request:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "tools": [...],
    "messages": [
      {"role": "user", "content": "What is the weather in Paris and Tokyo, and convert 100 USD to EUR?"}
    ]
  }'

Claude's response will have stop_reason: "tool_use" and a content array like this:

{
  "content": [
    { "type": "text", "text": "I'll check both cities' weather and do the conversion." },
    { "type": "tool_use", "id": "toolu_01A", "name": "get_weather", "input": { "city": "Paris" } },
    { "type": "tool_use", "id": "toolu_01B", "name": "get_weather", "input": { "city": "Tokyo" } },
    { "type": "tool_use", "id": "toolu_01C", "name": "convert_currency", "input": { "amount": 100, "from": "USD", "to": "EUR" } }
  ],
  "stop_reason": "tool_use"
}

Executing the calls in parallel

const toolUses = response.content.filter(block => block.type === "tool_use");

const results = await Promise.all(
  toolUses.map(async (block) => {
    const output = await runTool(block.name, block.input); // your dispatcher
    return {
      type: "tool_result",
      tool_use_id: block.id,
      content: JSON.stringify(output)
    };
  })
);

Sending results back

{
  "role": "user",
  "content": [
    { "type": "tool_result", "tool_use_id": "toolu_01A", "content": "{\"temp_c\": 14, \"condition\": \"cloudy\"}" },
    { "type": "tool_result", "tool_use_id": "toolu_01B", "content": "{\"temp_c\": 22, \"condition\": \"sunny\"}" },
    { "type": "tool_result", "tool_use_id": "toolu_01C", "content": "{\"converted\": 92.1, \"currency\": \"EUR\"}" }
  ]
}

Append this as a new message after Claude's tool_use message and send the full conversation history again. Claude will then produce a final text response combining all three results.

Common mistakes

Where this fits with SubToAPI

If you're exposing Claude through your own product's backend — say, a support bot that calls internal tools, or an agent that hits multiple APIs per user query — you need the same tool_use and tool_result contract regardless of how you provision access. SubToAPI turns your existing Claude access into an HTTPS API with application keys (sub_live_...), so you can call /v1/messages with full tool-use support, including parallel tool calls, without managing separate billing per team member. See the tools documentation and the messages API reference for the exact request/response shape, or check streaming if you want to see tool_use blocks arrive incrementally. Plans start at the pricing page, and you can try it from signup.

Questions

Can I force Claude to always make parallel tool calls? No. Claude decides based on the prompt and tool definitions whether multiple independent calls are needed. You can nudge it by writing prompts that clearly require several distinct pieces of information and keeping tools narrowly scoped.

Do parallel tool calls run concurrently on Anthropic's side? No — Claude returns multiple tool_use requests in one response, but the actual execution happens in your code. Concurrency depends entirely on how you dispatch the calls (e.g., Promise.all).

What happens if I only return some of the tool_result blocks? Claude may stall, ask for the missing result, or produce an incomplete answer. Always return exactly one tool_result per tool_use_id from the previous turn, including error results for failed calls.

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 →