# Tool calling

> Define functions, handle tool calls and return results.

Tool calling (function calling) lets a model ask your code to run a function and use the result. Clonvo uses OpenAI’s format for every provider and translates for Anthropic and Gemini. Filter the [catalogue](https://clonvo.com/models.md) by **Tools** to see which models support it.

## 1. Describe your tools

```python
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Current weather for a city.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["city"],
            },
        },
    }
]

messages = [{"role": "user", "content": "Do I need an umbrella in Lisbon?"}]
completion = client.chat.completions.create(
    model="anthropic/claude-sonnet-5-5",
    messages=messages,
    tools=tools,
)
```

## 2. Run the calls the model asks for

When the model wants a tool, the response has `finish_reason: "tool_calls"` and the assistant message carries `tool_calls`:

```json
{
  "role": "assistant",
  "content": null,
  "tool_calls": [
    {
      "id": "call_01",
      "type": "function",
      "function": { "name": "get_weather", "arguments": "{\"city\":\"Lisbon\"}" }
    }
  ]
}
```

`arguments` is a JSON string. Parse it, run your function, then send the assistant message back with one `tool` message per call:

```python
import json

message = completion.choices[0].message
messages.append(message)

for call in message.tool_calls or []:
    args = json.loads(call.function.arguments)
    result = get_weather(**args)
    messages.append({
        "role": "tool",
        "tool_call_id": call.id,
        "content": json.dumps(result),
    })

final = client.chat.completions.create(
    model="anthropic/claude-sonnet-5-5",
    messages=messages,
    tools=tools,
)
print(final.choices[0].message.content)
```

Repeat until `finish_reason` is `stop`.

## Controlling tool use

| `tool_choice` | Behaviour |
| --- | --- |
| `"auto"` (default) | The model decides whether to call a tool. |
| `"none"` | The model answers without calling tools. |
| `"required"` | The model must call at least one tool. |
| `{"type": "function", "function": {"name": "get_weather"}}` | The model must call this tool. |

Not every model supports every option; some only accept `auto` or `none`, at least while reasoning is on. When a model can’t honour the option you send, Clonvo sends `auto` instead rather than failing the request, so check the response for `tool_calls` instead of assuming one was made. On Anthropic models that accept a forced tool, forcing one (`required` or a named function) turns extended thinking off for that request.

Some requests are rejected with `400` before they reach a provider: `required` or a named function without any `tools`, a named function that isn’t in `tools`, and two tools with the same name. Sending `tools` to a model without tool support also returns `400` (code `unsupported_parameter`).

Set `parallel_tool_calls: false` to ask for at most one call per turn. It’s passed to OpenAI, xAI, Mistral and free models, and to Anthropic as `disable_parallel_tool_use`; Gemini, DeepSeek and Moonshot models ignore it.

## Strict schemas

Set `"strict": true` inside `function` to ask providers that support it to follow your `parameters` schema exactly. Other providers treat the schema as guidance, so validate arguments before using them.

## Streaming tool calls

With `stream: true`, tool calls arrive in pieces in `delta.tool_calls`. Each piece has an `index`; the first piece for an index carries `id` and `function.name`, and later pieces append to `function.arguments`.

```js
const calls = [];
for await (const chunk of stream) {
  for (const part of chunk.choices[0]?.delta?.tool_calls ?? []) {
    const call = (calls[part.index] ??= { id: "", name: "", arguments: "" });
    if (part.id) call.id = part.id;
    if (part.function?.name) call.name = part.function.name;
    call.arguments += part.function?.arguments ?? "";
  }
}
```

## Tips

-   Keep tool descriptions short and specific; they count as input tokens on every request.
-   When you switch models mid-conversation, keep the same message history: Clonvo converts tool calls and results for the new provider.