从 Opus 4.5 迁移到 4.6:这些 Breaking Change 不处理会直接 400

从 Opus 4.5 迁移到 4.6:这些 Breaking Change 不处理会直接 400

Anthropic 说 Opus 4.6 是"近似直接替换"。大部分情况下确实是——换个 model ID 就能跑。但有几个改动,如果你不知道,上线就会炸。

我把官方迁移指南和实际踩坑的经验整理了一遍,按"必须改"和"建议改"分两层说。

必须改:不改直接报错

1. Prefill 被移除了

这是最大的 breaking change。

以前你可以在请求的最后一条 assistant 消息里"塞"一段开头,强制模型从你指定的地方接着写。比如你想让它输出 JSON,就预填一个 {

# 以前能用,现在直接 400
messages=[
    {"role": "user", "content": "列出三个城市"},
    {"role": "assistant", "content": '{"cities": ['}  # prefill
]

Opus 4.6 不支持这个了。发了就返回 400 错误,不是降级、不是忽略,是直接拒绝。

替代方案有两个:

用 Structured Outputs:如果你 prefill 是为了控制输出格式,现在有更好的办法。

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=4096,
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "cities": {"type": "array", "items": {"type": "string"}}
                }
            }
        }
    },
    messages=[{"role": "user", "content": "列出三个城市"}]
)

用 System Prompt 引导:在 system 消息里明确要求输出格式。没有 prefill 那么精确,但对大部分场景够了。

如果你的代码库比较大,建议先全局搜一下所有构建 messages 的地方,找出最后一条 role 是 assistant 的请求——这些都是潜在的 prefill 点。

2. Tool Call 的 JSON 转义变了

Opus 4.6 在生成工具调用参数时,JSON 字符串的转义方式可能和 4.5 不一样。比如 Unicode 转义符、正斜杠的处理。

如果你用 json.loads()JSON.parse() 解析,不用担心——标准解析器能处理这些差异。

但如果你的代码里有用字符串匹配、正则提取、或者手动解析 tool call 的 input 字段的逻辑,一定要测一遍。我见过有人用正则从 tool call 里提取文件路径,4.6 换了转义方式之后正则就匹配不上了。

建议改:不改能跑,但越早改越好

3. Thinking 参数迁移

以前的写法:

response = client.beta.messages.create(
    model="claude-opus-4-5",
    max_tokens=16000,
    thinking={"type": "enabled", "budget_tokens": 32000},
    betas=["interleaved-thinking-2025-05-14"],
    messages=[...]
)

现在的写法:

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=16000,
    thinking={"type": "adaptive"},
    messages=[...]
)

变化有四点:

  • type: "enabled" + budget_tokenstype: "adaptive"(手动预算被弃用了)
  • 不再需要 betas=["interleaved-thinking-2025-05-14"],adaptive 自动启用交错思考
  • client.beta.messages.create 变成 client.messages.create(正式 GA,不用 beta 命名空间)
  • 用 effort 参数(low/medium/high/max)代替 budget_tokens 来控制思考深度

旧写法在 4.6 上还能跑,但 Anthropic 明确说了"will be removed in a future model release"。趁这次迁移一起改掉,省得下次再折腾。

4. 清理过期的 Beta Headers

以下三个 beta header 在 4.6 上已经没用了,发了也会被忽略:

  • effort-2025-11-24(effort 已 GA)
  • fine-grained-tool-streaming-2025-05-14(已 GA)
  • interleaved-thinking-2025-05-14(adaptive thinking 自动启用)

不删不影响功能,但留着会让代码维护的人困惑。

5. output_format → output_config.format

如果你用了 Structured Outputs,参数位置改了:

# 旧写法(还能用,但已弃用)
response = client.messages.create(
    output_format={"type": "json_schema", "schema": {...}},
    ...
)

# 新写法
response = client.messages.create(
    output_config={"format": {"type": "json_schema", "schema": {...}}},
    ...
)

从更老的版本迁移

如果你不是从 4.5,而是从 Opus 4.1、Sonnet 4 或更早的模型跳到 4.6,还有几个额外的坑:

sampling 参数冲突:Claude 4 开始不允许同时设 temperaturetop_p。3.x 时代两个可以一起用,现在会报错。挑一个留着。

工具版本更新text_editor_20250124 要换成 text_editor_20250728,工具名也从 str_replace_editor 变成了 str_replace_based_edit_toolundo_edit 命令被移除了。

新的 stop_reason:要处理两个新值——refusal(模型拒绝回答)和 model_context_window_exceeded(上下文满了)。以前这两种情况的行为不一样。

迁移清单

直接抄走:

  • model ID 换成 claude-opus-4-6
  • 全局搜索 assistant prefill,替换为 structured outputs 或 system prompt
  • 检查 tool call 解析逻辑,确认用的是标准 JSON parser
  • thinking 参数改成 {"type": "adaptive"}
  • 删除三个过期 beta header
  • output_format 迁移到 output_config.format
  • (从 4.1 或更早迁移)检查 temperature/top_p 冲突
  • (从 4.1 或更早迁移)更新工具版本
  • (从 4.1 或更早迁移)处理 refusal 和 context_window_exceeded stop_reason
  • 在测试环境验证,特别关注工具调用场景

先在 staging 跑一周再上生产。这次改动数量不多,但 prefill 那个坑,命中了就是 500 级别的事故。


参考链接

  • 官方迁移指南:https://platform.claude.com/docs/en/about-claude/models/migration-guide
  • What's New in Claude 4.6:https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-6
← 返回博客列表