claude-opus-5-5 and fixing four breaking changes. Thinking can no longer be disabled, and forced tool_choice returns a 400. Thinking blocks are bound to the model and the conversation. computer_20251124 is rejected on the Claude API and Google Cloud. Default effort also drops from high to medium.Anthropic released Claude Opus 5.5 on 22 September 2026. It costs less than Opus 5: $4 / $20 per million input / output tokens, against $5 / $25. The model ID swap is one line, but Anthropic's migration guide lists four breaking changes for code that already runs on Opus 5. Two more changes fail no request but still change behaviour.
Below: each change with its exact documented error, before/after Python and TypeScript, cost impact, a checklist, and a test-and-rollback plan. For benchmarks, see our Claude Opus 5.5 complete guide.
What changes when you migrate from Opus 5 to Opus 5.5?
Here is every change you need to plan for, sorted by how it shows up:
| Change | Symptom | Fix |
|---|---|---|
| Thinking can't be disabled | 400 invalid_request_error | Remove thinking (or send {"type": "adaptive"}) and set output_config.effort |
| Forced tool use removed | 400 on Messages, Batches, and count_tokens | tool_choice: auto + strict: true, or structured outputs |
| Thinking blocks tied to model and conversation | 400 on edited history (accounts created on or after 31 Aug 2026); reasoning silently lost on model switch | Keep history append-only; opt into drop_block if needed |
computer_20251124 rejected (Claude API, Google Cloud) | 400 naming the tool type | Use computer_toolset_20260801 |
Text between tool calls moves into thinking blocks | No error; progress UI goes quiet | thinking.display: "updates" (beta) or "summarized" |
Default effort is medium (was high) | No error; different depth, latency, and cost | Set effort explicitly and re-run your sweep |
New refusal categories (bio, reasoning_extraction) | stop_reason: "refusal" on HTTP 200 | Handle refusals; opt into fallback |
Opus 5.5 keeps Opus 5's 1M-token context window, 128K max output, tokenizer, 512-token minimum cacheable prompt, and feature set: task budgets, compaction, mid-conversation system messages, batch, Files API, vision, and structured outputs. If you are coming from Opus 4.8 or older, work through the Opus 5 migration first (our Opus 5 vs Opus 4.8 breakdown covers it). Then apply everything below, but skip Opus 5's "disable thinking at high effort or below" option, because it doesn't exist on 5.5.
What is the model ID for Claude Opus 5.5 on Bedrock and Vertex?
Like claude-opus-5, the ID claude-opus-5-5 is fixed and has no date suffix. Per Anthropic's What's new in Claude Opus 5.5:
| Platform | Model ID | Notes |
|---|---|---|
| Claude API | claude-opus-5-5 | All customers; fast mode available here only |
| Amazon Bedrock | anthropic.claude-opus-5-5 | computer_20251124 keeps working here |
| Claude Platform on AWS | claude-opus-5-5 | Billed in CCUs via AWS Marketplace |
| Google Cloud (Vertex AI) | claude-opus-5-5 | No @ date suffix; toolset required for computer use |
| Microsoft Foundry | claude-opus-5-5 | Billed at standard API rates via Azure Marketplace |
from anthropic import AnthropicBedrockMantle, AnthropicVertex
bedrock = AnthropicBedrockMantle(aws_region="us-east-1")
bedrock.messages.create(model="anthropic.claude-opus-5-5", max_tokens=16000,
messages=[{"role": "user", "content": "..."}])
vertex = AnthropicVertex(project_id="my-project", region="global")
vertex.messages.create(model="claude-opus-5-5", max_tokens=16000,
messages=[{"role": "user", "content": "..."}])Breaking change 1: "thinking.type.disabled is not supported for this model"
Opus 5 turns thinking on by default but accepts thinking: {"type": "disabled"} at effort high or below. On Opus 5.5 thinking is always on. Both the disabled form and the old manual budget ({"type": "enabled", "budget_tokens": N}) return a 400 invalid_request_error at every effort level. Anthropic's docs give the exact messages:
"thinking.type.disabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
"thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.The fix is to delete the thinking field, or send {"type": "adaptive"}, which does the same thing. Effort is now the only control. If you disabled thinking to save latency or tokens, set effort to low.
# Before: accepted on Opus 5, 400 on Opus 5.5
client.messages.create(
model="claude-opus-5",
max_tokens=16000,
thinking={"type": "disabled"},
messages=[{"role": "user", "content": "..."}],
)
# After: thinking is always on; effort is the control
client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
output_config={"effort": "low"},
messages=[{"role": "user", "content": "..."}],
)const response = await client.messages.create({
model: "claude-opus-5-5",
max_tokens: 16000,
output_config: { effort: "low" }, // no `thinking` field
messages: [{ role: "user", content: "..." }],
});
// Responses can now start with one or more thinking blocks.
// Select by type, never by index.
const text = response.content
.filter((b): b is Anthropic.TextBlock => b.type === "text")
.map((b) => b.text)
.join("");Three follow-ups trip people up on this change:
- Stop reading
content[0]. Any response can begin withthinkingblocks. Under the defaultdisplay: "omitted"those blocks have an emptythinkingstring. Code that assumes the first block is text will break quietly. - Raise
max_tokens. Thinking counts towardmax_tokenseven when its text isn't returned. A limit sized for a no-thinking route will cut replies short. Anthropic's skill guidance suggests about 64K for long agentic coding turns (use streaming at that size). - Delete "don't think" or "show your reasoning" prompt rules. The model can't comply with the first. The second can now be declined with
stop_details.category: "reasoning_extraction". To see the reasoning, setdisplay: "summarized"and read thethinkingblocks.
Breaking change 2: Opus 5.5 tool_choice "any" and "tool" return 400
Forced tool use is gone. tool_choice: {"type": "any"} and {"type": "tool", "name": "..."} both fail with:
tool_choice: type "tool" and "any" are not supported for this model.The same validation runs on the token counting endpoint and the Message Batches API. A batch built with forced tool calls will return errored items, not a failed HTTP call, so check your batch result handling. auto (the default) and none still work. disable_parallel_tool_use: true still works with auto, and now means at most one call.
What to use instead depends on why you were forcing the call:
- You forced it to get JSON back. Move the schema to structured outputs (
output_config.format). It's the cleaner fit. - You forced it because the tool must run. Use
autoand addstrict: trueto the tool definition (withadditionalProperties: falsein the schema). Name the tool in the prompt.autodoesn't guarantee a call, so check for one and retry if it's missing.
# Before: 400 on Opus 5.5
client.messages.create(
model="claude-opus-5",
max_tokens=1024,
tools=tools,
tool_choice={"type": "tool", "name": "get_weather"},
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
)
# After: auto + strict tool use, steer in the prompt, verify the call happened
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
tools=[{**tool, "strict": True} for tool in tools],
tool_choice={"type": "auto"},
messages=[{"role": "user",
"content": "What's the weather in Paris? Use the get_weather tool."}],
)
if not any(block.type == "tool_use" for block in response.content):
... # retry once, or fall back to a text answerconst response = await client.messages.create({
model: "claude-opus-5-5",
max_tokens: 4096,
tools: tools.map((t) => ({ ...t, strict: true })),
tool_choice: { type: "auto" },
messages: [
{ role: "user", content: "What's the weather in Paris? Use the get_weather tool." },
],
});
const called = response.content.some((b) => b.type === "tool_use");We raised max_tokens from 1024 because thinking now runs before the tool call and uses part of that limit.
Breaking change 3: thinking blocks are bound to the model and the conversation
This is the change most likely to bite custom agent harnesses. Anthropic calls it preserved thinking, and it has two halves.
Model binding. Opus 5.5 can read thinking blocks from Opus 5 and earlier Opus, Sonnet, and Haiku models. A conversation that moves onto 5.5 keeps its reasoning. It can't read blocks from Fable or Mythos models. In the other direction, on the Claude API only Claude Fable 5.1 and Claude Mythos 5.1 can read Opus 5.5 blocks. If a router or fallback moves a conversation from 5.5 back to Opus 5 or Opus 4.8, those later turns run without 5.5's reasoning. The request still succeeds, and the API drops the unreadable blocks without billing them. With the thinking-binding-controls-2026-08-01 beta header, each drop is reported in input_transformations with reason: "model_binding_mismatch".
Conversation binding. Each block's signature records the system prompt, the tools set, and every earlier message. If any of those change, later blocks become invalid. For accounts created on or after 31 August 2026, 00:00 UTC, replaying an invalidated block returns a 400 by default:
messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block". That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.Common triggers:
- Injecting a per-turn reminder or token count, then deleting it on the next request.
- Rebuilding the
systemprompt each turn (a timestamp is enough to break it). - Adding or removing tools partway through a session.
- Snipping old tool results, or "keep-tail" compaction that summarizes old turns but replays recent turns with their thinking blocks.
The append-only replacements: a mid-conversation {"role": "system"} message for instruction changes; the full tool set declared at session start plus tool_addition / tool_removal blocks; server-side context editing or compaction for trimming.
Claude Code, claude.ai, Managed Agents, and the Agent SDK already keep history append-only. If your code builds messages itself, test it. If you can't make the harness append-only yet, opt into dropping the invalid blocks:
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=64000,
betas=["thinking-binding-controls-2026-08-01"],
thinking={
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"},
},
messages=history, # replay thinking blocks verbatim
)
for t in response.input_transformations: # empty list when nothing was dropped
log.warning("thinking dropped at %s: %s", t.path, t.reason)drop_block is a fallback, not a fix: dropped blocks lose their reasoning, and every history edit also resets your prompt cache. Older accounts aren't enforced by default, but setting the field to either value opts a request in, which is how to test from one.
Breaking change 4: computer_20251124 is rejected, use computer_toolset_20260801
Opus 5 accepts computer use two ways: the computer_toolset_20260801 toolset, or the older computer_20251124 tool under the computer-use-2025-11-24 beta. On the Claude API and Google Cloud, Opus 5.5 accepts only the toolset. The old tool returns a 400 that begins:
'claude-opus-5-5' does not support tool types: computer_20251124.The rest of the message lists the accepted types after "Did you mean one of". On Amazon Bedrock, computer_20251124 keeps working on Opus 5.5, so Bedrock integrations need no change. For Foundry and Claude Platform on AWS, check the computer use tool's compatibility table.
# Before: 400 on Opus 5.5 (Claude API / Google Cloud)
client.beta.messages.create(
model="claude-opus-5",
max_tokens=4096,
betas=["computer-use-2025-11-24"],
tools=[{"type": "computer_20251124", "name": "computer",
"display_width_px": 1024, "display_height_px": 768}],
messages=[{"role": "user", "content": "Open the display settings."}],
)
# After: no beta header; the toolset takes no name or display size
client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
tools=[{"type": "computer_toolset_20260801"}],
messages=[{"role": "user", "content": "Open the display settings."}],
)The request swap is the easy part. The agent loop changes too:
- The action is the block's
name. Each call is its owntool_useblock named after a member tool (screenshot,left_click,type,zoom...). It is notinput.actionany more. - One turn can hold several actions (batch actions), each in its own block.
- Every
tool_resultmust echo"toolset_name": "computer". A result without it is rejected. Onlyscreenshotandzoomresults need an image. A shortOKis enough for the rest. - You must size screenshots yourself. The toolset takes no display dimensions, and the API won't downscale screenshots to fit the model's image limits.
results = []
for block in response.content:
if block.type == "tool_use" and getattr(block, "toolset_name", None) == "computer":
output = run_action(block.name, block.input) # e.g. "left_click", {...}
results.append({"type": "tool_result", "tool_use_id": block.id,
"toolset_name": "computer", "content": output})
messages.append({"role": "user", "content": results}) # all results in one messageToken overhead changes too. Anthropic's pricing page puts the toolset with default members at about 4,500 input tokens per request. Disabling zoom through configs saves about 410. Opus 5 accepts both forms, so make and test this change on Opus 5 first.
Why did my progress updates disappear on Opus 5.5?
No error here. On Opus 5, the short notes the model writes between tool calls ("found the failing test, checking the fixture next") come back as text blocks. On Opus 5.5 they come back as progress-update thinking blocks, at most one before each tool call. Under the default display: "omitted" their text is empty. A UI that only renders text blocks goes silent for the whole agentic turn.
The fix is to set display to "updates", which is in beta. It returns the progress notes while keeping the reasoning hidden. "summarized" returns notes and reasoning summaries mixed together. Render each non-empty thinking block ahead of the tool_use it precedes, and pass the blocks back unchanged.
with client.beta.messages.stream(
model="claude-opus-5-5",
max_tokens=64000,
betas=["thinking-display-updates-2026-08-18"],
thinking={"type": "adaptive", "display": "updates"},
tools=tools,
messages=messages,
) as stream:
response = stream.get_final_message()
for block in response.content:
if block.type == "thinking" and block.thinking:
ui.progress(block.thinking) # the between-tool-call narration
elif block.type == "text":
ui.answer(block.text)const stream = client.beta.messages.stream({
model: "claude-opus-5-5",
max_tokens: 64000,
betas: ["thinking-display-updates-2026-08-18"],
// If your SDK version doesn't type "updates" yet, cast or upgrade.
thinking: { type: "adaptive", display: "updates" },
tools,
messages,
});
const response = await stream.finalMessage();If the model must hand the user something verbatim mid-turn, give it a "send message" tool, declared on the session's first request so it doesn't break the prefix.
What does the medium effort default mean for cost and quality?
On Opus 5 a request with no effort runs at high. On Opus 5.5 it runs at medium. Two further points from Anthropic's docs complicate a simple "set it back to high":
- The effort levels don't map one-to-one between the models. In Anthropic's testing, Opus 5.5 at
mediumbeats Opus 5 athighon coding and knowledge-work evals. On several coding evals,lowcomes close. - At the same level, Opus 5.5 thinks more per turn, most of all at
xhighandmax. Keeping theeffortyou used on Opus 5 can mean longer turns and more output tokens.
So set effort explicitly on every route. Start at medium and test the levels on either side. Use xhigh or max only where you've measured a quality gain. The system card also notes that FrontierCode scores fall above medium, so higher effort isn't automatically better. To change effort for a single turn without breaking the prompt cache, use per-message effort (beta mid-conversation-output-config-2026-07-01). Changing the top-level effort between requests invalidates the cache.
How much cheaper is Opus 5.5 than Opus 5?
List prices, all from Anthropic's pricing page, per million tokens:
| Opus 5 | Opus 5.5 | Change | |
|---|---|---|---|
| Input | $5 | $4 | -20% |
| Output | $25 | $20 | -20% |
| 5-minute cache write | $6.25 | $5 | -20% |
| 1-hour cache write | $10 | $8 | -20% |
| Cache hit / refresh | $0.50 (0.1x) | $0.20 (0.05x) | -60% |
| Batch input / output | $2.50 / $12.50 | $2 / $10 | -20% |
| Fast mode input / output (Claude API only) | $10 / $50 | $8 / $40 | -20% |
| Tool-use system prompt | 286 tokens (auto/none) | 286 tokens (auto/none only) | — |
The full 1M context is billed at the standard rate, with no long-context premium. inference_geo: "us" still adds a 1.1x multiplier. Anthropic's announcement says the model "costs 40% less to run than Opus 5" on typical workloads. That claim combines the lower prices with fewer tokens per task.
Here is a worked example. Take an agentic session with 2M input tokens, 90% served from cache, and 200K output tokens:
- Opus 5: 200K uncached × $5 + 1.8M cached × $0.50 + 200K output × $25 = $1.00 + $0.90 + $5.00 = $6.90
- Opus 5.5, same token counts: $0.80 + $0.36 + $4.00 = $5.16, about 25% less
Output dominates both bills. By our arithmetic, Opus 5.5 would need about 43% more output tokens on that session to cost the same as Opus 5. That can happen if you carry max effort over: Artificial Analysis reports about 119K output tokens per Intelligence Index task at max effort for Opus 5.5, against about 73K for Opus 5. At medium the picture reverses. Anthropic's system card lists CursorBench at about $3 per task at medium (52.5%), against $11.95 for Opus 5 at max (46.6%).
The cheaper cache has a catch. A hit now costs 5% of input, not 10%, so a cache miss costs 20x a hit where it used to cost 10x. Anything that silently breaks your prefix now costs relatively more. That includes timestamps in the system prompt, unsorted tool JSON, and top-level effort changes, as well as the history edits that preserved thinking forbids. Check usage.cache_read_input_tokens before and after the swap. For more on cost levers, see our Opus 5 pricing and effort guide.
How should you handle refusals on Opus 5.5?
Opus 5.5 adds a biology classifier and a reasoning_extraction category to Opus 5's cyber classifier. A decline is an HTTP 200 with stop_reason: "refusal", so check it before reading content. The simplest safety net is server-side fallback (beta, Claude API):
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
output_config={"effort": "medium"},
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
messages=[{"role": "user", "content": "..."}],
)
if response.stop_reason == "refusal":
category = response.stop_details.category if response.stop_details else None
... # "reasoning_extraction" is never retried on a fallbackOn Bedrock, Vertex, and Foundry, use the SDK's client-side refusal middleware or your own retry instead.
Opus 5.5 migration checklist
- Swap the model ID:
claude-opus-5-5, oranthropic.claude-opus-5-5on Bedrock. Keep it in config, not hard-coded. - Remove every
thinking: {"type": "disabled"}andbudget_tokens. Grep forbudget_tokens,"disabled", andthinking=. - Set
output_config.effortexplicitly on every route. - Raise
max_tokensto leave room for thinking, and stream long requests. - Read content blocks by
type. Passthinkingblocks back unmodified in tool loops. - Replace
tool_choiceany/toolwithauto+strict: trueor structured outputs. Greptool_choicein batch andcount_tokenscode too. - If you use computer use on the Claude API or Google Cloud, switch to
computer_toolset_20260801and update the agent loop. - Audit your harness for history edits: system-prompt rebuilds, injected reminders, tool-list changes, client-side trimming.
- If your UI shows text between tool calls, set
display: "updates"or"summarized". - Handle
stop_reason: "refusal"and opt into fallback. - Delete "don't think" and "write out your reasoning" prompt rules. Re-test Opus 5-specific verbosity and scope instructions.
- Re-baseline cost, latency, and cache hit rate at your chosen effort.
How do you test and roll back an Opus 5.5 migration?
Do the code changes on Opus 5 first. Almost every fix above is also valid on Opus 5:
- Removing
thinking, explicit effort,auto+stricttool use, structured outputs, the computer toolset, append-only history, and refusal handling all work onclaude-opus-5. display: "updates"is documented for Fable 5.1 and Opus 5.5. Guard it behind the model flag if you run it on Opus 5.
Ship those changes, confirm nothing regressed, then flip the model ID as a separate, config-only change. Rollback is then one config value.
Catch the 400s for almost nothing. count_tokens runs the same tool_choice validation and the same preserved-thinking check, and it doesn't generate output. Replay a sample of captured production request bodies through client.messages.count_tokens(model="claude-opus-5-5", ...) in CI to find every forced-tool and thinking-config route before real traffic does.
Test the history check directly. Run real multi-turn sessions with prefix_mismatch_behavior: "error" under the thinking-binding-controls-2026-08-01 header, so any history edit fails the build. In staging, use "drop_block" and log input_transformations. An empty array on every turn means your history is intact.
Assert response.model.startswith("claude-opus-5-5"), then run your evals at low, medium, and high, comparing cost per completed task.
Canary, then ramp. Send a small slice of traffic to 5.5, watch refusal rate, cache hit rate, 400s, and p95 latency, then ramp. Opus 5 stays available on every platform, so rollback is flipping the ID back. One caveat: conversations already in progress on 5.5 lose that model's reasoning when they move back to Opus 5. The requests succeed, but the thinking blocks are dropped. Prefer rolling back at conversation boundaries, and pin sessions that started on 5.5 to 5.5 until they end.
In Claude Code, /claude-api migrate this project to claude-opus-5-5 applies the ID swap and breaking parameter changes after confirming scope. Managed Agents users only change the model name.
Should you migrate now?
For most teams, yes: prices are lower and most fixes are mechanical. Budget real time only for custom harnesses that edit history and for computer-use loops on the Claude API or Google Cloud. If you're weighing other vendors, see our Opus 5.5 vs GPT-6 Sol comparison and the three-way Opus 5.5 vs GPT-6 Astra vs Grok 4.7 comparison. Fable 5.1 introduced the same thinking-binding rules (Claude Fable 5.1 guide); for the wider tooling picture, see the AI coding agents guide.
FAQ
Can I disable thinking on Claude Opus 5.5?
No. thinking: {"type": "disabled"} and {"type": "enabled", "budget_tokens": N} both return a 400 at every effort level. Omit the field or send {"type": "adaptive"}, and use output_config.effort: "low" for the lowest latency and cost.
How do I force a tool call on Opus 5.5?
You can't. tool_choice types any and tool are rejected. Use tool_choice: {"type": "auto"} with strict: true, name the tool in the prompt, and check that a tool_use block came back. If you only needed JSON, use structured outputs instead.
What is the default effort on Opus 5.5?
medium, one level below Opus 5's high. Anthropic says Opus 5.5 at medium beats Opus 5 at high on its coding and knowledge-work evals, but set effort explicitly and measure on your own tasks.
What are the Bedrock and Vertex model IDs for Opus 5.5?
On Amazon Bedrock it's anthropic.claude-opus-5-5. On Google Cloud Vertex AI, Microsoft Foundry, and Claude Platform on AWS it's claude-opus-5-5. Fast mode is only on the first-party Claude API.
Can I switch back to Opus 5 mid-conversation?
Yes, but Opus 5 can't read Opus 5.5's thinking blocks. The API drops them unbilled and later turns run without that reasoning.
Does my computer-use integration still work on Opus 5.5?
On Amazon Bedrock, yes: computer_20251124 keeps working. On the Claude API and Google Cloud it's rejected. Move to computer_toolset_20260801 and update your loop to read the action from each tool_use block's name and echo toolset_name on results.
Sources: Anthropic: Migrating to Claude Opus 5.5, What's new in Claude Opus 5.5, Preserved thinking, Refusals and fallback, Claude pricing, Anthropic announcement, Opus 5.5 system card, Artificial Analysis.
If your team is shipping agents on Opus 5.5 and needs extra hands for harness and migration work, Codersera can help you hire vetted remote developers who already build on the Claude API.