← Blog

Claude API Tool Use With Multiple Tools: A Guide

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

Can Claude use multiple tools in one request?

Yes. The Claude API lets you register several tool definitions in a single request, and the model decides which one (or several, in sequence or in parallel) it needs to answer the user's query. You don't call a different endpoint per tool — you pass an array of tool schemas in the tools parameter, and Claude returns tool_use content blocks telling you which tool it picked and with what arguments.

The practical challenge isn't registering the tools — that's just an array. It's handling the response correctly: knowing when Claude wants to call more than one tool before replying, matching results back to the right tool_use_id, and deciding whether to let Claude call tools in parallel or force it to use (or avoid) a specific one. This guide walks through all of that with working examples.

Defining multiple tools in a single request

Each tool needs a name, a description, and an input_schema. You can pass as many as you need — there's no hard cap on the array length, though very large tool sets can hurt routing accuracy, so keep descriptions tight and avoid near-duplicate tools.

{
  "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"]
      }
    },
    {
      "name": "get_stock_price",
      "description": "Get the latest stock price for a ticker symbol",
      "input_schema": {
        "type": "object",
        "properties": {
          "ticker": { "type": "string" }
        },
        "required": ["ticker"]
      }
    }
  ],
  "messages": [
    { "role": "user", "content": "What's the weather in Berlin and the current price of AAPL?" }
  ]
}

Given a prompt like this, Claude typically responds with two tool_use blocks in the same message — one for get_weather, one for get_stock_price — because both pieces of information are needed and neither depends on the other.

Handling parallel tool calls

When Claude decides it needs more than one tool at once, the response content array contains multiple tool_use blocks, each with its own id, name, and input. You must execute all of them and return results for each before continuing the conversation.

const response = await client.messages.create({
  model: "claude-sonnet-4-5",
  max_tokens: 1024,
  tools: myTools,
  messages,
});

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

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

messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: toolResults });

Two details trip people up here:

Multi-turn tool use vs. parallel tool use

These are two different things that often get conflated:

An example of sequential use: "Find the CEO of the company behind ticker AAPL and tell me their age." Claude might first call get_company_info, read the CEO's name from the result, then call get_person_age with that name. You can't predict this chain in advance — your code just needs to keep looping: send messages, check for tool_use blocks, execute, append results, repeat, until Claude returns a plain text response with no tool calls.

while (true) {
  const response = await client.messages.create({ model, max_tokens, tools, messages });
  messages.push({ role: "assistant", content: response.content });

  const toolUses = response.content.filter(b => b.type === "tool_use");
  if (toolUses.length === 0) break; // final answer reached

  const results = await Promise.all(toolUses.map(executeTool));
  messages.push({ role: "user", content: results });
}

Controlling which tools Claude can pick

The tool_choice parameter gives you three modes:

For most multi-tool setups, auto is correct — it's what enables the parallel-call behavior shown above. Forcing a single tool disables that flexibility for the current turn.

Managing tool execution behind one API

Running multiple tools reliably means handling retries, timeouts, and consistent error formatting across every tool in your set — and doing it the same way across every service that calls Claude. If you're exposing Claude-backed features to other apps or teammates, it's worth centralizing that behind a single HTTPS API rather than duplicating the request/response loop in every client.

SubToAPI turns your existing Claude access into exactly that: application API keys (sub_live_...), streaming, and tool-use support in one place, so your tool-calling logic lives in one spot instead of being copy-pasted into every service. See the tool use docs for request/response shapes, or start with the quickstart. Plans start at the Solo tier, and you can try it with a free trial via signup.

questions

Can Claude call two unrelated tools in the same response? Yes — if the user's request requires independent pieces of information, Claude returns multiple tool_use blocks in one message. You execute all of them and return a matching tool_result for each tool_use_id.

What happens if I don't return a result for every tool_use block? The next API call will likely fail or produce inconsistent behavior, since Claude expects a tool_result for every tool_use_id it generated. Always return a result, even an error message, for each call.

How do I stop Claude from using a specific tool? Remove it from the tools array for that request, or use tool_choice to force a different tool. There's no per-call "exclude this tool" flag — exclusion happens at the schema level.

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 →