# What breaks when you switch to Claude Opus 5.5: four 400s, three silent changes, and what your fallback loses

> Four Opus 5 request shapes now return 400 on Claude Opus 5.5, three changes return 200, and a fallback to Opus 5 loses the reasoning. Error text, fixes, replay.

- Published: Sep 22, 2026
- Updated: Sep 28, 2026
- Author: Leo Kaka, Engineering
- Tags: models, gateway, failover
- Canonical: https://pirouter.ai/blog/claude-opus-5-5-migration-breaking-changes

---
Changing `claude-opus-5` to `claude-opus-5-5` is one line, and four request shapes that
worked on Opus 5 now return a 400 `invalid_request_error`: `thinking` set to `disabled` or
to a manual budget, a forced `tool_choice` of `any` or a named tool, a thinking block
replayed after you edited the history in front of it, and the `computer_20251124` tool on
the Claude API and Google Cloud. Three of those 400s show up on your first request; the
history one may not show up on your own key at all. Three more changes return 200: notes
between tool calls arrive as empty `thinking` blocks, and a request without an effort
setting runs at `medium` instead of `high`. The third is the expensive one: a fallback from
Opus 5.5 to Opus 5 succeeds without any of Opus 5.5's reasoning, runs an unset effort at
`high` again, and pays 25% more per token.

No measurements of mine here. This is Anthropic's Opus 5.5 documentation read field by
field as it stood on 23 September 2026, error strings copied verbatim, plus one router's
published migration guide as a second surface. We build a gateway, so for each change I
ask which layer should absorb it. A migration order is at the end.

| Change | On Claude Opus 5 | On Claude Opus 5.5 |
|---|---|---|
| `thinking` disabled | Accepted at effort `high` or below | ✗ 400 at every effort level |
| `tool_choice` of `any` or `tool` | Accepted | ✗ 400, on `count_tokens` too |
| Thinking block replayed after `system`, `tools` or earlier messages changed | Accepted; no check | ✗ 400 on accounts created from 31 Aug 2026, 00:00 UTC; in Batch, dropped silently |
| `computer_20251124` tool | Accepted with its beta header | ✗ 400 on the Claude API and Google Cloud; Bedrock still accepts it |
| Notes between tool calls | `text` blocks | ⚠ 200; `thinking` blocks, empty at the default `display` |
| Request with no effort set | Runs at `high` | ⚠ 200; runs at `medium` |
| Conversation moved from 5.5 down to Opus 5 | n/a | ⚠ 200; Opus 5.5 thinking blocks dropped, not billed |

