Skip to main content
Use tool calling whenever the model needs to act on the world: call an API, query a database, run a calculation, fetch a document. Tool calling is a per-model capability. Check the capability listing on the model’s page before sending tools. A model that does not list tool calling refuses the request with 400 hosted_capability_not_supported.

Minimal code

What one turn actually looks like

One tool turnrepeat until tool_calls is absentMessages you hold01 SendThe model sees every tool description you registered.user02 Getfinish_reason is tool_calls; arguments arrive as a JSON string.user03 PushThen one tool message per call, each with its tool_call_id.user, assistant, tool04 SendThe model now answers, or asks for another tool.user, assistant, tool, …Your messages, plus toolsAn assistant message with tool_callsPush the whole assistant message backThe grown array, same callFinal answerThe turn with no tool_calls is the one you show the user.Dropping the assistant turn at step 03 breaks the state: the tool result then has nothing to attach to.
One tool turnrepeat until tool_calls is absentMessages you hold01 SendThe model sees every tool description you registered.user02 Getfinish_reason is tool_calls; arguments arrive as a JSON string.user03 PushThen one tool message per call, each with its tool_call_id.user, assistant, tool04 SendThe model now answers, or asks for another tool.user, assistant, tool, …Your messages, plus toolsAn assistant message with tool_callsPush the whole assistant message backThe grown array, same callFinal answerThe turn with no tool_calls is the one you show the user.Dropping the assistant turn at step 03 breaks the state: the tool result then has nothing to attach to.

What to tune

Common mistakes

  • Dropping the assistant turn. Push the whole assistant message, tool_calls and all, before you push any tool result.
  • Returning a non-string tool result. The content on a tool-role message must be a string. Always serialize it.
  • A vague description. Write it as though the model has never seen your API: what the tool does, what each argument means, what a good input looks like. This is the single biggest lever on whether a tool gets called at all.
  • No turn limit. Bound the loop. Ten turns covers almost every pattern, and an unbounded loop can spend real money.
  • Trusting the arguments. The model can invent a field or omit a required one. Validate with Pydantic or Zod before you execute.

Next steps

Structured output

When you want JSON back without a tool loop.

Streaming

Stream the assistant turn as it arrives.

Chat completions

The full request contract.