ESSAY·

Anthropic API:模型接口协议

深入解析 Messages API 的内容块、工具回传、流式增量、停止原因与上下文续接,比较 OpenAI 接口并给出 Harness 适配边界。

最近修订:2026.09.07

阅读导航 · 第 7 / 7 篇

Anthropic API 的 Messages 接口把一轮模型响应表示为内容块组成的 Message。对 Harness 来说,关键不只是拿到一段回答,而是判断内容块属于文本、工具请求还是其他类型,并据停止原因决定执行、续接、验收或失败处理。

本文核对 2026-09-07 Claude 官方文档,重点讨论直接调用 Messages API。传统请求使用 anthropic-version: 2023-06-01;这个 API 版本头不等于模型版本,也不代表所有新功能无需额外配置。示例采用待配置模型 ID,未发送真实模型请求。API 概览

架构:内容块适配器连接模型与 Runtime

flowchart TB
%% title: 系统架构图
    H[Harness] --> C[system、messages 与 tools]
    C --> A[Messages API Adapter]
    A --> M[Claude API]
    M --> B[内容块与停止原因]
    B --> N[按类型归一化]
    N --> H
    H --> T[客户端工具执行]
    T --> C

API 的 Message 是模型交互对象;Runtime 的 Task 是用户工作对象。一次 end_turn 可以结束模型回答,但任务可能还需要验证文件、等待用户审查或运行测试。

直接 API 使用其认证方式与版本头;经云平台接入时,认证、端点和功能支持需要单独核验。不要把直接 API 的请求头机械搬到所有托管渠道。

请求的组成:指令、消息和工具

字段责任容易混淆的地方
model选择模型不是 API 协议版本
max_tokens限制响应生成预算不是整个 Agent 的预算
system从会话开始生效的系统指令不等于用户消息前加一句提示
messages当前轮次所需的交互历史不自动代表服务器保存了业务会话
tools描述可用工具声明工具不等于执行工具

起始系统指令放在顶层 system。当前官方文档也为部分模型定义了会话中途的 system 消息及位置规则,因此不能再笼统断言“所有 Messages 都只允许 user 和 assistant”。具体模型和模式需按文档检查。消息组织

下面是作者构造的请求形状,MODEL_ID 需替换为实际可用模型:

{
  "model":"MODEL_ID",
  "max_tokens":800,
  "system":"查询工单状态,不能修改工单。",
  "messages":[{"role":"user","content":"查询 T-17。"}],
  "tools":[{
    "name":"get_ticket",
    "description":"查询指定工单的状态。",
    "input_schema":{
      "type":"object",
      "properties":{"ticket_id":{"type":"string"}},
      "required":["ticket_id"]
    }
  }]
}

工具参数契约放在 input_schema,不能直接复制 OpenAI Responses 的 parameters 包装。工具是否支持 strict、特定流式参数等,还要核对模型与功能的支持范围。工具定义

直接 HTTP 接口的主要路径是 POST https://api.anthropic.com/v1/messages,JSON 请求体配合 content-type、anthropic-version 及选定认证方式。常见 API Key 方式使用 x-api-key;不要把用户 Token、MCP Server Token 和模型服务凭据混作同一个头。

版本兼容应同时记录端点、API 版本头、模型标识和启用的 beta 功能。只记录一个 SDK 版本,无法解释为什么同一工具定义在两个部署中被不同地接受。

内容块与工具结果形成连续历史

模型可能返回一个包含文本和 tool_use 的 assistant Message。客户端工具调用块包含 ID、名称和结构化 input;应用执行后,把对应的 tool_result 放入下一条 user Message,用 tool_use_id 关联原调用。工具回传

sequenceDiagram
%% title: 工具闭环时序图
    participant H as Harness
    participant C as Claude API
    participant T as 客户端工具
    H->>C: messages 与 tools
    C-->>H: assistant 内容块:tool_use
    H->>H: 校验输入与执行权限
    H->>T: 调用工具
    T-->>H: 业务结果或执行错误
    H->>C: 保留 assistant 块并追加 user tool_result
    C-->>H: 后续内容与 stop_reason

普通客户端工具闭环要求结果紧随对应的工具调用消息;同一 user 消息中,工具结果块应放在普通文字前。多个工具调用要逐一对应结果,不能只回传最先完成的一个后就遗失其他调用。

工具执行失败可以用 is_error 表达,和 HTTP/API 请求失败不是同一层错误。涉及服务端工具、混合工具或较新的异步机制时,应遵守对应功能的专门规则,不把普通客户端工具的简化顺序泛化到所有模式。

下面是单个客户端工具调用及其结果的消息片段,假定请求所需的其他历史仍完整保留:

