claude.dev 解读
PlaybooksAddy Osmani2026-09-28约 9 分钟阅读原文 ↗

Building with Claude Sonnet 5.5

Sonnet 5.5 单价不变、靠少用 token 省钱,但思考关不掉、强制调工具直接报 400

主张
6
审视
6
遗漏
2
  1. 01Sonnet 5.5 的每 token 单价与 Sonnet 5 相同,但完成同样的工作通常用的 token 少得多,所以总账单下降(厂商口径:多数工作最多便宜 30%)。它的定位是「规格清楚、结果能检验」的日常任务,最难的长程任务仍然交给 Opus 5.5。
  2. 02迁移的重点在接口层:思考默认开启,thinking: disabled 和强制 tool_choice 都改成直接返回 400;要关掉前置思考改用 between_tools,要强制调用工具改用 auto 加 strict 工具;读取 content 必须按块的 type 来读。
  3. 03调优的重点在 effort:各档位重新校准过,旧设置不能直接沿用,要重跑 sweep。改顶层 effort 会让缓存失效。拒绝以 HTTP 200 加 stop_reason: "refusal" 的形式返回,开启 server-side fallback 后,部分拒绝会被悄悄改到 Sonnet 5 上重试。
怎么读这篇
作者主张 · Addy Osmani我们的审视
01

可检验的日常活归 Sonnet

Sonnet 5.5 与 Opus 5.5 按任务性质分工:规格清楚、结果可检验的日常任务(修 bug、迭代功能、做文档、slides、表格)用 Sonnet;需要细致判断的复杂工作和最难的长程任务用 Opus。

机制拆解

能不能交给更便宜、更快的模型,取决于有没有外部判据:规格清楚,加上能检验结果,就能及时发现中档模型的偏差;没有判据的开放任务更依赖模型自身的判断质量,所以作者建议回到 Opus。Claude Code 里 default 仍是 Opus 5.5,要用 Sonnet 得手动执行 /model sonnet(¶48)。

“the task has a clear spec and a way to check the result” ¶7

遗漏

全文没有给出 Sonnet 5.5 和 Opus 5.5 之间的任何定量差距(质量或价格),「什么时候该换 Opus」只有定性说法。cyber 防护会误伤多少正常请求也没有数据,只说「Most routine software development is unaffected」。

自己验证在 model-eval 的 DEEP 题集上,同档位跑两款模型,记录得分和 refusal 率;把安全相关的题(如 DSH 插件签名调研里的绕过分析)单独统计拒绝率。
02

省钱靠省 token,档位要重测

成本下降来自 token 用量减少,不是降价。而且 effort 档位重新校准过,旧档位不能直接搬过来,必须重跑 effort sweep。

机制拆解

单价、批处理价、缓存价都与 Sonnet 5 一致(¶8),省钱靠的是同样的任务用更少的 token(¶9)。但同一个档位名在新模型上对应的思考量不同,各 surface 的默认值也不一样:Claude Platform 默认 high,Claude Code 默认 medium(¶10)。作者给出的起点是:一般任务从 high 开始;规格清楚的 agentic 任务从 medium 开始;只有 eval 证明 xhigh/max 能提升质量时才用。想让模型少想,要直接降 effort,在 system prompt 里要求它少想并不可靠(¶33)。

“Effort levels are recalibrated, so a level doesn't produce the same amount of thinking” ¶32

数字口径

「up to」(最多)和「for most work」(多数工作)叠在一起,30% 只是上限,不是典型值。另外有两处成本反方向上升:思考默认开启并计入 max_tokens;同尺寸图片比 Sonnet 4.6 多耗约 2.5 倍 token(¶11),对比对象不是 Sonnet 5。

自己验证把输出 token 拆成 thinking 和 text 两部分统计;对含图片的任务,单独比较缩图前后的 input token。
03

思考关不掉,只能挪到工具间

思考默认开启,而且关不掉。替代方案 between_tools 只在工具调用之间思考,同时带来一组硬约束。

机制拆解

不传 thinking 字段时走 adaptive thinking,传 disabled 会返回 400(¶16)。between_tools 只能在 low/medium/high 档使用,不能附带其他字段,对话中途也不能改 effort(¶18–¶20)。工具调用之间的进度说明以 thinking 块返回,必须原样回传(¶21)。所以凡是按 content[0].text 取文本的代码,都会因为第一个块是 thinking 而出错。

“because Sonnet 5.5 thinks by default, so a response can begin with a” ¶4

可复现性

文中所有 400 错误约束(disabled、强制 tool_choice、between_tools 用在 xhigh 档、旧版 computer 工具)和缓存失效规则,都能用几次廉价调用直接复现。

自己验证写一个小脚本,逐条发出会违反约束的请求,断言状态码为 400;连续发两次相同前缀、只改顶层 effort 的请求,看第二次 usage 里的 cache read 字段是否归零。
04

强制调用改 auto 加 strict