> **Correction (2026-09-28):** an earlier version of this table listed a manual `budget_tokens` alongside disabled thinking as new on Opus 5.5. Manual extended-thinking budgets have returned 400 since Claude Opus 4.7, so code already running on Opus 5 does not send them; the one new thinking 400 is `disabled` ([migration guide](https://platform.claude.com/docs/en/models/opus-5-5/migration-guide)).

Sources for every row: [What's new in Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/whats-new-opus-5-5)
and [Migrating to Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/migration-guide).
The first three 400s also apply to Claude Fable 5.1, the tier above Opus, so if a workload
already runs there, most of this is familiar.

## Claude Opus 5.5 rejects `thinking.type.disabled`: thinking is always on

On Opus 5 you could switch thinking off at effort `high` or below. On Opus 5.5 you cannot,
and the manual budget form is gone too. Either shape returns a 400 with one of these:

```text
"thinking.type.disabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
```

```text
"thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
```

Delete the `thinking` field, or send `{"type": "adaptive"}`, which the documentation calls
equivalent. Cost control moves to effort, which lives at `output_config.effort`:

```json
{ "model": "claude-opus-5-5", "max_tokens": 16000, "output_config": { "effort": "low" } }
```

The [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) page says the
disabled form returns "a 400 error at every effort level," so `low` is the floor, not an
off switch.

Teams that ran with thinking off hit two more things. Every response can now start with one
or more `thinking` blocks, so `content[0].text` breaks. Select by type:

```python
text = "".join(b.text for b in response.content if b.type == "text")
```

And thinking counts toward `max_tokens` even when its text is hidden. The
[Prompting Claude Opus 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#calibrate-effort)
page: "a limit sized for Claude Opus 5 with thinking off can cut replies off." It reports
128,000, the model's maximum, "has worked well in Anthropic's testing" for long agentic
turns. Raising it is not free everywhere: a gateway that reserves quota by `max_tokens`
reserves more, and a non-streaming call with a long ceiling can outlive your HTTP timeout.
The thinking that fills it bills as output at $20 per million tokens.

## Forced `tool_choice` returns 400 on Claude Opus 5.5, count_tokens included

```text
tool_choice: type "tool" and "any" are not supported for this model.
```

`auto` and `none` still work, and What's new adds one clause that matters later: "the same
validation applies to the token counting endpoint." If you forced a tool to get
schema-valid JSON, keep `auto` and set `strict: true`
([Strict tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use))
or move to structured outputs. If you forced it to get a call at all, say so in the prompt,
and check the response for a `tool_use` block, because `auto` does not promise one. A retry
resends the whole input: at least $0.20 on an uncached 50,000-token context, about a cent on
a warm cache. In the
[Batch API](https://platform.claude.com/docs/en/build-with-claude/batch-processing),
validation is asynchronous, so these come back as errored items when the whole batch ends.
Errored items are not billed.

## Editing history before a thinking block returns 400 on accounts created from 31 August 2026

The text of a thinking block is not the reasoning itself; the block
carries an encrypted `signature` from which the API rebuilds the model's earlier reasoning
when you send the block back. That is why tool-use loops must return thinking blocks
unmodified. On Opus 5.5 the signature is also bound to the conversation it came from.

[Preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking)
calls that conversation the block's prefix: the top-level `system` prompt, the `tools`
list, and every message before the block. Change any of them later, replay the block, and:

```text
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".
```

Accounts created on or after 31 August 2026, 00:00 UTC get this 400 by default, on the
Claude API and cloud platforms. Older accounts get it only on requests that set
`thinking.block_binding.prefix_mismatch_behavior`. The docs spell out the trap for anyone
shipping a tool that runs on other people's keys: "a run with no errors on your own key
doesn't show whether your code is affected." The same trap applies to a key pool that mixes
accounts from before and after that date: one history can return 200 on one key and 400 on
the next. Set `prefix_mismatch_behavior` explicitly on every request (it needs the
`thinking-binding-controls-2026-08-01` beta header) and every account behaves the same.

Batch is the exception to the 400. On an enforced account, a batch item that leaves the
field unset "doesn't fail"; the API drops the failing blocks instead. That puts Batch in the
silent column.

What counts as an edit is broader than it sounds. `effort`, `max_tokens`, `output_config`,
`tool_choice` and `metadata` are outside the check. Rebuilding the system prompt with
today's date, an MCP server that connects after the first turn, clearing old tool results,
summarizing old turns while keeping recent thinking, and adding a tool mid-session are all
edits. Removing thinking blocks from the start, the end, or all of them is allowed;
removing one from the middle invalidates every block after it.

With `"drop_block"`, the request succeeds, the failing blocks are dropped and not billed,
and each is listed in `input_transformations` with `reason: "prefix_binding_mismatch"`.
Anthropic's own caveat: it keeps requests succeeding "but doesn't fix the edit." Alert on
those entries.

## `computer_20251124` is rejected on the Claude API and Google Cloud, accepted on Bedrock

The conclusion first: as I read the docs on 23 September 2026, no single computer-use
request for Opus 5.5 works on both the Claude API and Bedrock. On the Claude API and Google
Cloud, Opus 5.5 accepts only the `computer_toolset_20260801` toolset, and the earlier tool
gets a 400 whose message begins:

```text
'claude-opus-5-5' does not support tool types: computer_20251124.
```

On Bedrock, What's new says the earlier tool "continues to work on Claude Opus 5.5 as it
does on Claude Opus 5." The
[Computer use tool compatibility section](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#compatibility)
says platforms other than the Claude API and Google Cloud "currently offer only the earlier
beta tool versions." Read together, the two pages imply that a failover between the Claude
API and Bedrock has to swap the tool declaration and the agent loop, not just the endpoint.
For Claude Platform on AWS and Microsoft Foundry, neither page lists either form for Opus 5.5.

The `tools` entry, before and after:

```json
{ "tools": [{ "type": "computer_20251124", "name": "computer", "display_width_px": 1024, "display_height_px": 768 }] }
{ "tools": [{ "type": "computer_toolset_20260801" }] }
```

Drop the `computer-use-2025-11-24` header too. The loop change is bigger: read the action
from the member `tool_use` block's `name`, not `input.action`; expect several per turn; echo
`toolset_name` on every result. Two defaults also change
([Migrate from computer_20251124](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#migrate-from-computer-20251124)):
zoom is on by default, and the toolset "rejects a screenshot or zoom image that exceeds the
model's image limits instead of downscaling it."

## The three changes that return 200: quiet progress notes, a lower default effort, and a fallback that forgets

Status codes catch none of these.

### Notes between tool calls arrive as empty thinking blocks

On Opus 5, the short note the model writes between tool calls, what it just found and what
it checks next, is a `text` block, and many agent UIs stream it as a status line. On Opus
5.5 it is a progress-update `thinking` block, at most one per tool call
([Thinking, Progress updates between tool calls](https://platform.claude.com/docs/en/build-with-claude/thinking#progress-updates)),
empty at the default `display: "omitted"`. The migration guide's phrase is the bug report
your users will file: the application "goes quiet between tool calls."

![Flowchart of a streamed response with thinking. After the thinking block opens, the path splits: with display summarized, thinking_delta events stream the thinking summary; with display omitted, one empty thinking_delta arrives and no thinking text streams. Both paths then get a single signature_delta and content_block_stop, after which the text block streams.](/blog/images/claude-opus-5-5-migration-breaking-changes-thinking-stream.png "Anthropic's diagram of a streamed thinking block. The right-hand branch, display omitted, is the Opus 5.5 default: one empty delta and a signature, no text for your UI. Source: [Thinking, Streaming thinking (Claude Platform Docs)](https://platform.claude.com/docs/en/build-with-claude/thinking#streaming-thinking)")

The fix is `display: "updates"`, which returns progress notes and keeps reasoning hidden. It
is in beta:

```json
{ "headers": { "anthropic-beta": "thinking-display-updates-2026-08-18" },
  "body": { "thinking": { "type": "adaptive", "display": "updates" } } }
```

Without that header, the same page says, the value "is rejected with the same 400
`invalid_request_error` as an unknown `display` value," so a proxy that strips beta headers
it does not recognize turns the fix into a fifth 400. `"summarized"` returns notes and
reasoning summaries mixed. Either way, a note "counts toward `usage.output_tokens` at its
full length," and the model writes fewer of them at higher effort.

### A request with no effort set now runs at medium

Effort: "Most Claude models default to high effort… Claude Opus 5.5 defaults to medium."
Anthropic's testing says 5.5 at `medium` "matches or exceeds Claude Opus 5 at `high`" on
coding and knowledge work, and that 5.5 tends to think more per turn at any level. The
prompting guide's line is the one to keep: "Effort level names don't correspond to the same
amount of thinking across models." I made that argument across vendors in
[reasoning_effort is one name with five physics](/blog/reasoning-effort-one-name-five-physics);
it now holds inside one model family. On one model, re-run your effort sweep. Behind a
router, read on.

### A fallback from Opus 5.5 to Opus 5 succeeds without the reasoning

Opus 5.5 reads thinking blocks from Opus 5 and earlier Opus, Sonnet and Haiku models. On the
Claude API, Claude Fable 5.1 and Claude Mythos 5.1 (the restricted-access version of the same
model) read Opus 5.5's blocks, and no other model does. Upgrading a conversation from Opus 5
to 5.5 keeps its reasoning. The migration guide on the other direction: "A router or
fallback that moves a conversation from Claude Opus 5.5 to any other model runs those turns
without them."

The API drops the unreadable blocks, the request succeeds, and the drops are not billed.
Without the `thinking-binding-controls-2026-08-01` header, "the drop is silent"; with it,
each drop appears in `input_transformations` as `model_binding_mismatch`. The API never
edits your `messages`, so when the next turn returns to 5.5 the blocks are readable again,
unless your own client stripped them.

On that fallback turn, if the request did not set effort:

1. Opus 5 sees none of Opus 5.5's reasoning.
2. It runs at `high`, its own default: a different effort than the one you tested.
3. Tokens cost 25% more: $5 input and $25 output per million, against $4 and $20.

Every hop is a 200, so the error-rate panel stays flat.

Refusals make this concrete. A classifier refusal on Opus 5.5 is itself a 200 with
`stop_reason: "refusal"` ([One model, two safety tiers](/blog/one-model-two-safety-tiers)
covers the shape), and 5.5 adds classifiers: bio and `reasoning_extraction` join cyber.
Anthropic's announcement ([Introducing Claude Opus 5.5](https://www.anthropic.com/claude-opus-5-5))
says "most cybersecurity tasks will be re-routed to Opus 4.8," a model outside the short list
that reads 5.5's blocks. Expect your refusal rate to move and watch it during the canary.
One category never retries: server-side fallback "doesn't retry requests declined with
`"reasoning_extraction"`; that refusal is returned to you."

## Where a router should absorb each change, and where it must not

A router handles every one of these requests before the model does, so each change has a
natural place to be caught:

| Change | Layer | What absorbing it honestly looks like |
|---|---|---|
| `thinking` disabled | Before routing | Reject for a target that does not accept it, or route only to one that does |
| Forced `tool_choice` | Before routing | Same; validate the body against every target in the fallback set |
| History edit before a 5.5 thinking block | History | Forward history byte for byte; pass `anthropic-beta` and `block_binding` through; return `input_transformations` |
| `computer_20251124` | Endpoint selection | Treat Claude API and Bedrock as different tool contracts |
| Progress notes | Response translation | Keep `thinking` blocks with text apart from reasoning when converting to another API shape |
| Default effort | Every route | Write `effort` on every request, primary and fallback |
| Dropped reasoning on fallback | Routing policy | Within the Claude API, prefer targets that read the blocks; across clouds, accept the loss and log `model_binding_mismatch` counts |

The general rule: a fallback set must be validated against the intersection of what every
target accepts. Anthropic applies a version of it to its own fallback list: a request "must
be valid as a direct request to every model named"
([Refusals and fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models)).
Its fallback entries can override `thinking`, `max_tokens`, `output_config` and `speed` per
attempt; `tool_choice` is not on that list, so a forced tool has to be valid everywhere.

For the history layer, the Preserved thinking page has a section titled "Libraries, proxies,
and gateways." Its four rules: forward the caller's `anthropic-beta` values and
`thinking.block_binding` unchanged and return `input_transformations`; leave a `role: "system"`
message where the caller put it; to turn tools off, "send `tool_choice: {"type": "none"}`.
Don't remove `tools`"; and "Don't hide the 400."

OpenRouter's
[Claude Opus 5.5 migration guide](https://openrouter.ai/docs/cookbook/evaluate-and-optimize/model-migrations/opus-5-5)
shows a router making different choices and documenting them. Disabling reasoning returns a
400 at the router. Thinking budgets "are accepted by OpenRouter but the request goes upstream
as adaptive thinking with no budget… Remove them and set an effort instead." Preserved
thinking: "Requests through OpenRouter are not subject to this enforcement." And it sends
summarized thinking by default: "Set `thinking.display` to `"omitted"`, or
`reasoning.exclude: true` on Chat Completions, if you do not want it." If you run a direct
key and a router side by side, a budgeted request or an edited history can be a 400 on one
path and a 200 on the other, and the progress-note UI differs. Test your failover against
the strictest path.

For our own gateway, the trade-off we chose is a 400 over a rewrite whenever a caller's field
would change their bill, because the caller who set a budget believes something about their
costs.

These specific behaviors are design, not shipped: our gateway is designed to reject a
disabled or budgeted `thinking` field and a forced `tool_choice` for a target that does not
accept them, returning Anthropic's documented error text; to forward history, beta headers
and `block_binding` untouched and return `input_transformations`; and to write `effort` on
every fallback hop.

## Find the requests that will 400 before you switch: pass 0, count_tokens and max_tokens: 0

Your Opus 5 logs are the test set. Use a separate workspace and key for replays, and check
that logged bodies with user data are allowed to leave their retention policy.

**Pass 0, local.** Three of the four 400s are visible in the body: `thinking.type` of
`disabled` or `enabled`, `tool_choice.type` of `any` or `tool`, and a `computer_20251124` tool.

**Pass 1, free: `count_tokens`.** The
[Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) page
says it "is free to use," with its own rate limit. It is documented to apply the
`tool_choice` check, not the others, so a 200 means "not rejected yet." It accepts only eight
top-level fields
([Count tokens in a Message, API reference](https://platform.claude.com/docs/en/api/messages/count_tokens)),
and it rejects server tools, the MCP connector, and `url` or `file` sources that Messages
accepts. Those are false positives.

**Pass 2, input tokens only: `max_tokens: 0`.** Anthropic's cache pre-warming shape
([Prompt caching, Pre-warming the cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pre-warming-the-cache))
reads the prompt and returns with "zero output tokens" billed, through the real Messages
validation. Its purpose here is to catch what the docs do not list. It has its own reject
list: `stream: true`, `thinking.type: "enabled"`, `output_config.format` and forced
`tool_choice`, so the script strips the first and third and leaves the others to pass 0.

Cost of pass 2: requests × average input tokens × $4 per million, plus uncached prefixes
with a `cache_control` breakpoint at $5 per million. Sample 200 requests first. The script
targets the Claude API, so Bedrock traffic that uses `computer_20251124` will be flagged here
and is fine where it runs.

The script needs Python 3.9+ and a JSONL file exported from your request logs, one line per
request with the body and its `anthropic-beta` value.

```python
# replay.py: which logged Opus 5 requests would Opus 5.5 reject?
# Input: JSONL, one logged request per line: {"beta": "<anthropic-beta header or empty>", "body": {...}}
# Without ANTHROPIC_API_KEY only pass 0 runs (local, free). PASS2=1 enables the input-billed pass.
import collections, json, os, sys, time, urllib.error, urllib.request
from concurrent.futures import ThreadPoolExecutor

API = os.environ.get("REPLAY_API", "https://api.anthropic.com/v1/messages")
KEY = os.environ.get("ANTHROPIC_API_KEY")  # use a separate workspace key for replays
COUNT_FIELDS = {"model", "messages", "system", "tools", "tool_choice",
                "thinking", "output_config", "cache_control"}
KNOWN = ("thinking.type.", "tool_choice: type", "does not support tool types")

def pass0(body):  # the three documented 400s, read straight off the body
    thinking = (body.get("thinking") or {}).get("type")
    if thinking in ("disabled", "enabled"):
        return f"pass0: thinking.type.{thinking}"
    if (body.get("tool_choice") or {}).get("type") in ("any", "tool"):
        return "pass0: forced tool_choice"
    if any(t.get("type") == "computer_20251124" for t in body.get("tools") or []):
        return "pass0: computer_20251124 (rejected on Claude API and Google Cloud only)"
    return None

def post(url, body, beta, tries=4):
    headers = {"x-api-key": KEY, "anthropic-version": "2023-06-01",
               "content-type": "application/json"}
    if beta:
        headers["anthropic-beta"] = beta
    for attempt in range(tries):
        req = urllib.request.Request(url, json.dumps(body).encode(), headers)
        try:
            with urllib.request.urlopen(req, timeout=60) as r:
                return r.status, ""
        except urllib.error.HTTPError as e:
            raw = e.read().decode("utf-8", "replace")
            if e.code in (429, 529) and attempt < tries - 1:
                time.sleep(2 ** attempt)
                continue
            try:
                return e.code, json.loads(raw)["error"]["message"]
            except (ValueError, KeyError, TypeError):
                return e.code, raw[:200]
        except (urllib.error.URLError, TimeoutError) as e:
            return 0, f"network: {e}"

def check(entry):
    body = entry.get("body", entry) | {"model": "claude-opus-5-5"}
    beta = entry.get("beta", "")
    found = pass0(body)
    if found or not KEY:
        return found or "pass0: clean (API passes skipped, no key)"
    status, msg = post(API + "/count_tokens",
                       {k: v for k, v in body.items() if k in COUNT_FIELDS}, beta)
    if status in (429, 529, 0):
        return f"unchecked: {status} {msg[:60]}"  # never fall through to the billed pass
    if any(k in msg for k in KNOWN) or os.environ.get("PASS2") != "1":
        return f"pass1: {msg[:90]}" if msg else "pass1: no known rejection"
    body.pop("stream", None)
    (body.get("output_config") or {}).pop("format", None)  # max_tokens: 0 rejects it on its own
    status, msg = post(API, body | {"max_tokens": 0}, beta)
    return f"pass2: {status} {msg[:90]}" if msg else "pass2: accepted"

entries = [json.loads(line) for line in open(sys.argv[1]) if line.strip()]
with ThreadPoolExecutor(max_workers=int(os.environ.get("CONCURRENCY", "4"))) as pool:
    results = list(pool.map(check, entries))
for msg, count in collections.Counter(results).most_common():
    print(f"{count:7d}  {msg}")
```

**Offline diff for history edits.** Replay cannot trigger the prefix check: it applies to
Opus 5.5 thinking blocks, and Opus 5 logs have none. But the edits that would trip it are in
your logs. For each conversation, compare consecutive requests: `system` and `tools` must be
identical, and the earlier request's `messages` must be an exact prefix of the later one's.
Any conversation that fails it would 400 on a new account once it runs on Opus 5.5 and
replays thinking blocks past the edit.

**What only live traffic shows.** Edits your logs do not capture, such as a proxy rewriting
bodies after logging. On the first Opus 5.5 sessions, send the binding header with
`"drop_block"` and alert on `prefix_binding_mismatch`. On an older account you can leave the
field unset and read `thinking_mismatch_allowed` entries instead: what a new account would
reject, without a 400.

## A migration order for Claude Opus 5.5: inventory, replay, change, canary, roll back

1. **Inventory.** Run pass 0 and the offline diff over a week of logs. That sizes the work
   for free.
2. **Replay.** Pass 1 on everything, pass 2 on a 200-request sample
   ([replay](#find-the-requests-that-will-400-before-you-switch-pass-0-count_tokens-and-max_tokens-0)).
3. **Change code.** Read blocks by type and raise `max_tokens`
   ([thinking](#claude-opus-55-rejects-thinkingtypedisabled-thinking-is-always-on));
   replace forced tools ([tool_choice](#forced-tool_choice-returns-400-on-claude-opus-55-count_tokens-included));
   make history append-only ([prefix](#editing-history-before-a-thinking-block-returns-400-on-accounts-created-from-31-august-2026));
   move to the computer toolset where you call the Claude API or Google Cloud; add
   `display: "updates"` with its header; write effort on every hop.
4. **Canary.** New conversations only, with `drop_block` and the binding header. Watch the
   share of `stop_reason: "max_tokens"`, output tokens per request, refusal rate,
   `input_transformations` entries, and p95 latency against the Opus 5 baseline.
5. **Roll back at conversation boundaries.** Send new conversations to Opus 5 and let open
   ones finish where they are. Do not strip thinking blocks on the way back: if a
   conversation returns to 5.5, its reasoning is still readable. Write effort explicitly on
   the rollback hop. `high` matches the quality you had on Opus 5 and costs what Opus 5
   cost; `medium` holds the token budget you tuned on 5.5 and accepts lower quality on
   Opus 5.

Start with pass 0 today. It costs nothing, and it tells you how big step 3 is.

---

## Sources

### platform.claude.com

- [migration guide](https://platform.claude.com/docs/en/models/opus-5-5/migration-guide)
- [What's new in Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/whats-new-opus-5-5)
- [Effort](https://platform.claude.com/docs/en/build-with-claude/effort)
- [Prompting Claude Opus 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#calibrate-effort)
- [Strict tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use)
- [Batch API](https://platform.claude.com/docs/en/build-with-claude/batch-processing)
- [Preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking)
- [Computer use tool compatibility section](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#compatibility)
- [Migrate from computer_20251124](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#migrate-from-computer-20251124)
- [Thinking, Progress updates between tool calls](https://platform.claude.com/docs/en/build-with-claude/thinking#progress-updates)
- [Thinking, Streaming thinking (Claude Platform Docs)](https://platform.claude.com/docs/en/build-with-claude/thinking#streaming-thinking)
- [Refusals and fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models)
- [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting)
- [Count tokens in a Message, API reference](https://platform.claude.com/docs/en/api/messages/count_tokens)
- [Prompt caching, Pre-warming the cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pre-warming-the-cache)

### anthropic.com

- [Introducing Claude Opus 5.5](https://www.anthropic.com/claude-opus-5-5)

### openrouter.ai

- [Claude Opus 5.5 migration guide](https://openrouter.ai/docs/cookbook/evaluate-and-optimize/model-migrations/opus-5-5)
