← Blog

Function Calling with Claude: A Complete Setup Guide

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

Function calling with Claude lets you give the model a set of tools — described as JSON schemas — that it can choose to invoke instead of just replying with text. Claude decides when a function call is appropriate, returns structured arguments matching your schema, and pauses so your code can run the actual function and send the result back. This is how you connect Claude to databases, internal APIs, calculators, search engines, or any system that needs precise, structured input rather than free-form prose.

The mechanics are the same regardless of which client you use: you send a list of tool definitions with your request, Claude responds with a tool_use block containing the function name and arguments, your application executes that function, and you send the result back as a tool_result so Claude can continue the conversation with that information in hand. This article walks through the full loop, common pitfalls, and how to keep it reliable in production.

How Claude's Tool Use Format Works

Each tool you define needs three things: a name, a description, and an input_schema written as JSON Schema. The description matters more than people expect — Claude uses it to decide whether to call the tool at all, not just how to fill in the arguments. Vague descriptions lead to missed calls or wrong tool selection when you have several similar tools.

{
  "name": "get_order_status",
  "description": "Look up the current status of a customer order by order ID. Use this whenever the user asks about an existing order.",
  "input_schema": {
    "type": "object",
    "properties": {
      "order_id": { "type": "string", "description": "The order ID, e.g. ORD-4821" }
    },
    "required": ["order_id"]
  }
}

When Claude decides to use this tool, the response contains a content block like:

{
  "type": "tool_use",
  "id": "toolu_01A2b3",
  "name": "get_order_status",
  "input": { "order_id": "ORD-4821" }
}

Your code executes the real lookup, then sends a follow-up message containing a tool_result block referencing that same id, with the output. Claude then produces a final natural-language answer incorporating the result. If Claude needs another tool call — say, checking inventory after confirming the order — it will emit another tool_use block instead of a final answer, and the loop repeats.

Building a Reliable Tool-Calling Loop

Most implementation bugs come from the surrounding loop, not from Claude's tool selection itself. A few things worth getting right from the start:

let messages = [{ role: "user", content: userInput }];

for (let i = 0; i < MAX_ROUNDS; i++) {
  const response = await callClaude(messages, tools);
  messages.push({ role: "assistant", content: response.content });

  if (response.stop_reason !== "tool_use") break;

  const toolResults = [];
  for (const block of response.content) {
    if (block.type === "tool_use") {
      const output = await runTool(block.name, block.input);
      toolResults.push({
        type: "tool_result",
        tool_use_id: block.id,
        content: JSON.stringify(output)
      });
    }
  }
  messages.push({ role: "user", content: toolResults });
}

This pattern works whether you're calling Claude directly or through a proxy layer — the tool-use protocol itself doesn't change.

Keeping Tool Definitions Tight

Function calling gets unreliable fast when tool sets grow sprawling. A few practices help:

Running Function Calling Through an API Key

If you're building on Claude through a subscription rather than a metered API account, you still need a stable way to issue application keys, stream responses, and see what tool calls are actually costing you in tokens. SubToAPI turns your existing Claude access into a standard HTTPS API — you get sub_live_... keys, streaming support, and full tool-use compatibility, so the same request format shown above works without changes. Usage metadata and team seats are handled in one dashboard, which is useful if more than one developer on your team needs to build against the same account.

Getting started takes the same shape as any other integration: create a key, point your requests at https://api.subtoapi.app/v1/messages, and pass your tools array exactly as documented. See the quickstart and the messages and tools reference pages for the exact request/response shapes, or check streaming if you want tool-use events delivered incrementally. Plans start at €9/month on the Solo tier, with team pricing on the pricing page and a free trial at signup.

Questions

Does Claude support parallel function calls in a single response? Yes. Claude can emit multiple tool_use blocks in one turn, and your code should execute all of them and return matching tool_result blocks before continuing the conversation.

What happens if Claude calls a function with invalid arguments? It usually won't if your input_schema is well-defined, but if it does, return a tool_result with is_error: true and a clear message — Claude will typically correct itself on the next call rather than failing outright.

Can I force Claude to always use a specific tool? Yes, most implementations support a tool_choice parameter to require a specific tool or force some tool use on a given turn, instead of leaving it to Claude's judgment.

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 →