强制调用工具的写法(tool_choice 为 any/tool)被取消,改成三件事配合:auto、strict: true 的 schema,以及在 prompt 里写明什么时候调用。

机制拆解

以前「保证结构化输出」靠 API 强制模型调用某个工具;现在拆成两层:schema 层由 strict 模式保证输入合法(每个 object 都要写 additionalProperties: false,¶25),什么时候调用则交给 prompt 里的指令。结构合法仍然由机器保证,但「一定会调用」不再由 API 担保,变成依赖指令遵循的概率行为。

“say in the prompt when to use it” ¶24

这一点暂无对应的审视。

05

改顶层 effort 即丢缓存

缓存的门槛和价格都更友好了,但顶层 effort 一改,缓存就失效;只有 per-message effort(beta)能做到「这一轮换个档位、缓存还在」。

机制拆解

最小可缓存长度降到 512 tokens,短的 system prompt 和工具定义也能缓存;缓存读取价是输入价的十分之一(¶38)。顶层 effort 属于请求级参数,一变就不再命中缓存前缀;per-message effort 只作用于这一条消息,所以缓存得以保留。这和 ¶20 的约束(between_tools 下不能中途改 effort)一起限定了「生成用低档、核验用高档」这类方案能怎么落地。

“Changing the top-level effort between requests invalidates the cache” ¶38

这一点暂无对应的审视。

06

拒绝藏在成功响应里

拒绝变成了「成功响应」里的一个状态,并且分成五类。在 prompt 里要求模型写出推理过程,本身就会触发其中的 reasoning_extraction 类拒绝。

机制拆解

拒绝返回 HTTP 200,stop_reason 为 refusal,由 stop_details 标明类别(¶40)。只看 HTTP 状态码的流水线会把拒绝当成正常答案。server-side fallback 会把 cyber/frontier_llm 两类拒绝转到 Sonnet 5 上重试,于是实际作答的模型可能悄悄换掉。想看推理过程,应改用 thinking.display: summarized,而不是在 prompt 里要求模型写出来(¶36)。

“Don't ask the model to write out its reasoning in the response” ¶36

遗漏

advisor 返回的建议是加密的,代码读不到(¶28);fallback 换模型也不会主动提示。对审计场景来说这是可追溯性缺口,文章没有讨论。

自己验证能否从响应元数据还原出实际作答的模型。

作者没有直接谈到这一点。

厂商视角

「30% faster」「up to 30% less」都是厂商自报,没有给任务集、测量口径和方差。Epic 那段引言是客户背书,只有定性描述。

作者没有直接谈到这一点。

数字口径

effort 档位名跨模型、跨 surface 都不等价:Platform 默认 high,Claude Code 默认 medium。不先固定档位就比较「Sonnet 5.5 vs Opus 5.5」,结论不成立。

自己验证对比时在请求里显式写明 output_config.effort,在 Claude Code 里显式传 --effort,并把实际档位写进日志。
01

机制聚焦

两种思考模式对照

想关掉前置思考只能改用 between_tools,但它换来一组会报 400 的硬约束。

adaptive thinking
between_tools
何时思考
不填 thinking 时的默认模式
只在工具调用之间思考
可用 effort
各档位可用,含 xhigh/max
仅 low/medium/high,更高档报 400
中途改 effort
可逐轮调整档位
对话中途不能改
附加字段
可设 display 等字段
带 display 等字段即报 400
无工具请求
适合需几步推演的请求
响应只含文本
依据原文 ¶16 ↗
02

核心观点

01

可检验的日常活归 Sonnet

Sonnet 5.5 与 Opus 5.5 按任务性质分工:规格清楚、结果可检验的日常任务(修 bug、迭代功能、做文档、slides、表格)用 Sonnet;需要细致判断的复杂工作和最难的长程任务用 Opus。

机制拆解

能不能交给更便宜、更快的模型,取决于有没有外部判据:规格清楚,加上能检验结果,就能及时发现中档模型的偏差;没有判据的开放任务更依赖模型自身的判断质量,所以作者建议回到 Opus。Claude Code 里 default 仍是 Opus 5.5,要用 Sonnet 得手动执行 /model sonnet(¶48)。

the task has a clear spec and a way to check the result¶7 ↗

02

省钱靠省 token,档位要重测

成本下降来自 token 用量减少,不是降价。而且 effort 档位重新校准过,旧档位不能直接搬过来,必须重跑 effort sweep。

机制拆解

单价、批处理价、缓存价都与 Sonnet 5 一致(¶8),省钱靠的是同样的任务用更少的 token(¶9)。但同一个档位名在新模型上对应的思考量不同,各 surface 的默认值也不一样:Claude Platform 默认 high,Claude Code 默认 medium(¶10)。作者给出的起点是:一般任务从 high 开始;规格清楚的 agentic 任务从 medium 开始;只有 eval 证明 xhigh/max 能提升质量时才用。想让模型少想,要直接降 effort,在 system prompt 里要求它少想并不可靠(¶33)。

