如果你把代码升级到了 Claude Opus 5,然后莫名其妙开始收到 400 错误,原因很可能是一个特定的组合:禁用 thinking 的同时把 effort 设为 xhigh 或 max。这是 Anthropic 官方文档记录的新规则,Opus 4.8 上并不存在。
Claude Opus 5 上的这个 400 错误是什么意思?
意味着你的请求同时要求了两件互相冲突的事。Anthropic 的官方文档说得很直接:
"On Claude Opus 5, thinking cannot be disabled atxhighormaxeffort: requests that setthinking: {"type": "disabled"}at those levels return a 400 error."(platform.claude.com/docs/en/build-with-claude/effort,查询于 2026-09-09)
翻译过来:在 Opus 5 上,只有 effort 设为 high 或更低时才能关闭 thinking。在 xhigh 或 max 级别下,模型强制要求 thinking 处于开启状态,API 会在处理任何内容之前就拒绝这个请求。
为什么这偏偏在从 Opus 4.8 迁移后就出问题了?
因为 Opus 4.8 上没有这个限制:禁用 thinking 和 effort 级别是相互独立的,所以可以在 max 下关闭 thinking 而不出问题。谁的代码里有这种写法(常见于为了降低延迟或强制固定输出格式而禁用 thinking 的流水线),把 model 换成 claude-opus-5 却没动其他任何东西,就会正好在 effort 最高的那些调用上开始收到 400,而这些往往是流程里最关键的调用。
还有一点值得注意:如果你只是省略 thinking 字段而不是显式禁用它,不同模型的行为也不一样:在 Opus 4.8 上,请求会在不开启 thinking 的情况下运行;在 Opus 5 上,同样的请求默认会以自适应 thinking 运行。这会影响 max_tokens 预算,因为在 Opus 5 上它是 thinking 加上回复文本合计的硬性上限。
现在该怎么修,用对的命令
有两条出路,取决于你到底需要什么。
如果你能接受 thinking 保持开启(大多数情况都是这样),把请求里的 thinking 字段去掉,xhigh 或 max 保持不变:
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-5",
"max_tokens": 65536,
"output_config": {"effort": "xhigh"},
"messages": [{"role": "user", "content": "..."}]
}'
官方文档本身建议,Opus 5 在 xhigh 或 max 任务下 max_tokens 从 6.4 万 token 起步,因为模型需要在这同一个上限内为思考、调用工具和子代理留出空间。
如果你确实需要关闭 thinking(比如需要固定输出格式),正确做法是把 effort 降到 high 或更低,而不是强行使用高级别:
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-5",
"max_tokens": 4096,
"thinking": {"type": "disabled"},
"output_config": {"effort": "high"},
"messages": [{"role": "user", "content": "..."}]
}'
这不是孤立的 bug:effort 用错模型早就出过生产事故
Opus 5 这个案例是新的,但这类问题的根源并不新。2026 年 5 月,开源项目 TauricResearch/TradingAgents 就在另一个场景下报告过完全相同类型的错误:一个在 Claude Haiku 4.5(用于快速任务)和更大的 Opus 模型(用于重度推理)之间路由的流水线,给每一次调用都发送了 effort 参数,却没检查当次用的模型是否真的支持它。issue 里的结果原文如下:
{"type": "error", "error": {"type": "invalid_request_error",
"message": "This model does not support the effort parameter."}}
两个案例的根源相同:代码假设某个模型系列有固定的能力,而 API 是按具体模型单独校验的。每一次发布都可能在不通知你的流水线的情况下改变规则。
| 模型 | 支持 effort? | 支持 max | 支持 xhigh | xhigh/max 下禁止禁用 thinking |
|---|---|---|---|---|
claude-opus-5 | 支持,全部 5 个级别 | 支持 | 支持 | 是,会返回 400 |
claude-opus-4-8 | 支持 | 支持 | 支持 | 该模型未有此文档说明 |
claude-sonnet-5 | 支持 | 支持 | 支持 | 该模型未有此文档说明 |
claude-sonnet-4-6 | 支持 | 支持 | 不支持 | 不适用(没有 xhigh) |
claude-haiku-4-5 | 不支持 | N/A | N/A | 错误已经出在 effort 参数本身 |
禁止在 xhigh/max 下禁用 thinking 的这条具体规则,官方文档只写明适用于 Opus 5。Anthropic 完全可能在不预告的情况下把同样的规则扩展到其他模型,所以把它当成 Opus 5 独有的边缘情况来处理是有风险的。
怎么逐个模型核实,而不是靠猜
与其把这张表记在脑子里(或者硬编码进代码),不如用 Models API 拿到每个模型的真实能力,effort 也包含在内:
curl https://api.anthropic.com/v1/models \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01"
data 里的每一项都带有一个 capabilities.effort 对象,每个级别(low、medium、high、max、xhigh)都有一个 supported 布尔值。在组装请求之前先检查这个字段,而不是对路由里的所有模型都套用同一个 effort,可以一次性避开本文提到的这两类错误。
Verboo Code 的用户会遇到这个错误吗?
通过 CLI 自身的命令不会。查看 verbeux-ai/code 仓库里 src/commands/effort/effort.tsx 和 src/utils/effort.ts 的源码可以确认:/effort 命令并没有暴露任何禁用 thinking 的方式,它只会在当前激活模型所支持的范围内选择一个 effort 级别。而在原生 Claude 账号模式下,这份有效级别列表来自 getClaudeNativeModel(model)?.supportedReasoningLevels,是从 Anthropic 真实的 Models API 实时拉取的,正是上面提到的同一个 capabilities.effort。
实际情况是,在 Verboo Code 里请求一个当前模型不支持的级别,不会变成一个原始的 400,而是会变成下面这两条消息之一,直接显示在终端里:
Invalid reasoning level: max. Available for claude-haiku-4-5: , auto
Reasoning is not supported for claude-haiku-4-5
真正会撞上那个 400 错误的人,通常是在 CLI 之外自己编写 API 集成代码,而那正是需要手动做 capabilities.effort 检查的地方。
如果你的代码已经在按任务在不同模型之间路由,这种限制在下一次发布时还会再抓住你一次。在Verboo Code中,/effort 会在发送调用之前读取每个模型的真实能力,配合不限量的 token,你可以反复测试直到找到正确的级别。