[
  {"role":"assistant","content":[{"type":"tool_use","id":"toolu_7","name":"get_ticket","input":{"ticket_id":"T-17"}}]},
  {"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_7","content":"工单状态为 open。"}]}
]

与 OpenAI Responses 的差异不是单纯重命名 ID:这里的工具请求和结果位于不同角色的 Message 内容块中。适配器需要保留块顺序和原 assistant 消息,而不是将每个工具块独立转换成一条任意角色的文本。

stop_reason 决定下一步

常见停止原因含义Runtime 后续动作
end_turn模型本轮自然结束检查业务完成条件
tool_use需要处理客户端工具调用校验、执行并回传
max_tokens输出达到限制标记未完整,决定续接或调整预算
stop_sequence命中配置的停止序列检查是否符合应用预期
pause_turn服务端长运行工具等场景暂停按该功能的续接规则处理
refusal模型拒绝向产品层传达明确结果

这张表覆盖常见情形,不是永不变化的完整枚举。未知停止原因应保留原值并按保守策略处理,不能默认归为成功。停止原因

stateDiagram-v2
%% title: Messages 调用状态语义图
    [*] --> 生成中
    生成中 --> 工具待处理: tool_use
    工具待处理 --> 生成中: 回传结果
    生成中 --> 等待续接: pause_turn
    等待续接 --> 生成中: 按规则继续
    生成中 --> 应用验收: end_turn
    生成中 --> 输出不完整: max_tokens
    生成中 --> 已拒绝: refusal
    生成中 --> 状态未知: 流断开
    应用验收 --> [*]
    已拒绝 --> [*]

图是 Runtime 决策模型,不是新增 API 状态。一次工具成功后模型仍可能拒绝后续工作;整体任务记录应保存已经发生的操作,而不能因最后一句拒绝就把整个任务标记为“未执行”。

流式协议按内容块归并

标准消息流包含 message_start,随后是按 index 关联的 content_block_start / delta / stop,再接顶层更新及 message_stop。流中还可能出现 ping 或 error;HTTP 已返回 200 并不能排除后续流内错误。Streaming Messages

flowchart TB
%% title: 流式数据流图
    S[SSE 字节流] --> F[完整事件解析]
    F --> I[按 content block index 分流]
    I --> T[text_delta 缓冲]
    I --> J[input_json_delta 缓冲]
    I --> X[其他受支持内容块]
    J --> P[块结束后解析工具参数]
    F --> U[message_delta 与停止信息]
    U --> R[最终 Message 与 Usage]
    T --> R
    X --> R

工具参数增量是部分 JSON 字符串,而最终 tool_use.input 是对象。不能把每个分片单独解析失败当作模型错误,也不能提前运行只收到一半参数的命令。

Usage 增量中的部分统计是累计值;实现需按具体字段语义更新,不能把每条事件的累计数再相加。流中途失败时,界面已展示的文字也应保留“未完整”状态,而不是伪造一个 end_turn。

Thinking 与缓存不是普通文本优化

涉及 Thinking 的内容块可能带有签名或不可直接展示的状态。在需要续接的工具循环中,应按具体模型要求保留相关块,不能把用户可见摘要当作可替换的完整状态。Thinking 文档

Prompt Caching 利用可复用前缀减少重复处理成本,但缓存命中不代表服务端替应用保存了全部会话,也不是长期记忆。工具定义、系统指令或前缀变更会影响缓存复用;写入和读取缓存的 Usage 需要单独观察。Prompt Caching

跨模型降级时尤其容易丢失语义:某个模型接受的 Thinking 块、系统消息位置或工具配置,目标模型未必接受。适配器应先判断能否安全转换;不能静默删掉陌生块之后仍宣称完整保留上下文。

与 OpenAI API 的映射边界

语义Anthropic MessagesOpenAI Responses
普通输出Message 的 content blocks类型化 output Items
函数定义参数input_schemaparameters
客户端工具请求tool_use 块function_call Item
工具结果关联tool_use_idcall_id
结果回传位置user Message 的 tool_resultfunction_call_output Item
继续决策依据stop_reason 与内容块Response 状态与输出项

OpenAI 一侧的对象和工具形状见其迁移文档。字段映射只是开始:停止原因、服务器工具、会话续接、Thinking 和缓存都需要行为测试。

错误处理应分别考虑参数错误、认证失败、限流、服务过载以及流内失败;重试必须受总截止时间和预算约束。自动重试不能代替工具副作用对账。API 错误

实际验收至少覆盖:多个 tool_use、工具执行错误、参数分片、输出截断、拒绝、断流、缓存计量和模型切换。本文解释协议与适配设计,不报告真实模型质量或网关兼容率。模型接入整体取舍见OpenAI API和LLM Gateway。