← Blog

Claude Tool Use: A Function Calling Tutorial

2026-11-06 · 5 min read · SubToAPI Team

Claude tool use (also called function calling) lets Claude call functions in your codebase instead of just generating text. You describe the tools available — their names, purposes, and input schemas — and Claude decides when to invoke them, producing structured JSON arguments you execute on your side. This tutorial walks through the full request/response cycle so you can wire it into a real application.

If you're searching for how this actually works end to end, here's the short version: you send a request with a tools array, Claude replies with a tool_use block containing a function name and arguments, your code runs that function, and you send the result back in a follow-up message so Claude can continue the conversation. The rest of this guide covers each step in detail, with working code.

How Claude Tool Use Works

Tool use in Claude follows a loop, not a single call:

  1. You send a message with a list of tool definitions (name, description, JSON schema for inputs).
  2. Claude's response may include a tool_use content block instead of (or alongside) plain text, specifying which tool to call and with what arguments.
  3. Your application executes the actual function — hitting a database, calling an external API, running a calculation.
  4. You send the result back to Claude as a tool_result block in the next message.
  5. Claude incorporates the result and produces a final answer, or calls another tool if needed.

This loop is what makes Claude useful for agentic tasks: looking up live data, performing calculations it can't do reliably in text, or triggering actions like sending an email or creating a ticket.

Step 1: Define Your Tool

Each tool needs a name, a description (Claude uses this to decide when to call it), and an input_schema in JSON Schema format:

{
  "name": "get_weather",
  "description": "Get the current weather for a given city",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": { "type": "string", "description": "City name, e.g. Paris" },
      "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
    },
    "required": ["city"]
  }
}

Write descriptions as if explaining the tool to a new teammate. Vague descriptions ("gets data") lead to Claude either skipping the tool or calling it at the wrong time.

Step 2: Send the Request with Tools Attached

Here's a request using curl against a generic Claude-compatible Messages endpoint:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 1024,
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather for a given city",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": { "type": "string" },
          "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
        },
        "required": ["city"]
      }
    }],
    "messages": [{ "role": "user", "content": "What is the weather in Lisbon?" }]
  }'

Step 3: Handle the Tool Use Response

Claude's reply won't contain a final answer yet — it contains a tool call:

{
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01abc",
      "name": "get_weather",
      "input": { "city": "Lisbon" }
    }
  ],
  "stop_reason": "tool_use"
}

Check stop_reason — if it's tool_use, your application must act before anything else happens. This is the most common thing beginners miss: nothing runs automatically. You parse the tool_use block, call your real get_weather function, and move to the next step.

Step 4: Send the Tool Result Back

You append both the assistant's tool call and your tool's output to the conversation, then send it again:

const followUp = await fetch("https://api.anthropic.com/v1/messages", {
  method: "POST",
  headers: {
    "x-api-key": process.env.API_KEY,
    "anthropic-version": "2023-06-01",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    model: "claude-3-5-sonnet-20241022",
    max_tokens: 1024,
    tools: [ /* same tool definitions as before */ ],
    messages: [
      { role: "user", content: "What is the weather in Lisbon?" },
      { role: "assistant", content: previousAssistantContent },
      {
        role: "user",
        content: [{
          type: "tool_result",
          tool_use_id: "toolu_01abc",
          content: "18°C, partly cloudy",
        }],
      },
    ],
  }),
});

Claude now generates a final text response using the real weather data. If your tool fails, send an error string in the tool_result and Claude will typically explain the failure to the user rather than crashing the flow.

Common Mistakes to Avoid

Running This in Production

Once tool use works in a script, the next problem is usually operational: API keys per environment, rate limits, streaming tool calls to a frontend, and giving teammates their own access without sharing one shared key. SubToAPI turns your existing Claude access into an HTTPS API with per-application keys (sub_live_...), so you can issue separate keys for staging and production, see usage per key, and manage team seats without passing around a single credential. The request format for tool use is the same Messages-style payload — see the tools docs for the exact schema SubToAPI expects, streaming if you want partial tool-call output as it's generated, and the quickstart to get a key from the pricing page in a few minutes.

Questions

Does Claude execute the function itself? No. Claude only decides that a function should be called and what arguments to use. Your application is responsible for actually running the function and returning the result.

Can Claude call multiple tools in one turn? Yes, a single response can include several tool_use blocks if the task requires calling more than one tool before continuing, and you return all corresponding tool_result blocks together in the next message.

What happens if the tool call fails? Return an error message as the tool_result content instead of throwing an exception in your own code. Claude will read the error and typically explain the issue to the user or try an alternative approach.

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 →