Effort levels are recalibrated, so a level doesn't produce the same amount of thinking¶32 ↗

03

思考关不掉,只能挪到工具间

思考默认开启,而且关不掉。替代方案 between_tools 只在工具调用之间思考,同时带来一组硬约束。

机制拆解

不传 thinking 字段时走 adaptive thinking,传 disabled 会返回 400(¶16)。between_tools 只能在 low/medium/high 档使用,不能附带其他字段,对话中途也不能改 effort(¶18–¶20)。工具调用之间的进度说明以 thinking 块返回,必须原样回传(¶21)。所以凡是按 content[0].text 取文本的代码,都会因为第一个块是 thinking 而出错。

because Sonnet 5.5 thinks by default, so a response can begin with a¶4 ↗

04

强制调用改 auto 加 strict

强制调用工具的写法(tool_choice 为 any/tool)被取消,改成三件事配合:auto、strict: true 的 schema,以及在 prompt 里写明什么时候调用。

机制拆解

以前「保证结构化输出」靠 API 强制模型调用某个工具;现在拆成两层:schema 层由 strict 模式保证输入合法(每个 object 都要写 additionalProperties: false,¶25),什么时候调用则交给 prompt 里的指令。结构合法仍然由机器保证,但「一定会调用」不再由 API 担保,变成依赖指令遵循的概率行为。

say in the prompt when to use it¶24 ↗

05

改顶层 effort 即丢缓存

缓存的门槛和价格都更友好了,但顶层 effort 一改,缓存就失效;只有 per-message effort(beta)能做到「这一轮换个档位、缓存还在」。

机制拆解

最小可缓存长度降到 512 tokens,短的 system prompt 和工具定义也能缓存;缓存读取价是输入价的十分之一(¶38)。顶层 effort 属于请求级参数,一变就不再命中缓存前缀;per-message effort 只作用于这一条消息,所以缓存得以保留。这和 ¶20 的约束(between_tools 下不能中途改 effort)一起限定了「生成用低档、核验用高档」这类方案能怎么落地。

Changing the top-level effort between requests invalidates the cache¶38 ↗

06

拒绝藏在成功响应里

拒绝变成了「成功响应」里的一个状态,并且分成五类。在 prompt 里要求模型写出推理过程,本身就会触发其中的 reasoning_extraction 类拒绝。

机制拆解

拒绝返回 HTTP 200,stop_reason 为 refusal,由 stop_details 标明类别(¶40)。只看 HTTP 状态码的流水线会把拒绝当成正常答案。server-side fallback 会把 cyber/frontier_llm 两类拒绝转到 Sonnet 5 上重试,于是实际作答的模型可能悄悄换掉。想看推理过程,应改用 thinking.display: summarized,而不是在 prompt 里要求模型写出来(¶36)。

Don't ask the model to write out its reasoning in the response¶36 ↗

03

批判性审视

厂商视角

「30% faster」「up to 30% less」都是厂商自报,没有给任务集、测量口径和方差。Epic 那段引言是客户背书,只有定性描述。

数字口径

「up to」(最多)和「for most work」(多数工作)叠在一起,30% 只是上限,不是典型值。另外有两处成本反方向上升:思考默认开启并计入 max_tokens;同尺寸图片比 Sonnet 4.6 多耗约 2.5 倍 token(¶11),对比对象不是 Sonnet 5。

自己验证把输出 token 拆成 thinking 和 text 两部分统计;对含图片的任务,单独比较缩图前后的 input token。
数字口径

effort 档位名跨模型、跨 surface 都不等价:Platform 默认 high,Claude Code 默认 medium。不先固定档位就比较「Sonnet 5.5 vs Opus 5.5」,结论不成立。

自己验证对比时在请求里显式写明 output_config.effort,在 Claude Code 里显式传 --effort,并把实际档位写进日志。
可复现性

文中所有 400 错误约束(disabled、强制 tool_choice、between_tools 用在 xhigh 档、旧版 computer 工具)和缓存失效规则,都能用几次廉价调用直接复现。

自己验证写一个小脚本,逐条发出会违反约束的请求,断言状态码为 400;连续发两次相同前缀、只改顶层 effort 的请求,看第二次 usage 里的 cache read 字段是否归零。
遗漏

全文没有给出 Sonnet 5.5 和 Opus 5.5 之间的任何定量差距(质量或价格),「什么时候该换 Opus」只有定性说法。cyber 防护会误伤多少正常请求也没有数据,只说「Most routine software development is unaffected」。

自己验证在 model-eval 的 DEEP 题集上,同档位跑两款模型,记录得分和 refusal 率;把安全相关的题(如 DSH 插件签名调研里的绕过分析)单独统计拒绝率。
遗漏

advisor 返回的建议是加密的,代码读不到(¶28);fallback 换模型也不会主动提示。对审计场景来说这是可追溯性缺口,文章没有讨论。

自己验证能否从响应元数据还原出实际作答的模型。
本篇未覆盖(3)
风格