Anthropic 的协议
thinking、cache、tool_use
一、原理:Claude API 的独有能力
LLM API 协议长得最像现代标准的是 Anthropic 的 Claude API。它的 messages 结构、tools 字段、stream 设计——很多被其他 provider 跟进抄。
但 Anthropic API 真正的优势不是"接口规范漂亮"——是几个独有能力让 Claude 在某些场景下比其他 LLM 强一档。
我们看 3 个核心能力。
能力 1:thinking(思考链显式输出)
Claude 3.5 推出之后加了一个特性——LLM 在回答前可以"先思考一段"。具体说,response 的 content 里可能有:
{
"content": [
{
"type": "thinking",
"thinking": "Let me analyze this problem... The user wants X, so I need to consider Y and Z..."
},
{
"type": "text",
"text": "Here's the answer: ..."
}
]
}
thinking 是模型的"内部独白"——它在给最终答案前的推理过程。
这件事为什么重要?两个原因:
原因 a:质量提升
让模型显式"思考"再回答——质量明显高。这是 chain-of-thought 这种 prompt 技巧的原生支持。
OpenAI 的 o1 模型也有类似机制——但走的是隐藏路径(reasoning 在 API 层不暴露给用户)。Claude 的 thinking 是公开的——用户能看到推理过程。
原因 b:可解释性
用户能看到 AI"为什么这么回答"——debug 容易、信任建立快。
如果 Claude 给错答案——用户看 thinking 能找到错误的推理步骤。比"AI 不知怎的给错了"清楚得多。
能力 2:prompt caching(cache_control)
我们在 6.1 章已经看到 cache_control 标签。这是 Anthropic 的 prompt caching 机制——告诉 API "这一段 prompt 可以缓存"。
具体使用:
{
"system": [
{
"type": "text",
"text": "[大段稳定的 system prompt + 工具描述]",
"cache_control": {"type": "ephemeral"}
}
]
}
第一次请求:normal price 计费这段。同时 Anthropic 服务端把这段做哈希、存缓存。
第二次请求(5 分钟内):同样的 text + cache_control——Anthropic 服务端识别缓存命中——这段只付 10% 价格。
这是个巨大的成本优化——长 session 的 system prompt 几十次复用,每次省 90%——累积下来是几十倍降本。
cache_control 的几个细节:
细节 a:只能标"稳定不变"的部分
如果你标记的内容下一次请求里变了——缓存不命中——白付了 cache_write 的钱。
要保证标记的部分绝对稳定——比如全局 system prompt + tools 描述。每个 turn 变的环境信息不要标。
细节 b:有顺序约束
cache 是按"前缀"匹配的——如果你的 prompt 是 [A, B, C, D],标记了 A 和 C 作为 cacheable——只有 A 能命中缓存(C 在 B 后面,B 没缓存就断了)。
要让缓存生效——把所有 cacheable 内容放前面、连续放、不要被非缓存内容打断。
细节 c:5 分钟 TTL
ephemeral 缓存只活 5 分钟。如果你的 session 间隔超过 5 分钟——缓存失效。
下一次请求又要"cache_write"——付一次写入的钱。
能力 3:tool_use 的成熟设计
Anthropic 的 tool calling 设计是业界最成熟的——它早就支持:
- streaming tool input(边收边知道 tool name)
- parallel tool calls(一次响应输出多个 tool_use)
- tool_use ID(每次调用有唯一 ID)
- 多模态 tool result(content 可以是 text 或 image)
这些都被 OpenAI 后来跟进——但 Anthropic 先做的。
opencode 在这些 Anthropic 独有能力上充分利用——我们看具体怎么做。
二、案例:opencode anthropic-messages.ts(reference 实现)
R6-02 / R8 阶段的研究告诉我们——opencode 的 protocol adapter 里 anthropic-messages.ts 是最长、最复杂、最完整的一个——845 行代码。
它的复杂度反映了 Anthropic API 的功能丰富。我们看几个具体的实现细节。
细节 1:thinking 的处理
opencode 把 Claude 的 thinking 输出保留——不丢、不过滤。
它在 messages 里作为一个独立 part 存:
{
type: "reasoning", // 内部统一叫 reasoning
text: "[Claude 的 thinking 内容]"
}
UI 上能显示 thinking——用户可以展开/折叠看 Claude 的推理过程。这是用户体验的差异化点——其他 provider 没法做到。
细节 2:cache_control 的分层标记
opencode 把 system 数组分 3 层标 cache_control(参考 6.1 章的实例):
- 第 1 段:5 张脸 + AGENTS.md + 工具描述——
cache_control: ephemeral(缓存) - 第 2 段:项目级 instruction
- 第 3 段:环境信息——不缓存(每次都变)
这种分层让缓存覆盖最多——同时不冒"缓存失效"风险。
细节 3:tools 也可以缓存
cache_control 不止能用在 system——也能用在 tools 数组:
{
"tools": [
{
"name": "read",
...,
"cache_control": {"type": "ephemeral"}
}
]
}
opencode 把 tools 数组的最后一个 tool 标记 cache_control——这样整个 tools 数组都被缓存(cache 从这个点往前覆盖)。
15 个工具描述 3-5K tokens——缓存后省一大笔。
细节 4:stop_reason 映射
Anthropic 的 stop_reason 有几种:
end_turn—— 正常完成tool_use—— 要调 toolmax_tokens—— 输出到上限stop_sequence—— 命中停止词pause_turn—— 暂停(这是 Anthropic 独有,用于 task tool 等)
opencode 把这些映射到内部统一的状态——主循环按这个状态决定下一步。
pause_turn 是个独特的状态——表示 LLM 主动暂停等待外部事件(比如 background subagent 完成)。其他 provider 没有这个概念——opencode 在 Anthropic 上能用、其他 provider 上 fallback 到普通逻辑。
细节 5:multimodal 支持
Anthropic API 接受 image 输入(image 作为 content block 的一种 type):
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "..."
}
},
{
"type": "text",
"text": "What's in this image?"
}
]
}
opencode 的 read tool 读到图片时——直接用这种格式塞给 Claude——Claude "看到"图片回答。
这是视觉理解能力——其他 provider 也有(GPT-4V、Gemini)但格式不一样。opencode 的 adapter 把内部统一格式翻译成每家的。
为什么 Anthropic 总是先做这些?几个理由:
理由 a:Claude 模型本身能力强
Anthropic 的模型在 reasoning、tool use、long context 上能力强——他们在 API 设计上能率先暴露这些能力。
理由 b:Anthropic 的产品定位
Anthropic 主打"开发者友好"——他们的客户多是用 LLM 做产品的开发者。开发者要 cache_control、要 thinking、要 parallel tool calls 这些"工程化"特性。
理由 c:Anthropic 的迭代速度
Anthropic 的 API 更新频率比 OpenAI 高——他们更愿意"试新东西"。结果是他们经常先做 + 业界跟进。
把这些合起来——Anthropic API 是 LLM 协议的事实 reference。其他 provider 经常"参考 Anthropic 的设计"。
opencode 的 anthropic-messages.ts 845 行——是 opencode 充分利用 Anthropic 独有能力的体现。其他 adapter 的"简化版"实现都是因为对应 provider 缺这些能力。
三、设计启示:为什么 Anthropic 总是先做新功能
这一章的核心论点:Anthropic 在 LLM 协议层是 reference 实现——理解它能让你看清其他 provider 的差距。
如果你做 AI 产品考虑 Anthropic API,下面几条原则有用:
1. 善用 prompt caching
如果你用 Claude 而不用 caching——你的成本是别人的 10 倍。这不是 nice-to-have——是必做。
设计 prompt 结构时考虑 caching:
- 稳定不变的部分放前面、连续放
- 标记 cache_control
- 测试缓存命中率
2. thinking 输出给用户看
Claude 的 thinking 是个差异化体验——用户能看到 AI 推理过程。
UI 上提供"展开 thinking"选项——专业用户喜欢看。
如果你的产品场景需要"可解释性"——这是必用的。
3. parallel tool calls 要支持
Claude 一次响应可能输出多个 tool_use——你的 agent 必须能并行执行多个 tool。
如果你串行执行——浪费时间。
4. multimodal 默认支持
Claude 支持图片——你的 AI 产品也该支持。
用户截图发给 AI 问"这个 UI 有什么问题"——这是个常见场景。
5. 5 分钟 TTL 要规划
prompt cache 5 分钟过期——如果你的 session 间隔超过——cache 失效。
可以加 heartbeat(每 4 分钟发个小请求保活)——或者接受失效。
具体策略看场景。
6. pause_turn 处理
Claude 的 pause_turn 是个独特状态——你的主循环要识别。
其他 provider 没这个——fallback 到普通完成处理。
7. 跟着 Anthropic 看新 features
Anthropic 经常发布新 API features——订阅他们的 changelog、试用 beta 功能。
很多新能力先在 Anthropic 出现——你能比竞品早 3-6 个月用上。
8. 不要过度依赖 Anthropic 独有特性
虽然 Anthropic 强——但你的产品如果只跟 Anthropic 绑——会失去灵活性。
把 Anthropic 独有特性作为"增值"——基础功能保持跨 provider 兼容。
最后一个观察。Anthropic 的 API 是当前 LLM 协议事实标准的"参考实现"——OpenAI 的 Chat API 算是"最小公分母",Anthropic 算是"完整版"。
理解 Anthropic 设计——你看其他 provider 的设计立刻能识别"缺什么"。
opencode 的 anthropic-messages.ts 845 行不是"过度工程"——是对 Anthropic 完整能力的充分利用。其他 adapter 简单——是因为对应 provider 没那么多能力可用。
下一章 6.3 我们看另一极——OpenAI 的协议。它是 LLM 协议的"最小公分母"——简洁但能力有限。