从 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_tokens→type: "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 开始不允许同时设 temperature 和 top_p。3.x 时代两个可以一起用,现在会报错。挑一个留着。
工具版本更新:text_editor_20250124 要换成 text_editor_20250728,工具名也从 str_replace_editor 变成了 str_replace_based_edit_tool。undo_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