Claude思维块绑定机制:Agent历史为何变成只读账本

Anthropic 的 preserved thinking 要求思维块前缀不可变,Agent 框架常见改写历史的做法会导致 400 错误。
Anthropic 为防止模型蒸馏推出 preserved thinking 机制,要求回传的 thinking 块之前的内容(system 提示、tools 数组、前置消息)必须与生成时完全一致,否则签名校验失败并返回 400 错误。该检查对新账号默认强制执行,老账号需通过 beta 头或特定参数触发。重新渲染系统提示、中途编辑工具集、裁剪中间轮次等六种常见 Agent 框架做法现在都会破坏请求。开发者可借助 `thinking-binding-controls-2026-08-01` beta 头与 `input_transformations` 输出提前定位问题,或用 `drop_block` 作为临时权宜之计,但代价是输出 token 显著增加。根本修复方向是持久化并回放实际发送与接收的内容。
如果你的 Claude 集成会重写自己的对话历史,API 可能返回一个以 messages.1.content.0: Invalid \signature` in `thinking` block` 开头的 400 错误——提示该思维块被绑定到了另一段对话。开头的路径会随失败的块而变化,所以排查时要盯住路径之后的那段描述。

这段措辞出自 Anthropic 的 preserved thinking 文档。Anthropic 在一篇关于蒸馏防御的研究文章中解释了这条规则的来由:preserved thinking 是"防止新建 API 账号编辑 Claude 此前上下文"的一项措施。它是三层防御体系之一,目的是阻止其他实验室用 Claude 的推理过程训练自家模型。Anthropic 在文章中给出一个合并结论:
早期证据表明,这些方法使蒸馏者采集的数据量减少了约 90% 到 99%。
Anthropic 称其为"早期证据",并未说明如何测量。而你这一侧的成本更容易确定:同一篇文章承认,preserved thinking "要求部分开发者更新其集成"。
三层防御,其中一层在你的请求链路上
Anthropic 列出的三层防御分别是:
- Preserved thinking:随 Claude Fable 5.1 和 Claude Opus 5.5 一同发布。在 Claude Sonnet 5.5 上,推理记录只对发起请求的组织可见。
- 两阶段分类器:运行在 Claude Sonnet 5.5、Opus 5 和 5.5、Fable 5 和 5.1 之上,Anthropic 称其误报率低于 0.1%。
- 强制执行:持续尝试提取推理的账号会被施加更严格的限制乃至封禁。Anthropic 已恢复对在 Claude 响应前就被安全机制拦截的请求收费,前提是这些安全机制在蒸馏等领域的误报率低于 0.1%。
有媒体评价这一取舍"可以辩护",但同时指出,它把摩擦转移到了付费客户身上。分类器和计费规则主要在你"运气不好"时才会碰到,而 preserved thinking 影响每一个多轮集成,因为它改变了"合法请求"的定义。
API 对每个思维块检查什么
对你回传的每一个 thinking 或 redacted_thinking 块,文档描述了两项检查。第一,模型必须能够读取该块,否则 API 会静默丢弃它而不报错。第二:"思维块之前的内容没有任何变化"。
这里的"之前"指顶层 system 提示、tools 数组,以及该块之前的每一条消息。只要其中任何一项与生成该块时的状态不同,该块及其之后的所有思维块都会失效。
强制执行取决于账号创建时间:在此之后创建的账号默认启用该检查并收到 400 错误;较老的账号上检查仍会运行,但只有设置了特定参数的请求才会真正强制执行,否则失败的块会被放行至模型。前缀检查覆盖多款模型。
追加消息始终有效。对 effort、max_tokens、tool_choice、metadata 和 cache_control 标记的修改同样有效,服务端压缩也不会触发问题,因为检查"比较的是你发送的内容,而不是服务端编辑后的副本"。
什么是 thinking 块与 signature
在 Anthropic 的扩展思考(extended thinking)机制中,模型在给出最终答案前会先输出一段推理过程。启用 thinking 后,API 响应里会包含 thinking 类型的 content block,其结构大致为 {"type": "thinking", "thinking": "...", "signature": "..."}。其中 signature 是一个与生成该块的完整上下文绑定的加密校验值,由 Anthropic 服务端生成,用于证明这段推理确实由对应模型在该特定前缀下产生。客户端在后续轮次回传历史时,必须原样携带这些块,服务端会重新校验签名是否与当前请求的 system、tools 及前置消息一致。redacted_thinking 是当推理内容因安全策略被遮蔽时返回的变体,结构类似但 thinking 字段被替换为不可读密文,签名同样承载绑定信息。正因如此,只要前缀哪怕发生一个字符的变化,签名校验就会失败,API 便以 400 错误拒绝整个请求。
这些习惯现在会打断 Agent 循环
大多数 Agent 框架都会在某个地方改动历史。文档列出了会失败的几种模式及替代做法:
- 重新渲染系统提示。注入当天日期、或把更新后的
CLAUDE.md/AGENTS.md重新加载进system,都会改变前缀。应当只在开始时加载一次指令文件,后续版本作为对话中途的系统消息追加,或不信任文件内容时放进下一个user轮次。 - 会话中途编辑
tools。应在开始时声明完整工具集,用defer_loading: true标记后加入的工具,并通过tool_addition和tool_removal块来启用或撤回。 - 通过移除工具来关闭工具使用。应改用
tool_choice: {"type": "none"}。 - 从中间裁掉轮次。这会让裁切点之后的每个思维块失效。应使用服务端上下文编辑来修剪旧的工具结果。
- 自己写 keep-tail 摘要。被保留的轮次携带的是针对已被替换的历史产生的思维。应让 API 通过按需压缩来生成摘要,或从被保留的轮次中剥离思维。
- 跳过"空"块的序列化器。文档警告
thinking字段默认为空,推理内容由signature承载。丢掉这个块就等于丢掉推理。
还有两个更隐蔽的问题:网关把 role: "system" 消息移入顶层 system 字段,会使对话中每个思维块失效;以及通过 URL 引用的图片或文档在内容变化后,会破坏后续思维。跨轮次引用任何内容时,应使用 Files API 和 file_id。
defer_loading 与 tool_addition / tool_removal
Anthropic 为工具集动态变化提供的替代方案涉及几个工具栏字段。defer_loading: true 标记的工具在声明时不会立即把完整定义塞进上下文,而是把定义推迟到真正被调用时再加载,从而让前缀保持稳定。tool_addition 块用于在对话中途正式激活某个此前被延迟声明的工具,tool_removal 则相反,用于撤回一个工具。这两个块本身被设计为可追加的增量,因此不会改变此前思维块所依赖的前缀。与之相对,直接增删 tools 数组元素会让前缀与生成思维块时不一致,进而触发 messages.1.content.0 之类的签名错误。这一设计实际上把“工具集可变”从数组编辑问题转化成了消息流内的显式事件问题。
在变成 400 错误之前找到那些改动
你不需要新账号就能测试。文档 FAQ 说明,较老的账号可以发送 thinking-binding-controls-2026-08-01 beta 头,并且不设置 prefix_mismatch_behavior。失败的块仍会到达模型,而响应会在 input_transformations 中以 thinking_mismatch_allowed 把它们列出:
import logging
import anthropic
client = anthropic.Anthropic()
resp = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
thinking={"type": "adaptive"},
system=system_prompt,
tools=tools,
messages=history,
betas=["thinking-binding-controls-2026-08-01"],
)
for t in resp.input_transformations or []:
reason = getattr(t, "reason", None)
logging.warning("%s %s %s", t.type, t.path, reason)
每条记录带有一个 path,例如 messages.1.content.0。第一条记录指向你的框架最早使其失效的块。
如果你暂时无法修复这个编辑,临时的权宜之计是 drop_block:
thinking={
"type": "adaptive",
"block_binding": {
"prefix_mismatch_behavior": "drop_block",
},
}
这样请求会成功,API 会丢弃每个失败的块及其之后的所有块,并以 reason: "prefix_binding_mismatch" 列出它们。文档警告这可能"显著增加生成的输出 token 数量",在一项多轮编码基准测试中,增幅范围为 2.5% 到 67.1%,取决于 effort 和块被丢弃的频率。模型也会在没有先前推理的情况下作答,所以应当计划移除触发这一行为的编辑。
input_transformations 与 beta 头
thinking-binding-controls-2026-08-01 是一个 Anthropic beta 头,启用它后可以调整思维块前缀校验的触发行为。其配套参数 prefix_mismatch_behavior 决定校验失败时如何处理:默认(新账号)为直接返回 400,设置为 drop_block 时则放行请求但丢弃失效块。老账号在未设置该参数时会把这批失败块原样传给模型,并在响应的 input_transformations 数组中逐条列出,每条包含 type、path 与 reason 字段。path 采用 JSON 指针风格,例如 messages.1.content.0 表示第 2 条消息的第 1 个内容块,据此可定位框架最早改坏历史的位置。这套观测能力让你无需新账号即可复现和排查前缀不匹配问题。
近期可以改什么
以下建议均来自文档:
- 精确持久化你发送和接收的内容:渲染后的系统提示和工具定义,以及每一次返回的助手轮次。恢复时回放这些内容,而不是从可能已经变化的输入重新渲染。
- 如果你运行代理或网关,要透传
anthropic-beta值和thinking.block_binding,把input_transformations返回给调用方,不要在 400 时静默剥离思维并重试。 - 如果你使用多个账号,注意 Sonnet 5.5 和 Haiku 5.5 的思维块无法从另一个未关联的账号中复用。
我的看法是:Anthropic 正在用你的工程时间来支付它的蒸馏防御成本。好的一面是,一个只追加、可回放的消息记录,也是调试起来最容易的一类 Agent 运行记录。
Files API 与 file_id
原文提到通过 URL 引用的图片或文档在内容变化后会破坏后续思维块,解决方案是使用 Files API。Files API 允许你先将文件上传到 Anthropic 侧,获得一个稳定的 file_id,随后在消息中改用 file_id 引用而非直接嵌入 URL 或文件内容。由于 file_id 本身不随后续源文件变化而改变,签名校验时的前缀保持一致,思维块得以继续有效。若改用 URL,服务端会在每次请求时按 URL 重新拉取内容,源文件一改,前缀即变,之前所有携带签名的思维块随之失效。对于需要跨多轮引用同一张图或同一份文档的 Agent 场景,Files API 基本是唯一稳妥做法。
相关推荐

OpenAI与Shield合作:Astra智能体如何革新IT故障修复
OpenAI与Shield合作推出Astra智能体,可自动登录电脑和遗留系统,实时修复IT故障,比传统模型快35%到40%,仅在需要人类判断时引入人工。

iPhone Duo续航实测:一天一充跑不掉,大屏是耗电元凶
iPhone Duo续航实测:重度使用一天需至少充电一次,6.5小时亮屏约剩30%电量。大屏展开频率是耗电关键,MagSafe电池背夹可救场,长期衰减同样值得关注。

Kimi K3.1 Pro开源发布:2.8万亿参数逼近Opus
Moonshot发布开源MoE模型Kimi K3.1 Pro,2.8万亿总参数、1040亿激活参数,Terminal Bench 4.0仅落后Opus 5.5不到1分,单任务成本约三分之一,API价格减半,开源权重11月4日开放。