← Blog

Claude API Tool Use: A Python Example

2026-10-25 · 4 min read · SubToAPI Team

If you're searching for a working Claude API tool use Python example, you want code you can run, not just theory. This article walks through a complete script: defining a tool, sending a request, handling Claude's tool_use response, executing the function, and returning the result so Claude can finish its answer.

Tool use (also called function calling) lets Claude call code you control — a weather lookup, a database query, a calculator — instead of guessing an answer. Claude doesn't execute anything itself; it tells you which tool to call and with what arguments, and your Python code runs it and sends the result back.

How Tool Use Works, in Practice

The flow is always the same four steps:

  1. You send a message plus a list of available tools (name, description, JSON schema for inputs).
  2. Claude replies with stop_reason: "tool_use" and a block containing the tool name and input arguments.
  3. Your code runs the actual function and packages the output as a tool_result.
  4. You send that result back in a new message; Claude uses it to produce the final answer.

This is a multi-turn exchange even for a single user question — Claude's first reply isn't the final answer, it's a request for data.

Full Python Example

This example defines a get_stock_price tool and walks through the full loop using the requests library and the Anthropic Messages API format.

import requests
import json

API_KEY = "your-api-key"
URL = "https://api.anthropic.com/v1/messages"
HEADERS = {
    "x-api-key": API_KEY,
    "anthropic-version": "2023-06-01",
    "content-type": "application/json",
}

tools = [
    {
        "name": "get_stock_price",
        "description": "Get the current price of a stock by ticker symbol.",
        "input_schema": {
            "type": "object",
            "properties": {
                "ticker": {
                    "type": "string",
                    "description": "Stock ticker symbol, e.g. AAPL",
                }
            },
            "required": ["ticker"],
        },
    }
]


def get_stock_price(ticker: str) -> dict:
    # Replace with a real API call in production
    fake_prices = {"AAPL": 227.14, "MSFT": 418.30}
    return {"ticker": ticker, "price": fake_prices.get(ticker, 0.0)}


messages = [
    {"role": "user", "content": "What's the current price of AAPL?"}
]

response = requests.post(
    URL,
    headers=HEADERS,
    json={
        "model": "claude-sonnet-4-5",
        "max_tokens": 1024,
        "tools": tools,
        "messages": messages,
    },
).json()

if response["stop_reason"] == "tool_use":
    tool_block = next(
        block for block in response["content"] if block["type"] == "tool_use"
    )
    tool_name = tool_block["name"]
    tool_input = tool_block["input"]
    tool_use_id = tool_block["id"]

    if tool_name == "get_stock_price":
        result = get_stock_price(**tool_input)

    messages.append({"role": "assistant", "content": response["content"]})
    messages.append(
        {
            "role": "user",
            "content": [
                {
                    "type": "tool_result",
                    "tool_use_id": tool_use_id,
                    "content": json.dumps(result),
                }
            ],
        }
    )

    final = requests.post(
        URL,
        headers=HEADERS,
        json={
            "model": "claude-sonnet-4-5",
            "max_tokens": 1024,
            "tools": tools,
            "messages": messages,
        },
    ).json()

    print(final["content"][0]["text"])

A few details that trip people up:

Running This Against SubToAPI

If you're already using SubToAPI to turn your Claude subscription into an API key, the same script works with almost no changes — just swap the endpoint and auth header:

URL = "https://api.subtoapi.app/v1/messages"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "content-type": "application/json",
}

The request and response shapes for tool use — tools, tool_use blocks, tool_result messages — are unchanged, since SubToAPI passes through the same Messages API format. This is useful if you want a single dashboard for API keys, streaming, and usage metadata across a team, without managing separate Anthropic billing per developer. Details on the request format are in the docs and the tool use docs specifically; general message handling is covered in the Messages API docs. You can try it with a free trial at signup, and plans start at €9/month on the pricing page.

Common Mistakes to Avoid

Once this loop works for one tool, adding more is just appending to the tools list and extending the dispatch logic (an if/elif or a dict of function name to callable) that routes tool_name to the right Python function.

questions

Can Claude call more than one tool in a single response? Yes. Claude can return multiple tool_use blocks in one content array when a task needs several function calls. Loop through all blocks, execute each, and return all corresponding tool_result blocks in the next message.

Does tool use work with streaming responses? Yes, but the tool input arguments arrive as accumulated JSON deltas rather than a single block, so you need to buffer the partial JSON until the block closes before parsing it.

What happens if my function throws an error? Return the error as the tool_result content (as a string) and set "is_error": true on that block. Claude will see the failure and can retry, ask for clarification, or explain the problem to the user instead of crashing your application.

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 →