> Markdown mirror of https://router.one/blog/claude-opus-5-5-migration-guide for AI assistants and crawlers. Router One is an OpenAI-compatible LLM API gateway.
> Published: 2026-09-24 · Author: Router One Team

# Migrating to Claude Opus 5.5: Breaking Changes and 400 Fixes

_Move Opus 5 code to claude-opus-5-5: four breaking changes, the exact 400 errors, before/after JSON, what Router One normalizes, and which SDKs are ready._

Claude Opus 5.5 is `claude-opus-5-5`. Moving Opus 5 code onto it takes that model string plus four request changes Anthropic marks as breaking: thinking can no longer be disabled, forced tool use returns HTTP 400, thinking blocks are bound to the model and conversation that produced them, and computer use needs the new `computer_toolset_20260801` tool. On Router One, send the corrected request to `POST https://api.router.one/v1/messages` (or `/v1/chat/completions`) with `"model": "claude-opus-5-5"` and an explicit `max_tokens`; the [Claude Opus 5.5 model page](https://router.one/models/claude-opus-5-5) carries the live rates.

Old code that reaches Opus 5.5 unchanged gets one of these four errors, quoted from Anthropic's [What's new in Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/whats-new-opus-5-5):

```text
"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.
tool_choice: type "tool" and "any" are not supported for this model.
'claude-opus-5-5' does not support tool types: computer_20251124.
```

For Opus 5.5 requests, Router One absorbs the first three: it rewrites legacy `thinking` values to adaptive thinking, removes `temperature`, `top_p` and `top_k`, downgrades a forced `tool_choice` to `auto`, and maps Chat Completions `reasoning_effort` onto `output_config.effort`. Fix your code anyway: Anthropic's API and gateways that forward requests unchanged still return these 400s, and a normalized request is not the one you meant — a "disabled" request still thinks and bills its thinking tokens, and a downgraded tool choice can come back as plain text.

