TL;DR: tool_choice tells a model whether it must call a tool this turn, and which one. OpenAI uses auto / none / required / a named function; Anthropic uses auto / none / any / a named tool; Google's Gemini uses auto / none / any / validated. Forcing a tool (required, any, or a named tool) isn't universal: GLM-5.3 only supports auto, and three current Anthropic models reject forced tool use outright with a 400 error.
What does tool_choice actually decide?
Every provider that supports tool calling gives you a lever separate from the tools list itself: not just which tools the model can see, but how much say it has in whether to use one. Set it to let the model decide, and it might answer in plain text even with five tools defined. Set it to force a call, and the model must produce a tool call on this turn instead of a text response, whether or not a tool call is actually the right move.
That distinction sounds small until you've shipped it. An "auto" setting is what you want for a general chat assistant that sometimes needs a calculator and sometimes just needs to answer a question in words. A forced setting is what you want for a form-filling pipeline, a structured-extraction job, or anything where a plain-text reply would break the code downstream expecting JSON. Getting this parameter wrong doesn't usually crash anything; it just quietly produces the wrong shape of output, which is worse to debug than a hard failure.
What does tool_choice look like on OpenAI?
Verified directly from OpenAI's current function-calling guide (developers.openai.com/api/docs/guides/function-calling, fetched September 25, 2026), OpenAI documents four options:
// Let the model decide (the default)
{ "tool_choice": "auto" }
// Never call a tool this turn
{ "tool_choice": "none" }
// Must call some tool, model's choice of which
{ "tool_choice": "required" }
// Must call this exact function
{ "tool_choice": { "type": "function", "name": "get_weather" } }
OpenAI also documents a fifth shape worth knowing about, allowed_tools, which restricts the model to a named subset of your full tool list without forcing a call on every turn:
{
"tool_choice": {
"type": "allowed_tools",
"mode": "auto",
"tools": [{ "type": "function", "name": "get_weather" }]
}
}
The same page notes that on GPT-5-generation models, parallel function calls work alongside built-in tools by default, and you can turn that off with a separate parallel_tool_calls: false flag if your downstream code can only handle one call at a time. It also flags a detail specific to reasoning models: any reasoning items returned alongside a tool call have to be passed back to the API together with that tool call's output on the next turn, not dropped.
What does tool_choice look like on Anthropic, and where did it just get stricter?
Anthropic's current Messages API documentation (platform.claude.com/docs/en/api/messages, fetched September 25, 2026) defines four tool_choice types:
// Model decides whether and how to use tools (default)
{ "tool_choice": { "type": "auto" } }
// Model must use some tool
{ "tool_choice": { "type": "any" } }
// Model must use this specific tool
{ "tool_choice": { "type": "tool", "name": "get_weather" } }
// Model may not use tools at all
{ "tool_choice": { "type": "none" } }
Each of auto, any, and tool also accepts an optional disable_parallel_tool_use boolean, defaulting to false, if you need to cap the model at one tool call per turn.
This is where a lot of existing guides go stale, because Anthropic's own current thinking documentation (platform.claude.com/docs/en/build-with-claude/thinking, also fetched September 25, 2026) spells out two real constraints that didn't exist in earlier generations of the API:
That second half matters more than it looks. It means the same tool_choice: {"type": "any"} call that works fine on an older Claude model returns a hard 400 on some of the newest ones, on every single request, thinking enabled or not. If you're maintaining an integration that forces tool calls and you're about to point it at a newer model, check this constraint before you migrate, not after your error rate spikes in production.
What does tool_choice look like on Google's Gemini?
Google migrated Gemini's function-calling configuration onto its newer Interactions API surface, and the current documentation (ai.google.dev/gemini-api/docs/function-calling, fetched directly from the page's raw markup on September 25, 2026, not a summarized reading) sets tool_choice inside generation_config, with four modes:
generation_config = {
"tool_choice": "any" # or "auto", "none", "validated"
}
auto(default): the model decides whether to call a function or respond directly.any: the model is constrained to always predict a function call.none: the model is prohibited from making function calls.validated: the model ensures function schema adherence.
Gemini also documents an allowed_tools shape nested under tool_choice, functionally similar to OpenAI's, for restricting a forced call to a named subset of your available tools:
generation_config = {
"tool_choice": {
"allowed_tools": {
"mode": "any",
"tools": ["get_current_temperature"]
}
}
}
That validated mode is worth calling out on its own, because neither OpenAI nor Anthropic documents an equivalent as part of tool_choice itself: it's Gemini's own schema-adherence guarantee, layered onto the forcing decision rather than kept as a separate setting.
Three providers, three genuinely different shapes for the same underlying idea, and none of them chose the same field values twice. That's the practical lesson before you even get to the comparison table: don't assume a provider you haven't checked follows OpenAI's required convention, Anthropic's any convention, or Gemini's own validated addition. A parameter's name, casing, and existence on one vendor's API tells you nothing about another vendor's API, and that holds for tool_choice specifically as much as it does for sampling parameters like temperature, top_p, and top_k — see our top-p vs top-k reference and our guide to temperature, seeds, and determinism for the same pattern playing out on a different parameter family.
Does forcing a tool call actually look different in the request?
It's worth seeing the failure mode directly, not just described. Here's a request shape that works fine on most Anthropic models but is exactly the combination the current thinking documentation flags as unsupported:
// This combination errors on models where manual extended thinking
// is active: forcing tool_choice: {"type": "any"} together with
// thinking: {"type": "enabled"} is documented as incompatible.
{
"model": "claude-sonnet-4-6",
"max_tokens": 4096,
"thinking": { "type": "enabled", "budget_tokens": 2048 },
"tool_choice": { "type": "any" },
"tools": [{ "name": "get_weather", "input_schema": { "type": "object" } }],
"messages": [{ "role": "user", "content": "What's the weather in Paris?" }]
}
Drop the thinking block, or switch tool_choice back to {"type": "auto"}, and the same request is fine. Nothing about the tool definition or the message changed — only the interaction between two configuration fields that, read separately, look unrelated. That's the trap: tool_choice and thinking each work exactly as documented in isolation, and the failure only shows up when you read the page that discusses both together.
The comparison, side by side
| Feature | OpenAI | Anthropic | Google Gemini |
|---|---|---|---|
| Let the model decide | auto (default) | auto (default) | auto (default) |
| Never call a tool | none | none | none |
| Force any tool | required | any | any |
| Force one named tool | {"type": "function", "name": "..."} | {"type": "tool", "name": "..."} | allowed_tools with mode + tools list |
| Restrict to a subset without forcing | allowed_tools, mode auto | not documented as a distinct mode | allowed_tools, mode auto |
| Forced tool use can be rejected outright | Not documented as model-specific | Yes, on 3 current models, every request | Not documented as model-specific |
| Schema-adherence guarantee in tool_choice | Not part of tool_choice itself | Not part of tool_choice itself | validated mode |
Where does "always force a tool call" quietly break?
A pattern that shows up constantly in agent tutorials is: force a tool call on every turn so the output is always structured, always parseable, never a stray paragraph of prose. It's a reasonable instinct, and it works right up until one of these hits:
- You upgrade a model and the same forced
tool_choicecall now 400s. As covered above, this is a real, current, documented behavior on specific Anthropic models, not a hypothetical edge case. A model upgrade is usually tested for quality regressions; it's rarely tested for a parameter combination that used to be accepted and now isn't, which is exactly why this class of failure tends to reach production before anyone catches it. - You need extended thinking and forced tool use at the same time on Anthropic. You can't have manual extended thinking and a forced tool choice in the same request; you have to pick one or migrate to adaptive thinking, which changes other behavior too, such as whether prior turns' thinking blocks get preserved in context.
- You're building against a model that never supported forcing at all, like GLM-5.3, where
tool_choiceaccepts onlyautoand there is no forced-function option to fall back on. If your integration layer assumes every model speaks the OpenAI/Anthropic-style forcing vocabulary, a provider like this will silently ignore the field or reject the request, depending on how strictly that provider validates unknown parameters. - The model has nothing useful to call, and forcing it anyway produces a technically-valid but semantically empty tool call: arguments that don't actually answer the user's question, because the model had no path to decline. This is the most common way "always force a tool" quietly degrades output quality without ever throwing an error.
The safer default, across all three major providers, is to reach for auto plus a structured-output or strict-schema constraint when what you actually want is "guarantee the shape of the response," and reserve a genuinely forced tool choice for the narrow cases where you need a tool called on every single turn no matter what: a fixed pipeline stage, a benchmark harness testing the tool itself, or a single-purpose agent with exactly one job. If structured JSON output is really the goal rather than a tool call specifically, our guide to JSON prompts covers that alternative path directly.
What should you check before you set tool_choice?
- Do you actually need a tool called on this turn, or do you need output in a specific shape? If it's the shape you care about, look at structured outputs or strict tool use before reaching for a forced
tool_choice. - Which provider and which model? Confirm the exact accepted values on that provider's current docs. The shapes above are correct as of September 25, 2026, and Anthropic's own thinking documentation notes its pages are actively edited, so a stale cached answer from a search engine or an older tutorial is a real risk here, not a formality.
- Is extended thinking or an equivalent reasoning mode active? If you're on Anthropic and using manual extended thinking, forced tool use is off the table until you migrate to adaptive thinking or drop the forced choice.
- Do you need one specific tool, or any tool from a subset? A named-tool force and an
allowed_toolsrestriction solve different problems; conflating them produces either an overly rigid integration or one that calls the wrong tool. - What happens if the model is forced to call a tool it shouldn't? Design the fallback path (a "no relevant tool" tool, a validation layer, a human review step) before you ship forcing in production, not after the first bad call.
If you're writing prompts and tool definitions by hand across more than one of these providers, keeping the exact tool_choice shape straight per vendor is exactly the kind of detail that's easy to get right once and then quietly drift on, especially after a model upgrade changes what used to work. Saving a working, per-provider prompt and parameter reference in a searchable personal library rather than scattered across old chat threads is one simple way to make sure a change like the Anthropic forcing restriction above gets caught and fixed in one place instead of in every copy-pasted integration. See also our full LLM parameter cheat sheet for how tool_choice fits alongside temperature, top-p, and the other per-provider knobs.
Stop rewriting prompts. Start shipping.
Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.
Create An Account