---
title: "How to Migrate to the Claude Opus 5 API: Breaking Changes, 400 Errors, and a Production Checklist"
description: "A Claude Opus 5 migration guide from a team that did it on launch day. Every breaking change in the claude-opus-5 API, the exact 400 errors you'll hit coming from Opus 4.8, and the fixes with working Python code."
image: "https://foundrysoft.co/api/og?type=article&title=How+to+Migrate+to+the+Claude+Opus+5+API%3A+Breaking+Changes%2C+400+Errors%2C+and+a+Production+Checklist&cat=AI+Engineering&rt=10+min+read&au=Varun+Raj+Manoharan&dt=2026-07-25"
url: "https://foundrysoft.co/blog/migrating-production-agents-to-claude-opus-5"
---

AI Engineering 2026-07-25 10 min read

# How to Migrate to the Claude Opus 5 API: Breaking Changes, 400 Errors, and a Production Checklist

A Claude Opus 5 migration guide from a team that did it on launch day. Every breaking change in the claude-opus-5 API, the exact 400 errors you'll hit coming from Opus 4.8, and the fixes with working Python code.

![Varun Raj Manoharan](https://foundrysoft.co/images/about/founder.webp)

Varun Raj Manoharan

Claude Opus 5 Anthropic Claude API Migration Agents Python

Anthropic released Claude Opus 5 yesterday. The pricing stayed at Opus 4.8 levels ($5 input / $25 output per million tokens), the context window stayed at 1M tokens with 128K max output, the knowledge cutoff moved to May 2026, and the benchmarks in the announcement beat Fable 5 in several places at half its price. Anthropic is positioning it as the default model for agentic coding and enterprise work.

We run several client agent stacks on `claude-opus-4-8`, so I spent launch day migrating them. If you searched "how to migrate to Claude Opus 5" and landed here, this is the complete list of what breaks, why, and what we changed. The model ID swap takes one line. The other four changes are where the real work is.

### Breaking change 1: thinking is now on by default

On Opus 4.8, a request without a `thinking` field ran without thinking. On Opus 5, the same request runs with adaptive thinking enabled. Nothing errors and your code appears to work. The problem is that `max_tokens` caps total output, thinking plus response text, so a request that fit comfortably in `max_tokens: 4096` yesterday can spend most of that budget thinking and come back truncated with `stop_reason: "max_tokens"`.

We hit this on a summarization route that had `max_tokens: 2000` and no `thinking` field. It started returning summaries that stopped mid-sentence. You have two options:

Python

Copy

```python
# Option A: keep thinking, give it room
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=16000,  # was 2000; thinking counts against this now
    messages=[{"role": "user", "content": doc}],
)

# Option B: restore the old no-thinking behavior explicitly
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=2000,
    thinking={"type": "disabled"},
    output_config={"effort": "high"},
    messages=[{"role": "user", "content": doc}],
)
```

One catch on Option B cost me twenty minutes: disabling thinking only works at effort `high` or below. Combine `thinking: {"type": "disabled"}` with `effort: "xhigh"` or `"max"` and the API returns a 400. Anthropic coupled these on purpose. The extra capability at the top effort levels comes from reasoning, so you can't have one without the other.

### Breaking change 2: temperature and top_p return 400 errors

`temperature`, `top_p`, and `top_k` are gone. Any non-default value is a hard 400, the same as on Opus 4.7 and 4.8. We still had one legacy classification route pinned to `temperature: 0.2` from the Opus 4.6 days, and it died immediately after the model swap.

The replacement is prompting. If you were using low temperature for consistency, you probably need nothing at all, because Opus 5 follows instructions more literally than any Claude before it. If you were using high temperature for variety, ask for variety in the system prompt ("vary your phrasing and structure across responses"). This felt wrong to me for about a day. Then I noticed the outputs were more controllable than they ever were with sampling knobs.

### Breaking change 3: assistant prefills return 400 errors

If you're coming from anything older than the 4.6 family, the prefill trick of ending `messages` with a partial assistant turn like `{"role": "assistant", "content": "{\"category\": \""}` is a 400 on Opus 5. Structured outputs replace it, and the schema is enforced rather than hinted:

Python

Copy

```python
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "category": {"type": "string", "enum": ["billing", "technical", "sales"]},
                    "urgency": {"type": "integer", "enum": [1, 2, 3]},
                },
                "required": ["category", "urgency"],
                "additionalProperties": False,
            },
        }
    },
    messages=[{"role": "user", "content": ticket_text}],
)
```

### Breaking change 4, the silent one: Claude Opus 5 token counts

Opus 5 uses the tokenizer introduced with Opus 4.7. Migrating from 4.7 or 4.8? Counts are roughly unchanged. Jumping from Opus 4.6 or older? The same text produces roughly 1x to 1.35x more tokens, which quietly shifts every token-denominated assumption in your stack: `max_tokens` values, compaction triggers, cost dashboards, rate-limit math. Skip the blanket multiplier and run `client.messages.count_tokens()` against `claude-opus-5` on a representative sample of your real prompts.

### What the Claude Opus 5 API adds

The migration isn't all defensive. We turned on three new capabilities the same day.

**Mid-conversation system messages.** You can now append `{"role": "system", "content": "..."}` to the `messages` array after a user turn. This is the right way to inject operator instructions mid-session. It preserves your cached prefix instead of invalidating it the way editing the top-level `system` prompt does, and the model treats it with system authority rather than as user text.

**Refusal fallbacks.** Opus 5 ships with real-time cybersecurity classifiers, and a declined request comes back as HTTP 200 with `stop_reason: "refusal"`. The new beta `fallbacks: "default"` parameter re-runs a refused request automatically. We wrote a separate post on building refusal-resilient pipelines, because for security-adjacent work it deserves one.

**A lower prompt caching minimum.** The floor for cacheable prompts dropped from 1,024 tokens to 512. Several of our smaller tool-heavy prompts that silently never cached now do. No code change needed. The `cache_control` markers we already had just started working.

### One prompt change worth making

Opus 5 self-verifies. All the "double-check your output against the schema before responding" lines we accumulated over two years of prompt engineering now cause over-verification, where the model checks its work twice and bills you for both passes. We deleted them route by route and A/B tested against the old prompts. The shorter prompts won on cost and latency with no quality drop. The least intuitive migration advice I can offer: your Opus 5 prompts should be shorter than your Opus 4.8 prompts.

### The Claude Opus 5 migration checklist we used

1.  Swap the model ID to `claude-opus-5`
2.  Find every request with no `thinking` field; raise `max_tokens` or disable thinking explicitly
3.  Audit for `thinking: disabled` combined with effort above `high` (400 error)
4.  Strip `temperature`, `top_p`, `top_k` (400 error)
5.  Replace prefills with `output_config.format` (400 error)
6.  Re-baseline token counts with `count_tokens` if coming from Opus 4.6 or older
7.  Delete self-verification scaffolding from prompts
8.  Add `stop_reason == "refusal"` handling before reading `content`

Total time for our stack was one afternoon, most of it spent rerunning evals rather than editing code. The 400 errors are the easy part because they announce themselves. The silent thinking-by-default change is the one that will bite teams who swap the model ID, see green tests, and call the migration done.

#### Related reading

[MCP Went Stateless: Migrating Your Server to the 2026-07-28 Spec

The 2026-07-28 MCP revision removes sessions, the initialize handshake, and server-initiated requests. Here's what actually breaks in your server, the new wire format, the requestState and MRTR patterns that replace sessions, and the SDK v2 migration path.

MCP Model Context Protocol AI Agents

](https://foundrysoft.co/blog/mcp-stateless-spec-migration)[Claude Opus 5 vs Grok 4.5 vs Muse Spark 1.1: Which Agentic Model to Use in 2026

An independent comparison of the three agentic models that launched this month. Real pricing, production failure modes, cost per completed task, and the routing table we actually run, not a benchmark aggregation.

Claude Opus 5 Grok 4.5 Muse Spark

](https://foundrysoft.co/blog/claude-opus-5-vs-grok-4-5-vs-muse-spark-comparison)[Claude Opus 5 Batch API Tutorial: AI Contract Data Extraction at Scale, with Real Costs

A step-by-step tutorial for bulk AI document extraction with the Claude Opus 5 Batch API: structured outputs with JSON schemas, 50% batch pricing, the 300K output beta, and the real cost of processing 40,000 vendor contracts.

Claude Opus 5 Anthropic Batch API

](https://foundrysoft.co/blog/claude-opus-5-batch-api-contract-extraction)

#### Next Article

[

How to Build a Computer Use Agent with Muse Spark 1.1: Cross-Application Workflows That Actually Finish

](https://foundrysoft.co/blog/muse-spark-computer-use-agent-cross-application)

Available for new projects

## Let's build something great.

Have a project in mind? We are an elite software and AI development studio ready to bring your ideas to production. Let's talk about your roadmap.

Start a Project [See our work](https://foundrysoft.co/work)

```json
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "FoundrySoft",
  "url": "https://foundrysoft.co",
  "logo": "https://foundrysoft.co/logo.svg",
  "description": "FoundrySoft builds production-grade software and AI systems for US companies, from an India-based team of senior engineers.",
  "sameAs": [
    "https://github.com/foundrysofthq",
    "https://www.linkedin.com/company/foundrysoft",
    "https://www.instagram.com/foundrysoft/"
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "FoundrySoft",
  "url": "https://foundrysoft.co"
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "How to Migrate to the Claude Opus 5 API: Breaking Changes, 400 Errors, and a Production Checklist",
  "description": "A Claude Opus 5 migration guide from a team that did it on launch day. Every breaking change in the claude-opus-5 API, the exact 400 errors you'll hit coming from Opus 4.8, and the fixes with working Python code.",
  "url": "https://foundrysoft.co/blog/migrating-production-agents-to-claude-opus-5",
  "mainEntityOfPage": "https://foundrysoft.co/blog/migrating-production-agents-to-claude-opus-5",
  "image": [
    "https://foundrysoft.co/api/og?type=article&title=How+to+Migrate+to+the+Claude+Opus+5+API%3A+Breaking+Changes%2C+400+Errors%2C+and+a+Production+Checklist&cat=AI+Engineering&rt=10+min+read&au=Varun+Raj+Manoharan&dt=2026-07-25"
  ],
  "datePublished": "2026-07-25",
  "dateModified": "2026-07-25",
  "keywords": "Claude Opus 5, Anthropic, Claude API, Migration, Agents, Python",
  "author": {
    "@type": "Person",
    "name": "Varun Raj Manoharan"
  },
  "publisher": {
    "@type": "Organization",
    "name": "FoundrySoft",
    "logo": {
      "@type": "ImageObject",
      "url": "https://foundrysoft.co/logo.svg"
    }
  }
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://foundrysoft.co/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog",
      "item": "https://foundrysoft.co/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "How to Migrate to the Claude Opus 5 API: Breaking Changes, 400 Errors, and a Production Checklist",
      "item": "https://foundrysoft.co/blog/migrating-production-agents-to-claude-opus-5"
    }
  ]
}
```
