拆.
协议与适配——AI 怎么对接不同 LLM · 第 02

Anthropic 的协议

thinking、cache、tool_use

4500读完约 23 分钟craft:B+发布于 2026-06-21

一、原理: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 —— 要调 tool
  • max_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 协议的"最小公分母"——简洁但能力有限。