← 返回 Claude AI IP 检测更多资讯 →

Anthropic 给 Claude 思考块上锁:改动对话历史,API 直接报错

首页AI 资讯Claude 资讯 · 2026-09-02 · Net.Coffee

防的是工业规模的非法蒸馏,代价是 messages 数组从此只能追加——先在 8 月 31 日之后新建的账户上生效。

一句话:Anthropic 给 Claude Fable 5.1 的思考块加了绑定校验——你把模型上一轮的推理块发回 API,就得连同当时的 system 提示、工具列表和之前每一条消息原样奉还,改动任何一处请求直接被拒;官方同时留了一个「不严格」开关,允许 API 把对不上的思考块丢掉后继续跑。

这条改动的落点很窄,只在 Messages API 上;但它废掉的是一个几乎所有自研 agent 都在用的默认假设:对话历史是一份可以随手改的草稿。从 Fable 5.1 开始,只要历史里还留着思考块,messages 就是一本只能往后追加的账本。

签名把一段推理钉死在一段对话上

思考块本身是加密的,外面看不到内容,回传时靠一个 signature 字段自证身份。新规则做的事就是把这个签名从「证明这块是真的」升级成「证明这块还长在原来那段对话上」——API 收到请求时会核对三件事:模型是同一个或更新的版本;system 提示、tools 集合以及这个块之前的每一条消息都没变过;更早的思考块链条没被从中间挖走。三条里任何一条不过,这个块就作废。

为什么非要绑这么死,Anthropic 在帮助中心里说得直白:修改思考块之前的上下文,是一种被公开记录过的手法,可以诱导模型把自己那段加密推理解密并打印出来,属于工业规模的非法蒸馏,本来就违反使用政策。加密防的是「看见」,绑定防的是「换个场景重放」——在一套指令下生成的推理,不能拿到另一套(可能是对抗性的)指令下再走一遍。

顺带一提,模型这一条的方向是单向的:新模型读得懂老模型产出的块,反过来不行。所以做了模型路由或降级回退的服务,会看到块被静默丢弃,那不算集成有 bug,官方明确说继续照发就行。

报错长什么样,以及那个可以关掉的开关

默认行为是直接失败。触发时返回 400 invalid_request_error,消息会点名第一个出问题的块,开头是这样一句:messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. 结尾通常还会补一句到底是什么变了——是 system 变了,还是 tools 列表和当初对不上。

另一条路是加上 thinking-binding-controls-2026-08-01 这个 beta 头,把 thinking.block_binding.prefix_mismatch_behavior 设成 drop_block:API 会把这个块以及它后面所有思考块摘掉,请求照常成功,被丢掉的块不计费,响应里多出一个顶层 input_transformations 数组,逐条列出丢了哪个路径、原因是前缀不匹配还是模型不匹配。这个数组也是自查的主要工具——跑一整轮正常会话,如果每次都是空的,说明历史是干净的追加。

有一个细节值得单独记:撞上 400 之后原样重试没有用,必须带着 drop_block 重发,而且这一整个会话的后续请求都得继续带着——丢弃只对单次请求生效。

八月三十一日那条线,最先绊倒的不是你

目前的生效范围是 2026 年 8 月 31 日 00:00 UTC 之后新建的账户,Claude 平台、Amazon Bedrock、Google Cloud Vertex AI、Microsoft Azure Foundry 一视同仁。在此之前建的账户,在 Fable 5.1 上暂时不受影响,留出改造时间;再往后的模型,官方说会对所有人生效。

Anthropic 特意提醒了一类人:如果你维护的是一个让别人用自己 API key 跑的工具或框架,那么你的新账户用户会比你先撞上这堵墙——你自己那把 key 大概率是老账户,本地怎么测都测不出问题。想复现,就主动把 prefix_mismatch_behavior 设上,这个字段一出现就等于自愿进入强制模式,跟账户年龄无关。反过来,想知道自己是不是已经被强制了,发一个改过历史、又不带 beta 头的请求,如果 400 里点名要那个 beta 头,就是已经在管控内了。

用官方产品的人不用管这件事。Claude Code、claude.ai、Claude Agent SDK 和 Managed Agents 的历史都由官方自己维护,前缀天然是完整的;如果你在这一层遇到过奇怪的报错,多半和这条规则无关,更可能是配置或网络层面的老问题。真正需要动手的,是那些自己写循环、自己拼 messages 的集成。

要改的其实是「每轮重建上下文」这个习惯

把官方列出来的高危写法摊开看,会发现它们的共同点不是「删」,而是「重建」——每次请求都当作一次全新的组装:

其中第三、第四条最容易中招,因为它们看起来根本不像「修改历史」。每轮追加一句 nudge、下轮再删掉,是很多 agent 循环里的标准动作;而把当前时间写进系统提示,几乎是所有人的第一反应。对应的替代品官方都准备好了:会话中途要加指令,就在 messages 里追加一条 role: "system" 消息(Fable 5.1 上这个已经是正式功能,不需要 beta 头);一次性的提醒改用带 clear_at: "next_user_message" 的轮次级系统消息,它下一轮就自动失效但仍留在数组里,前面的思考块因此不受影响;工具变动走 tool_addition / tool_removal;要裁上下文就交给服务端的压缩和 context editing——校验比对的是你发过去的内容,服务端自己怎么改不算数。

客户端压缩也没被禁,规则比想象中窄:不要把思考块留在一段已经被你改写过的前缀后面。最简单的那种压缩反而完全合规——把整段会话总结成一条消息,下一轮就从这条摘要加新指令重新开始,不回放任何旧轮次和旧思考块。Anthropic 说 Claude 模型本来就是按这个方案在长任务上训练的,多数场景下效果和更复杂的方案相当。至于 keep-tail 和后台异步压缩,都只需要一个动作:把带过去的助手轮里的 thinking 块剥掉,保留 texttool_use

还有一个不太起眼但影响实际账单的连带效果。前缀必须逐字节稳定,恰好也是 prompt caching 命中的前提——过去很多集成缓存命中率上不去,原因就是每轮请求头部都被自己改动过。这次相当于把一条本来靠自觉的性能建议,变成了必须遵守的接口约定;省下来的钱和延迟,算是改造的补偿。

所以这条更新真正的分量不在报错本身,而在它把「对话历史」的性质改了。以前那是客户端可以随便捏的一段数据结构,现在它带着可验证的签名,是一份必须逐字节保管的记录。做 agent 的人多了一条硬约束,也少了一类难查的隐性 bug——毕竟以前偷偷改了前缀,模型只是悄悄变笨,没人会收到一条 400。