Forcing a Specific Tool Call in the Claude API An engineer detailed how the Claude API's tool_choice parameter can be used to force a specific tool call, enabling developers to obtain structured JSON output by declaring a single tool and setting tool_choice to that tool. The technique guarantees a tool_use response with no preamble text, which is useful for extracting structured data from unstructured input, though it does not ensure the values are present in the source document. tool choice decides whether the model may call a tool, must call some tool, must call one particular tool, or may not call any. The interesting part is not the parameter — it is what each setting removes from the response. tool choice is a top-level object with a type discriminator. All four forms: "tool choice": {"type": "auto"} // default "tool choice": {"type": "any"} // some tool, model picks "tool choice": {"type": "tool", "name": "get deploy status"} // this exact tool "tool choice": {"type": "none"} // no tools this turn auto is what you get when the parameter is omitted and tools is present. none is what you get when there are no tools at all, and setting it explicitly while leaving the tools array in place is the way to keep the tool definitions in the cached prefix while forbidding calls for one turn. With auto , the model chooses. The response may contain only text, with stop reason: "end turn" : { "content": {"type": "text", "text": "Deploy ids look like dpl XXXX — which one?"} , "stop reason": "end turn" } Or text plus one or more tool use blocks, with stop reason: "tool use" . Both are normal and your code has to handle both. With any or tool , the model is required to call. stop reason is "tool use" on every response, and — this is the part worth internalising — the preamble text disappears. A forced response is the tool call and nothing else: // tool choice: {"type": "tool", "name": "get deploy status"} { "content": {"type": "tool use", "id": "toolu 01B7…", "name": "get deploy status", "input": {"deploy id": "dpl 8f21"}} , "stop reason": "tool use" } There is no text block to render, and if your UI expected one it now shows a blank turn. That is the trade: you gain a guaranteed shape and lose the model’s ability to say “I need more information first”. The difference between any and tool is only who picks. With any and three tools declared, you will get exactly one of the three and you will not know which until you read name . With tool you know before you send the request. The most common reason to force a specific tool has nothing to do with tools. A tool is a JSON Schema the model must fill in, so declaring one tool and forcing it is a way to get a guaranteed object back: { "model": "claude-opus-4-6", "max tokens": 1024, "tools": { "name": "record incident", "description": "Record the structured fields of an incident report.", "input schema": { "type": "object", "properties": { "severity": {"type": "string", "enum": "sev1", "sev2", "sev3" }, "component": {"type": "string"}, "customer impact": {"type": "boolean"} }, "required": "severity", "component", "customer impact" } } , "tool choice": {"type": "tool", "name": "record incident"}, "messages": {"role": "user", "content": "