Guides

Tool use (function calling) with Claude

Define tools with a JSON Schema, let the model decide when to call them, and send tool results back in the next turn. Complete round-trip example over the SubToAPI conversation endpoint.

Updated

Tools let the model ask your code to do something — look up an order, query a database, call a weather API — and continue with the result. You stay in control: the model only *requests* a call; your backend executes it.

1. Define tools

Each tool has a name, an optional description and an input_schema (JSON Schema, type: "object"). Up to 50 tools per request. Good descriptions matter more than clever schemas.

terminal
curl -X POST \
  "https://api.subtoapi.app/v1/conversation" \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "system": "You can return tool calls.",
    "model": "balanced",
    "messages": [{ "role": "user", "content": "Weather in Frankfurt?" }],
    "tools": [{
      "name": "get_weather",
      "description": "Get current weather for a city",
      "input_schema": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"]
      }
    }],
    "tool_choice": { "type": "auto" }
  }'

2. Read the tool_use block

When the model wants a tool, the response contains a tool_use block with an id, the tool name and parsed input, and stop_reason is "tool_use".

200 OK
{
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_...",
      "name": "get_weather",
      "input": { "city": "Frankfurt" }
    }
  ],
  "stop_reason": "tool_use",
  "usage": {
    "input_tokens": 780,
    "output_tokens": 32,
    "cache_read_tokens": 0,
    "cache_write_tokens": 0,
    "total_tokens": 812
  },
  "model": "balanced",
  "provider": "claude",
  "request_id": "req_..."
}

3. Run it and send the result back

Append the assistant turn exactly as received, then a user turn with a tool_result block referencing the same tool_use_id. Send the whole thread again; the model now answers with the information.

terminal
curl -X POST "https://api.subtoapi.app/v1/conversation" \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "balanced",
    "messages": [
      { "role": "user", "content": "Weather in Frankfurt?" },
      { "role": "assistant", "content": [
        { "type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": { "city": "Frankfurt" } }
      ]},
      { "role": "user", "content": [
        { "type": "tool_result", "tool_use_id": "toolu_01", "content": "21 °C, light rain" }
      ]}
    ],
    "tools": [{ "name": "get_weather", "description": "Current weather for a city",
                "input_schema": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] } }]
  }'

Controlling tool choice

  • { "type": "auto" } — the model decides (default).
  • { "type": "any" } — the model must call some tool.
  • { "type": "tool", "name": "get_weather" } — force one specific tool; ideal for structured extraction.
  • { "type": "none" } — tools are visible but must not be called.

Validate inputs

Treat input like any untrusted request body: validate against your schema before executing anything with side effects.

Frequently asked questions

Can the model call several tools at once?
Yes — the response can contain multiple tool_use blocks. Return one tool_result per block in the next user turn.
Is tool use available on every model?
Yes, on fast, balanced and best. Use balanced or best when tool selection needs judgement.