标准Extended Thinking仅在开始时推理一次,交错思考允许工具返回后继续生成thinking块,适合搜索结果需调整策略的场景。
Extended thinking 通常发生在助手回合的开始,在 Claude 看到任何工具结果之前,一次性完成。Interleaved thinking 解除了这个限制:模型可以在每次工具结果返回后生成一个新的 thinking block,这样后面的决策就能在已有答案的基础上进行推理。
一个标准的 extended-thinking 回合有固定的形状。Claude 先思考,然后行动。thinking block 先发出,tool_use block 紧随其后,回合以 stop_reason: "tool_use" 结束。运行工具,追加 tool_result,再次调用 API——紧接着的助手回合中,工具输出已经在上下文里,但没有附加新的推理。模型从结果中作答,而不是对结果进行思考。
这在工具调用是查询场景时没有问题。但当第二次调用依赖于第一次的结果时,这就成了限制:搜索没有返回有用内容、应该用不同关键词重新运行;数据库查询的行数决定了是聚合还是分页;计算结果在报告之前需要合理性检查。这三种场景中,有用的推理都发生在工具回答之后,但之前没有地方放置这些推理。
Anthropic 将这个行为放在了 beta header 后面。在原始 HTTP API 中,它是一个请求头,和版本头一起传递:
POST https://api.anthropic.com/v1/messages
x-api-key: $ANTHROPIC_API_KEY
anthropic-version: 2023-06-01
anthropic-beta: interleaved-thinking-2025-05-14
content-type: application/json
{
"model": "claude-sonnet-4-20250514",
"max_tokens": 8000,
"thinking": { "type": "enabled", "budget_tokens": 4000 },
"tools": [
{
"name": "search_orders",
"description": "Search orders by customer email.",
"input_schema": {
"type": "object",
"properties": { "email": { "type": "string" } },
"required": ["email"]
}
}
],
"messages": [
{ "role": "user", "content": "Did [email protected] order anything in March?" }
]
}
在官方 SDK 中,同样的东西作为 beta 传递而不是手写——Python 客户端在 client.beta.messages.create 上传入 betas=["interleaved-thinking-2025-05-14"],TypeScript 客户端传入等价的 betas 数组。带日期的后缀是值的一部分,不是文档:header 是字面匹配的,所以去掉日期会使其变成无法识别的 beta。通用机制(包括必需的 header 缺失时会发生什么)参见 Claude API 中的 beta headers。
Beta 名称及其可用性会变动。Anthropic 的 extended thinking 文档是权威来源,用于判断这个 beta 是否仍然需要、是否仍然以此命名、或者是否已升级为你所调用模型的一般可用性。
可观察的差异完全在 content 数组中。以下是两步步回合的文档化形状——第一次响应,然后在工具结果返回后的响应。这是 API 被指定生成的 schema,是从文档中重建的,不是某次运行的记录:
// First assistant turn
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "...", "signature": "EqQBCgIY..." },
{ "type": "tool_use", "id": "toolu_01A...", "name": "search_orders",
"input": { "email": "[email protected]" } }
],
"stop_reason": "tool_use"
}
// You append: { "role": "user", "content": [
// { "type": "tool_result", "tool_use_id": "toolu_01A...", "content": "[]" } ] }
// Second assistant turn — WITH the interleaved beta
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "...", "signature": "EqQBCgIY..." },
{ "type": "tool_use", "id": "toolu_01B...", "name": "search_orders",
"input": { "email": "[email protected]", "include_archived": true } }
],
"stop_reason": "tool_use"
}
第二个 thinking block 就是整个特性的意义所在。没有 beta 时,第二个助手回合以 text 或 tool_use 开头,没有自己的推理;有 beta 时,Claude 可以先考虑空结果,再决定下一步做什么。回合中也可能在工具调用的同时混入 text block,这是正常的,在"为什么 Claude 在同一回合中返回 text 和 tool call"中有单独解释。
每个 thinking block 都带有一个 signature 字段:一个不透明的值,让 API 能够验证该 block 是由模型生成的,而不是由客户端编写的。构建下一个请求时,整个助手 content 数组——thinking blocks、signatures 及其顺序——逐字返回,位于你正在追加的 tool_result 之前。
不要从仍在进行中的回合里剥离 thinking blocks。在 tool-use 回合中,它们是模型保持连贯性所必需的状态的一部分。
不要编辑其中的文本。signature 是对整个 block 的校验;重写推理而保留 signature 会导致验证失败。
不要重新排序。Thinking 位于它所导致的工具调用之前,API 期望这个顺序被保留回来。
预期 redacted_thinking。如果安全系统标记了推理过程,block 会以加密内容的 redacted_thinking 形式到达。它仍然原样传回;这不是错误,也不应该被过滤掉。
出问题的时候 API 会告知你,这是仁慈的:一个 thinking blocks 被剥离、截断或重新序列化的请求会返回 HTTP 400,并带有 invalid_request_error,指出 block 索引并抱怨无法验证 signature,而不是静默地产生一个更差的结果。常见原因不是恶意破坏,而是消息历史层将对话存储为 {role, text} 对,并在传出时重建数组。这种表示无法完整往返一个 thinking block,在第一次启用 thinking 的工具调用之前它都能完美工作。
存储的推论:将助手回合持久化为原始 content 数组,而不是扁平化的文本。如果需要显示字符串,在渲染时从 text blocks 中派生,并保持数组作为事实来源。这与同一回合中 text 和 tool calls 要求的纪律相同,一次性采用比后续改造要容易。
budget_tokens 限制 thinking,而通过 interleaving,这个上限应用于整个回合中的所有 thinking blocks,而不是每个单独计算。四次工具调用配 4,000-token budget,并不会每次获得 4,000 tokens。这也是为什么回合可能跑得很长:thinking tokens 作为输出 tokens 计费,max_tokens 必须足够大,以容纳 budget 加上可见答案加上途中的每个工具调用参数。将 max_tokens 设置为小于或等于 budget_tokens 会被拒绝,而不是静默截断。分配规则参见 budget_tokens and extended thinking。
两个实际后果随之而来。首先,针对非-thinking 工具调用调优的 agent 循环,一旦开启 interleaving,每回合的输出 token 账单会更高,因为推理现在出现在每个步骤而不是只有第一步。其次,prompt 缓存与此相互作用:每多一轮都会重新发送更长的助手历史,因此位于工具循环之前的缓存断点比没有 thinking 在中间时更快回本。
如果额外的推理没有改变模型的行为——对于简单的单次查询工具来说通常确实不会——诚实的结论是在那条路由上关闭 beta,把它留给那些工具结果真正改变计划的地方。
在构建成本模型之前,有一个会计细节值得对照文档检查。Anthropic 对较早的、已完成的助手回合中的 thinking blocks 与当前进行中回合内的 thinking blocks 处理方式不同:已完成回合的推理不需要像进行中的工具循环那样被持续向前携带。实际的解读是,interleaving 膨胀了单个多步回合,而不是无限制地膨胀整个对话——但确切规则在 extended thinking 页面上,它已经被修订过,不能从账单中推断。
最后,关于如何判断 beta 是否真正生效的说明,因为响应中没有任何内容宣告这一点。统计工具循环中每个助手回合的 thinking blocks 数量。没有 beta 时,你最多看到一个,在回合序列的第一个回合中;有 beta 时,你可能在每个回合中看到一个。单个回合中没有不代表 beta 关闭了——模型没有义务在每个步骤之前都思考——所以要看在若干多步对话中的分布,而不是看单个响应。
Extended Thinking in Claude: budget_tokens and What Replaced It
Beta Headers in the Claude API: How Features Ship Before General Availability
Why Claude Sometimes Returns Text and a Tool Call in the Same Turn