New to Opus 5.5? Start with the [Claude Opus 5.5 API guide](https://router.one/blog/claude-opus-5-5-api-guide); this post covers migration and troubleshooting.

## Migration checklist

Anthropic's [migration guide](https://platform.claude.com/docs/en/models/opus-5-5/migration-guide) has the full list. These items decide whether Opus 5 or older code keeps working; items 5 and 6 mostly catch code from Opus 4.6 or earlier.

1. **Model id.** Send `claude-opus-5-5`; plain HTTP clients can also send the catalog id `anthropic/claude-opus-5.5`. `claude-opus-5.5`, `anthropic/claude-opus-5-5` and `-thinking` variants are rejected.
2. **Thinking.** Delete `{"type": "disabled"}` and `{"type": "enabled", "budget_tokens": N}`. Omit `thinking`, or send `{"type": "adaptive"}`.
3. **Effort.** Set `output_config.effort`: the default fell from `high` on Opus 5 to `medium`.
4. **Tool choice.** Replace `any` and `tool` (on Chat Completions, `"required"` or a named function) with `auto`, mark the tool `"strict": true` and say in the prompt when to use it. Strict tools need `/v1/messages`: the Chat Completions translation does not forward `strict`.
5. **Sampling parameters.** Remove non-default `temperature`, `top_p` and `top_k`.
6. **Prefill.** Don't end `messages` with an assistant turn.
7. **Computer use.** Declare `computer_toolset_20260801` instead of `computer_20251124`; rework the agent loop.
8. **Content blocks.** Read blocks by `type`, never `content[0].text`; send each assistant turn back exactly as returned.
9. **`max_tokens`.** Thinking counts against it: send it on every request, with headroom.
10. **Refusals.** Handle `stop_reason: "refusal"` by retrying on another model in your code.
11. **Billing.** As of the 2026-09-24 plan response, no tier of Pro, Max or Ultra lists `claude-opus-5-5`, so Opus 5.5 calls bill per token to your wallet balance; Claude Opus 5 stays in the Premium models tier of all three plans. The `aws/` and `vertex/` [channel ids](https://router.one/blog/azure-aws-vertex-channel-model-ids) in the 2026-09-24 catalog stop at Opus 5.

A request that passes, on the native Messages endpoint:

```bash
curl https://api.router.one/v1/messages \
  -H "x-api-key: sk-your-api-key" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 16000,
    "stream": true,
    "output_config": {"effort": "medium"},
    "messages": [{"role": "user", "content": "Review this diff for breaking API changes: ..."}]
  }'
```

And on Chat Completions, where `reasoning_effort` stands in for the effort field:

```bash
curl https://api.router.one/v1/chat/completions \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 16000,
    "stream": true,
    "reasoning_effort": "medium",
    "messages": [{"role": "user", "content": "Review this diff for breaking API changes: ..."}]
  }'
```

## Breaking change 1: thinking is always on

Opus 5.5 runs adaptive thinking on every request. Omitting `thinking` equals sending `{"type": "adaptive"}`; `disabled` returns 400 `invalid_request_error`, as does `enabled` with `budget_tokens`. `output_config.effort` (`low`, `medium`, `high`, `xhigh` or `max`) is the only depth control ([effort docs](https://platform.claude.com/docs/en/build-with-claude/effort)). Opus 5 accepted `disabled` at effort `high` or below, so code that worked there fails now.

Before, on Opus 5:

```json
{
  "model": "claude-opus-5",
  "max_tokens": 16000,
  "thinking": {"type": "disabled"},
  "messages": [{"role": "user", "content": "Summarize this changelog in five bullets."}]
}
```

After — thinking stays on, effort sets how much:

```json
{
  "model": "claude-opus-5-5",
  "max_tokens": 16000,
  "output_config": {"effort": "low"},
  "messages": [{"role": "user", "content": "Summarize this changelog in five bullets."}]
}
```

If you disabled thinking to keep reasoning text out of responses, the default already does that: `thinking` blocks arrive empty (`display: "omitted"`), though their tokens still bill as output.

**Through Router One.** For Opus 5.5 the gateway rewrites `{"type": "disabled"}` to adaptive thinking, adding `output_config.effort: "low"` when the request sets no effort, and rewrites `{"type": "enabled", "budget_tokens": N}` (or a bare `budget_tokens`) to adaptive thinking, on both `/v1/messages` and `/v1/chat/completions`. The budget no longer applies: an `enabled` request that sets no effort runs at the default `medium`. The request goes through but still thinks, and bills the thinking as output, so choose the effort yourself.

## Breaking change 2: forced tool use returns 400

Opus 5.5 accepts only `tool_choice` `{"type": "auto"}` (the default) and `{"type": "none"}`. `any` and `tool` return:

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

Before:

```json
{
  "model": "claude-opus-5",
  "max_tokens": 16000,
  "tools": [{
    "name": "get_weather",
    "description": "Current weather for a city",
    "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}
  }],
  "tool_choice": {"type": "tool", "name": "get_weather"},
  "messages": [{"role": "user", "content": "What's the weather in Paris?"}]
}
```

After — `auto`, a strict tool, and the instruction moved into the prompt:

```json
{
  "model": "claude-opus-5-5",
  "max_tokens": 16000,
  "tools": [{
    "name": "get_weather",
    "description": "Current weather for a city",
    "strict": true,
    "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], "additionalProperties": false}
  }],
  "tool_choice": {"type": "auto"},
  "messages": [{"role": "user", "content": "What's the weather in Paris? Use the get_weather tool."}]
}
```

[Strict tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use) guarantees valid input and a valid tool name, not a call. When you need JSON rather than an action, use [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) instead of a forced tool:

```json
{
  "model": "claude-opus-5-5",
  "max_tokens": 16000,
  "output_config": {
    "effort": "low",
    "format": {
      "type": "json_schema",
      "schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}, "summary": {"type": "string"}},
        "required": ["city", "summary"],
        "additionalProperties": false
      }
    }
  },
  "messages": [{"role": "user", "content": "Extract the city and a one-line summary from: ..."}]
}
```

**Through Router One.** For Opus 5.5 the gateway downgrades `tool_choice` `any` and `tool` (`"required"` and a named function on Chat Completions) to `auto`: no 400, but the model is free to answer in text. Check that `stop_reason` is `"tool_use"` (on Chat Completions, that the message carries `tool_calls`) before reading a tool call. Strict tools and `output_config.format` need `/v1/messages`: the Chat Completions translation does not forward `strict`, and its `response_format` is not a reliable way to get JSON from Claude ids.

## Breaking change 3: thinking blocks are bound to their conversation

Every `thinking` block carries a signature tied to the model that wrote it and to everything sent before it, so in a tool loop send each assistant turn back exactly as returned, empty and `redacted_thinking` blocks included. Two errors mean the history changed:

```text
`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified
messages.{i}.content.{j}: 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".
```

The first means your code rebuilt or filtered the assistant turn; the second, that the `system` prompt, `tools` or an earlier message changed between requests. Anthropic enforces this prefix check by default on accounts created on or after August 31, 2026; through a gateway, assume it is on and keep history append-only. To recover, send the `thinking-binding-controls-2026-08-01` beta header with `prefix_mismatch_behavior: "drop_block"`, or strip every `thinking` and `redacted_thinking` block from the history and retry once ([thinking troubleshooting](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting)).

An assistant turn at the default display — send it back as is:

```json
{
  "role": "assistant",
  "content": [
    {"type": "thinking", "thinking": "", "signature": "EqQBCkYIBxgCKkA..."},
    {"type": "tool_use", "id": "toolu_01A", "name": "get_weather", "input": {"city": "Paris"}}
  ]
}
```

A tool loop that follows every rule above, with the Anthropic Python SDK:

```python
import anthropic

client = anthropic.Anthropic(
    base_url="https://api.router.one",
    api_key="sk-your-api-key",
)

tools = [{
    "name": "get_weather",
    "description": "Current weather for a city",
    "strict": True,
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
        "additionalProperties": False,
    },
}]
messages = [{"role": "user", "content": "What's the weather in Paris? Use the get_weather tool."}]

while True:
    response = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=16000,
        output_config={"effort": "medium"},
        tools=tools,
        messages=messages,
    )
    # Append the assistant turn exactly as returned, thinking blocks included.
    messages.append({"role": "assistant", "content": response.content})
    if response.stop_reason != "tool_use":
        break
    results = [
        {"type": "tool_result", "tool_use_id": block.id, "content": "Light rain, 18 degrees"}
        for block in response.content
        if block.type == "tool_use"
    ]
    messages.append({"role": "user", "content": results})

print(response.stop_reason)
print("".join(block.text for block in response.content if block.type == "text"))
```

**Through Router One.** `/v1/messages` forwards the thinking blocks you send back unchanged, except when an upstream failure moves the request to another route for the same model: that retry drops them, without an error, and the turn loses the earlier reasoning. The Chat Completions translation returns thinking as `reasoning_content` but never replays it on the next turn, so tool loops work without the earlier reasoning. Run multi-turn tool loops on `/v1/messages`.

## Breaking change 4: computer use moves to a toolset

On the Claude API and Google Cloud, Opus 5.5 rejects the previous computer tool with an error that begins:

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

Before — sent with the `anthropic-beta: computer-use-2025-11-24` header:

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

After — no beta header, and the entry carries no name or display size:

```json
{
  "tools": [{"type": "computer_toolset_20260801"}]
}
```

The loop changes too: the action name moves from `input.action` to each `tool_use` block's `name`, one turn can hold several such blocks, and every result carries `toolset_name`. The toolset rejects `"strict": true`.

**Through Router One.** `/v1/messages` passes tool definitions through unchanged, so the toolset goes through and `computer_20251124` is rejected. Chat Completions carries function tools only, so computer use needs `/v1/messages`.

## Three older rules that catch code from earlier models

**Thinking budgets.** `{"type": "enabled", "budget_tokens": N}` returns 400 on Claude 4.7 and later models, Opus 5 included; Anthropic lists it for code from Opus 4.6 or earlier. Replace it as in breaking change 1:

```json
{
  "model": "claude-opus-4-6",
  "max_tokens": 16000,
  "thinking": {"type": "enabled", "budget_tokens": 10000},
  "messages": [{"role": "user", "content": "Summarize this changelog in five bullets."}]
}
```

**Sampling parameters.** Non-default `temperature`, `top_p` or `top_k` return 400 on Opus 4.7 and later Opus models, Opus 5 included, which catches code from Opus 4.6 or earlier and OpenAI-style clients that send `temperature` by default. Router One removes them for Opus 5.5; remove them in your code too.

**Prefill.** Opus 5.5 rejects `messages` that end with an assistant turn (Anthropic files this under code from Opus 4.5 or earlier). Move format instructions to the system prompt or use `output_config.format`. Router One does not rewrite prefill either, so remove it from your code rather than relying on how a given route handles it.

## Behavior changes that break assumptions, not requests

**Default effort is `medium`.** Opus 5 defaulted to `high`. If your results depended on that, set `"output_config": {"effort": "high"}`, then compare cost and quality at `medium`. Router One passes `output_config.effort` through unchanged on `/v1/messages`; on `/v1/chat/completions` it maps `reasoning_effort` to it for Opus 5.5, with `none` and `minimal` becoming `low`.

**More thinking per turn.** At the same effort Opus 5.5 thinks more than Opus 5, and thinking counts against `max_tokens`. Anthropic suggests starting at 64k for `xhigh` or `max`; its [Opus 5.5 prompting guide](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5) reports that 128,000, the output ceiling, has worked well for long agentic coding turns. Stream long runs ([streaming guide](https://router.one/llm-streaming)). Through Router One, send `max_tokens` on every request and keep your wallet balance comfortable: when the balance cannot cover a request's prepaid estimate, the gateway lowers `max_tokens`, which can cut a long answer short. Measure cost per request at your chosen effort before moving production traffic; the [Opus 5.5 vs Opus 5 comparison](https://router.one/models/compare/claude-opus-5-5-vs-claude-opus-5) shows both models' live Router One rates.

**Narration between tool calls lives in thinking blocks.** Opus 5.5's short progress text between tool calls now arrives in `thinking` blocks, empty at the default `display: "omitted"`. To show it, set `thinking: {"type": "adaptive", "display": "summarized"}` (or `"updates"` with the `thinking-display-updates-2026-08-18` beta header) and render non-empty thinking blocks ([thinking display](https://platform.claude.com/docs/en/build-with-claude/thinking)). Router One's `/v1/messages` passes `thinking.display` and `anthropic-beta` through unchanged; `/v1/chat/completions` does not forward `anthropic-beta`, so `updates` needs `/v1/messages`.

**Refusals are a stop reason.** A refusal is HTTP 200 with `stop_reason: "refusal"` and a `stop_details.category`; new beside `"cyber"` are `"bio"` and `"reasoning_extraction"`, the latter for prompts that push the model to reveal its reasoning. Anthropic suggests a fallback: the beta server-side `fallbacks` parameter, its SDK middleware, or your own retry. Don't send `fallbacks` through Router One: wallet billing rejects it with HTTP 400 before the request reaches the model. Router One does not answer an Opus 5.5 request with another model either, so retry in your own code, and return `reasoning_extraction` refusals as they are, as Anthropic's server-side fallback does:

```python
response = client.messages.create(
    model="claude-opus-5-5", max_tokens=16000, messages=messages
)
if (
    response.stop_reason == "refusal"
    and response.stop_details.category != "reasoning_extraction"
):
    response = client.messages.create(
        model="claude-opus-5", max_tokens=16000, messages=messages
    )
```

Keep the thinking blocks in `messages` when you switch (see the next section); [fallback strategies in production](https://router.one/blog/llm-fallback-strategies-production) covers when a cross-model retry is worth it.

## Switching models mid-conversation

A thinking block is readable only by the model that produced it and a fixed set of others; the API silently drops, and does not bill, a block the target model cannot read. Opus 5.5 reads blocks from Opus 5 and earlier Opus, Sonnet and Haiku models, so moving an Opus 5 conversation up keeps its reasoning. As of 2026-09-24 no other Claude id in the Router One catalog reads Opus 5.5's blocks, so switching down to Opus 5 or Sonnet 5 continues without the earlier reasoning; Opus 5.5 does not read Claude Fable 5's blocks either. Keep one model per conversation where you can, and switch at a task boundary, not mid-loop.

If Router One retries an Opus 5.5 request after an upstream failure, the retry stays on Opus 5.5, and a 400 is never retried or answered by another model, so for requests that name a model id, any model switch in Dashboard → Logs came from your code ([per-request observability](https://router.one/llm-observability)).

## Opus 5.5 400 error lookup

| Error text or symptom | Cause | Fix |
| --- | --- | --- |
| `"thinking.type.disabled" is not supported for this model` | `thinking: {"type": "disabled"}` | Omit `thinking`; use `output_config.effort: "low"` |
| `"thinking.type.enabled" is not supported for this model` | `budget_tokens` thinking | `{"type": "adaptive"}` plus an effort level |
| `tool_choice: type "tool" and "any" are not supported for this model.` | Forced tool use | `tool_choice` `auto`, strict tool, instruction in the prompt |
| Begins `'claude-opus-5-5' does not support tool types: computer_20251124.` | Old computer tool | `{"type": "computer_toolset_20260801"}` and the new loop |
| `` `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified `` | Assistant turn rebuilt or filtered | Send the turn back exactly as returned |
| `` Invalid `signature` in `thinking` block. The block is bound to a different conversation. `` | `system`, `tools` or an earlier turn changed | Append-only history; `drop_block`, or strip thinking blocks and retry once |
| 400 `invalid_request_error` on a request with `temperature`, `top_p` or `top_k` | Non-default sampling parameter | Remove the parameter |
| 400 on a request whose `messages` end with an assistant turn | Prefill | System-prompt instruction or `output_config.format` |
| `model 'claude-opus-5.5' not supported, check /v1/models for available models` | HTTP 404: id spelling on Router One | `claude-opus-5-5` or `anthropic/claude-opus-5.5` |
| `request includes features that cannot be safely prepaid for balance billing` … `(unsupported: fallbacks)` | `fallbacks` sent to Router One | Remove it; retry on another model in your code |
| `must be called via /v1/messages or /v1/chat/completions` | A Claude id sent to `/v1/responses` | Use one of those two endpoints |
| HTTP 200, `stop_reason: "refusal"` | Safety classifier | Read `stop_details`; retry on another model |
| HTTP 200, `stop_reason: "max_tokens"`, little or no text | Thinking used up `max_tokens` | Raise `max_tokens`, lower effort, check the wallet balance |

For Opus 5.5, Router One normalizes the requests behind the two thinking rows, the `tool_choice` row and the sampling-parameter row, so those errors appear only when you call Anthropic directly or through a gateway that forwards requests unchanged. Other upstream 400s usually keep Anthropic's text on non-streaming `/v1/messages`. On streaming `/v1/messages` and on `/v1/chat/completions`, validation messages that start with a request field, such as the thinking-signature errors, now come through as well; other 400s there, the computer-use error included, arrive as the generic `invalid request (upstream rejected with status 400)`. The [API error codes page](https://router.one/llm-api-error-codes) covers status codes that are not specific to Opus 5.5, and the [API compatibility facts](https://router.one/facts/api-compatibility.md) list the endpoint rules per model family.

## Clients and SDKs as of 2026-09-24

Whether a client breaks depends on whether its code knows Opus 5.5 by name. The rows describe each project's own code as of 2026-09-24, not Router One behavior; through Router One most of them no longer end in a 400 (see above), but the fixes still matter everywhere else.

**Coding tools**

| Tool | Knows Opus 5.5 | What to watch |
| --- | --- | --- |
| [Claude Code](https://router.one/claude-code-china) | v2.1.280 or later; `opus` and `default` resolve to Opus 5.5 | Recognizes Opus 5.5 by its official id; with the catalog id it applies Opus 5 defaults. Use `claude-opus-5-5` or `/model opus`. Thinking cannot be turned off, and effort defaults to `medium` |
| Codex CLI | Not possible | Speaks only the Responses API, and Router One serves Claude ids on `/v1/messages` and `/v1/chat/completions`, not `/v1/responses` |
| [Cline](https://router.one/integrations/cline) | CLI 3.0.65 and `@cline/llms` 0.0.86; not yet the VS Code extension 4.1.20 | Never sets `tool_choice`. On its Anthropic provider, switching reasoning off can send `thinking` disabled; the OpenAI Compatible setup in our guide is unaffected |
| [Roo Code](https://router.one/integrations/roo-code) | No — last release 3.54.0, project sunset | Its Anthropic provider lists models up to Opus 4.6, swaps an unknown id for its default Sonnet 4.5 model, and sends a budget when reasoning is on. Use the OpenAI Compatible provider and leave the reasoning budget off |
| [Continue](https://router.one/integrations/continue) | No (2.1.0) | With its Anthropic provider, `reasoning: true` sends `enabled` with a budget. Our guide uses the OpenAI provider, where this is unverified; leave reasoning off either way |
| [Aider](https://router.one/integrations/aider) | No (0.86.2) | Sends `temperature` 0 for models it does not know, and `--thinking-tokens` sends a budget. Add `use_temperature: false` for the model in `.aider.model.settings.yml` and skip `--thinking-tokens` |
| [Zed](https://router.one/integrations/zed) | 1.21.0, in its built-in Anthropic provider | In the openai_compatible setup from our guide, list the model as `claude-opus-5-5` |
| [Goose](https://router.one/integrations/goose) | v1.52.0 | With its Anthropic provider it never sends `disabled`, and sends effort `high` by default rather than `medium`. Our guide uses the OpenAI provider, where this is unverified |
| [OpenCode](https://router.one/integrations/opencode), [Kilo Code](https://router.one/integrations/kilo-code) | OpenCode 1.18.32, Kilo Code 7.7.9 | Adaptive thinking without a budget; they force `tool_choice` `"required"` only when you ask for JSON-schema structured output |

**SDKs and frameworks**

| Library | Knows Opus 5.5 | What to watch |
| --- | --- | --- |
| [Vercel AI SDK](https://router.one/integrations/vercel-ai-sdk), `@ai-sdk/anthropic` | 4.0.60 (3.0.120 and 2.0.103 on the older lines) | Maps reasoning off to effort `low` and forced tool choice to `auto`, with a warning — but matches the id by substring, so the dotted catalog id is treated as Opus 5. Use `claude-opus-5-5` |
| LiteLLM | Main-branch model map; the map bundled with 1.102.1 lacks it | Forced `tool_choice` raises a client-side error unless `drop_params=True`, which downgrades it to `auto`. Use `claude-opus-5-5` so the model map matches |
| [LangChain](https://router.one/integrations/langchain), `langchain-anthropic` | 1.7.3 | `with_structured_output` no longer forces a tool (it warns and suggests `method="json_schema"`); `bind_tools(tool_choice="any")` and `create_agent` with `ToolStrategy` still force one. Use `method="json_schema"`, and `claude-opus-5-5`, which the fix matches by prefix |
| Instructor | Not fixed in 1.17.0 | Its default tools mode forces a named tool; pass `tool_choice={"type": "auto"}` explicitly |
| [PydanticAI](https://router.one/integrations/pydantic-ai) | `pydantic-ai-slim` 2.48.0 | Softly downgrades its own tool requirement to `auto`; an explicit `tool_choice='required'` raises `UserError`. Use `output_type=NativeOutput(...)` |
| [LlamaIndex](https://router.one/integrations/llamaindex), `llama-index-llms-anthropic` | No (0.12.0) | `claude-opus-5-5` raises `ValueError: Unknown model`, and `structured_predict` forces tool choice `any`; use the Anthropic SDK's structured outputs for now |

Model pinning, plan quota and the 1M window in Claude Code are covered in [Claude Code on Opus 5.5](https://router.one/blog/claude-code-opus-5-5-setup).

## FAQ

**Why does my Opus 5 code return 400 on Claude Opus 5.5?**
Opus 5.5 rejects four things Opus 5 accepted: thinking set to disabled, tool_choice any or tool, the computer_20251124 tool, and thinking blocks replayed after the conversation prefix changed. Use output_config.effort, tool_choice auto, the computer_toolset_20260801 toolset and append-only history instead.

**My Opus 5 code sends thinking disabled. What should it send now?**
Omit thinking, or send type adaptive, and set output_config.effort to low for the lightest thinking; Opus 5.5 cannot turn it off. At the default display the thinking blocks carry no text, but their tokens still bill as output.

**Does Router One fix these errors for me?**
For Opus 5.5 it rewrites legacy thinking values to adaptive thinking, removes temperature, top_p and top_k, turns a forced tool_choice into auto and maps reasoning_effort to output_config.effort. It does not rewrite prefill, the old computer tool or edited thinking blocks, which Anthropic's API rejects. Fix the code anyway, so it does what you meant everywhere.

**How do I make Opus 5.5 call a specific tool now?**
You cannot force it. Use tool_choice auto and a strict tool on /v1/messages (the Chat Completions translation does not forward strict), say in the prompt when the tool applies, and check that stop_reason is tool_use. For JSON rather than an action, use output_config.format on /v1/messages.

**Can I still send temperature or top_p to Claude Opus 5.5?**
Only at their defaults: non-default values return 400 on Opus 4.7 and later Opus models, Opus 5.5 included. Router One removes them for Opus 5.5, but delete them in your code and watch for clients that add temperature on their own, such as Aider.

**What does "The block is bound to a different conversation" mean?**
A replayed thinking block no longer matches its context: the system prompt, the tools or an earlier message changed. Keep history append-only; to continue, send the thinking-binding-controls-2026-08-01 beta header with prefix_mismatch_behavior set to drop_block, or strip all thinking and redacted_thinking blocks and retry once.

**What should my code do when Opus 5.5 refuses?**
It is HTTP 200 with stop_reason refusal and a stop_details.category. Retry on another model in your code, such as claude-opus-5, except for reasoning_extraction refusals. Don't send Anthropic's fallbacks parameter, which wallet billing rejects with HTTP 400; for a request that names claude-opus-5-5, Router One never answers with a different model.

**Can I switch one conversation between Opus 5.5 and Opus 5?**
Yes, but reasoning carries only one way: Opus 5.5 reads Opus 5's thinking blocks, while Opus 5 cannot read Opus 5.5's, so the API drops them silently and does not bill them. Switch at a task boundary.

## Next steps

- First call: the [Claude Opus 5.5 API guide](https://router.one/blog/claude-opus-5-5-api-guide) covers the model id, endpoints and SDK setup.
- Claude Code: [Claude Code on Opus 5.5](https://router.one/blog/claude-code-opus-5-5-setup) covers model pinning, plans and the 1M context window; the [Claude Code setup guide](https://router.one/blog/claude-code-setup-guide) covers a fresh install.
- Live specs and rates: [Opus 5.5 vs Opus 5](https://router.one/models/compare/claude-opus-5-5-vs-claude-opus-5), [Opus 5.5 vs Claude Sonnet 5](https://router.one/models/compare/claude-opus-5-5-vs-claude-sonnet-5) and [Opus 5.5 vs GPT-6 Sol](https://router.one/models/compare/claude-opus-5-5-vs-gpt-6-sol).
- Check plan coverage on the [pricing page](https://router.one/pricing), and give the key you migrate with a `maxSpend` cap: it cannot spend past that amount and your other keys keep working ([per-key cost tracking](https://router.one/llm-cost-tracking)). Requests reach `api.router.one` from mainland China without a VPN.

## See also

- Canonical page: https://router.one/blog/claude-opus-5-5-migration-guide
- LLM API Gateway and Routing: https://router.one/llm-api-gateway
- All blog posts: https://router.one/blog
- Models and per-model token rates: https://router.one/models (markdown: https://router.one/models.md)
- Pricing: https://router.one/pricing
- API docs (markdown): https://router.one/docs.md
- Company facts: https://router.one/facts/company.md
