tool_choice: 4 Recipes That Ship (2026)
tool_choice in 2026: four copy-paste recipes to force any tool, pin one named tool, forbid tools for a turn, or leave it on auto, in Claude and OpenAI, each with the failure mode that bites.

On this page
Quick Answer
tool_choice decides whether a model is allowed to call a tool, forced to, or forbidden. There are four modes and they are the same idea across vendors. On Claude: auto (the model decides, the default when tools are present), any (must call some tool), tool (must call one named tool), none (no tools). Anthropic documents all four in its tool use guide. OpenAI uses the same shape with different words:
auto, required, none, and a forced named function. Four copy-paste recipes below, each with the failure mode that bites.
The mode is not a hint in your prompt. "Please call the tool" is a suggestion the model can skip. tool_choice is enforced by the decoder. Set it wrong and you either get chatter where you wanted a clean tool call, or a locked agent that can never answer. OpenAI's function-calling guide (2026) maps
required to Claude's any; the rest line up one to one.
The four modes in one table
Scroll to see more
| Intent | Claude 2026 | OpenAI 2026 | Model emits text first? |
|---|---|---|---|
| Model decides | {"type":"auto"} (default) | "auto" (default) | Yes |
| Must call something | {"type":"any"} | "required" | No |
| Must call one named tool | {"type":"tool","name":"x"} | {"type":"function","name":"x"} | No |
| No tools this turn | {"type":"none"} | "none" | Yes |
Recipe 1: force any tool
Claim: when the turn must end in an action, stop asking nicely and set any.
{
"model": "claude-haiku-4-5",
"tools": [{ "name": "log_ticket", "description": "File a support ticket", "input_schema": {"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]} }],
"tool_choice": { "type": "any" },
"messages": [{ "role": "user", "content": "The checkout page 500s on mobile Safari." }]
}
Receipt: the response comes back as a tool_use block, no chat. OpenAI equivalent: "tool_choice": "required".
Why it works: any prefills the assistant turn to a tool call, so the decoder cannot open with prose.
Failure mode: it also kills the preamble. The model will not explain itself first, even if you ask. Need reasoning plus a call? See Recipe 4.
Ship it when the only valid output is a tool call.
Recipe 2: pin one specific tool
Claim: for extraction and classification, name the tool. Do not let the model choose.
{
"model": "claude-haiku-4-5",
"tools": [{ "name": "extract_invoice", "description": "Pull fields from an invoice", "input_schema": {"type":"object","properties":{"total":{"type":"number"},"due_date":{"type":"string"}},"required":["total"]} }],
"tool_choice": { "type": "tool", "name": "extract_invoice" },
"messages": [{ "role": "user", "content": "Invoice 4471, total 1290.00 EUR, due Sept 30." }]
}
Receipt: one tool_use block for extract_invoice, arguments matching your schema. OpenAI: {"type":"function","name":"extract_invoice"}.
Why it works: this is the clean way to get typed, schema-shaped output without prompt-wrangling a JSON blob. Pair it with strict: true on Claude and the arguments are guaranteed to validate against your schema.
Failure mode: pinning a tool is not the same as forcing valid JSON in a text turn. If you want raw JSON in the message body instead, that is a different pattern; see our structured output recipes.
Ship it for single-purpose extractors and routers.
Recipe 3: forbid tools for one turn
Claim: in an agent loop, the closing turn should be text. Set none so the model writes the answer instead of calling one more tool.
{
"model": "claude-haiku-4-5",
"tools": [{ "name": "search", "description": "Search the docs", "input_schema": {"type":"object","properties":{"q":{"type":"string"}},"required":["q"]} }],
"tool_choice": { "type": "none" },
"messages": [
{ "role": "user", "content": "Summarize what you found." }
]
}
Receipt: a plain text turn. The tools are still declared, so the model stays aware of them, but it cannot call one. OpenAI: "tool_choice": "none".
Why it works: none lets you keep the tool definitions in context (and cached) while blocking calls for exactly one step.
Failure mode: people reach for none to save tokens. It does not drop the tool definitions from the prompt; they still cost input tokens. It only blocks the call.
Ship it on the final synthesis turn of a loop.
Recipe 4: leave it on auto, and keep the preamble
Claim: most of the time, do nothing. auto is the default and it is usually right.
{
"model": "claude-haiku-4-5",
"tools": [ /* your tools */ ],
"tool_choice": { "type": "auto" },
"messages": [{ "role": "user", "content": "What is the weather in Lisbon? Use the get_weather tool in your response." }]
}
Receipt: the model can open with a short natural-language line ("I'll check that for you.") and then emit the tool_use block. That preamble is what any and tool destroy.
Why it works: auto does not prefill the assistant turn, so reasoning text is allowed. If you need the model to call a specific tool AND talk, use auto and just ask for the tool by name in the user message. This is Anthropic's documented workaround for the no-preamble problem.
Failure mode: on ambiguous prompts auto will sometimes answer from memory instead of calling the tool. If the call is mandatory, that is Recipe 1's job, not auto's.
Ship it as the default. Only override when the output contract demands it.
Three failure modes that bite
Forcing a tool erases the preamble. any and tool prefill the assistant message, so there is no explanation before the tool_use block, even if your system prompt begs for one. If you need both, use auto plus an explicit instruction.
Forced tool use breaks manual extended thinking on Claude. With thinking: {type: "enabled"} set manually, any and tool return an error; only auto and none are allowed. Adaptive thinking, including models where thinking is on by default, does support forced tool use. This is the trap that turns up as a question devs keep re-asking (2025-2026): how do I get reasoning and a guaranteed call at once. On Claude with manual thinking, you cannot force it; you steer with auto.
Flipping tool_choice mid-conversation busts your prompt cache. On Claude, a change to tool_choice invalidates cached message blocks; tool definitions and the system prompt stay cached, but the message content is reprocessed. If you toggle modes every turn, you are paying full input price every turn.
When NOT to force a tool
Do not set any or required on every turn of an agent loop. If the model must call a tool at each step, it can never emit a final answer and the loop runs until your max-iterations cap. Force on the acting turns; switch to auto or none on the answering turn.
Do not use forced tool use to fake structured text output. If you want JSON in the message body, prompt for it or use the structured-output path. Forcing a tool gives you a tool_use block, which your code has to unwrap. That is the right shape for actions, the wrong shape for "return me a JSON string." The same discipline shows up in our Claude tool use recipes.
Cost to test: $0.02 (four Claude Haiku 4.5 calls, one per mode, tiny prompts).
Written by
Sam Q.Sam Q. writes terse, tested prompt and API recipes for PromptAttic. Every recipe ships with a receipt, a failure mode, and a cost to test.
FAQ
What are the tool_choice values in the Claude API?
Four: auto (the model decides whether to call a tool, the default when tools are provided), any (the model must call one of the provided tools), tool (the model must call one specific named tool, set as {"type":"tool","name":"..."}), and none (the model cannot call any tool, the default when no tools are provided). Source: Anthropic tool use docs, 2026.
What is the difference between tool_choice any and tool?
any forces the model to call some tool but lets it pick which one. tool forces one specific tool by name. Use any when several tools are valid and the model should route; use tool for a single fixed extractor or classifier.
Does forcing a tool stop the model from explaining itself?
Yes. On Claude, tool_choice any and tool prefill the assistant message, so the model emits no natural-language text before the tool_use block, even if asked. If you need both reasoning and a call, use auto (the default) and name the tool in the user message instead.
How do I force a tool call in the OpenAI API?
Set tool_choice to "required" to force some function call, or to {"type":"function","name":"your_function"} to force one specific function. "auto" lets the model decide and "none" blocks calls. This mirrors Claude's any, tool, auto, and none. Source: OpenAI function-calling guide, 2026.
Why does forcing a tool fail with extended thinking on Claude?
With manual extended thinking enabled (thinking: {type: "enabled"}), Claude only supports tool_choice auto and none; any and tool return an error. Adaptive thinking, including models where thinking is on by default, does support forced tool use.
Does changing tool_choice affect prompt caching?
On Claude, changing tool_choice invalidates cached message blocks. Tool definitions and the system prompt stay cached, but message content is reprocessed. If you flip modes every turn you pay full input price every turn.
Related recipes
Claude Tool Use: 3 Recipes That Ship + 2 Failure Modes (June 2026)
Three production Claude tool use recipes tested on Sonnet 4.6, Opus 4.7, and Haiku 4.5 with current pricing. Plus the two failure modes nobody warns you about. June 2026.
Claude Structured Output: 3 Prompt Recipes That Ship (June 2026)
Three production-grade Claude structured output recipes for June 2026. Invoice extraction on Sonnet 4.6, support triage on Haiku 4.5, NL to SQL on Opus 4.7. Real cost per call. Three failure modes the docs do not warn you about.
Assistant Prefill: 4 Recipes That Ship (2026)
Assistant prefill in 2026: four copy-paste recipes that force JSON, kill the preamble, lock the output shape, and hold a persona, plus where prefill breaks.


