# Tool calling

> The full function-calling loop — declare tools, read tool_calls, feed results back, then let the model answer.

Tool calling takes **two or more rounds**: the model never executes a function. It only emits which
function it wants and with what arguments; your code runs it, feeds the result back, and the model
answers from there.

## Round one: declare tools

```python
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Current weather for a given city",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string", "description": "City name"}},
            "required": ["city"],
        },
    },
}]

resp = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "How warm is it in Beijing?"}],
    tools=tools,
)
msg = resp.choices[0].message
print(msg.tool_calls)
# [ChatCompletionMessageToolCall(id='call_...', function=Function(name='get_weather', arguments='{"city":"Beijing"}'))]
```

## Round two: feed results back

```python
import json

messages = [{"role": "user", "content": "How warm is it in Beijing?"}, msg]
for call in msg.tool_calls:
    result = get_weather(**json.loads(call.function.arguments))
    messages.append({
        "role": "tool",
        "tool_call_id": call.id,
        "content": json.dumps(result),
    })

final = client.chat.completions.create(model="gpt-5.4", messages=messages, tools=tools)
print(final.choices[0].message.content)
```

`tool_call_id` must match the `id` the model returned — that pairing is the only way to associate
results when the model calls several tools in parallel.

## Common issues

| Symptom | Cause |
| --- | --- |
| Model answers without calling a tool | The `description` is too vague, or the model has no tool support |
| `arguments` is not valid JSON | Wrap `json.loads` in try/except and feed the error back so the model retries |
| Parallel results get mixed up | Pair by `tool_call_id`, never by array index |

<Callout type="info" title="Tool calling vs structured output">
Tool calling is "let the model decide what to call"; structured output is "make the answer fit a
schema". See [Structured output](/en/guides/structured-output/).
</Callout>
