Claude 报错缺少 tool_result?检查工具调用 ID 和消息顺序

Claude 或 OpenCode 提示 tool_use 缺少对应 tool_result 时,如何检查调用 ID、消息顺序、并行结果和中断记录,避免无效重试。

暖米底色的线稿封面,浅色卡纸上画有钥匙与绳线,配几何点缀和英文标题 Claude Tool Results。

Claude 提示 tool_use 没有对应的 tool_result,通常需要检查工具调用的消息记录。对 Claude 原生 Messages API 来说,assistant 发起客户端工具调用后,下一条 user 消息应携带结果,并使用同一个调用 ID。先检查这组对应关系,再重试请求。

本文针对自建集成及 OpenCode 等客户端出现的这一类错误,并不意味着所有 OpenCode HTTP 400 都是同一原因。协议规则依据 Claude 的工具调用处理文档,核验日期为 2026 年 9 月 14 日。文中示例是合成的消息片段,不是真实 API 测试记录。

先找到没有配对的调用 ID

读完整报错,在前一条 assistant 消息中找到被点名的工具调用 ID,再检查后一条 user 消息。tool_result.tool_use_id 必须与该 ID 完全一致,工具名称不能代替调用标识。

Claude 原生协议把工具结果放在 user 消息的 content 块中,这种消息结构没有原生的 role: "tool"。如果适配器同时处理其他提供商的格式,需要转换角色和字段,不能原样转发。

检查项正确关系常见问题
标识符tool_use.idtool_result.tool_use_id 一致重新生成或截断了 ID
消息顺序assistant 调用之后紧接 user 结果两者之间插入了别的消息
多个调用每个客户端工具调用都有对应结果只保留了第一个结果
user 内容顺序工具结果块在前,普通文字在后文字块出现在结果之前

一组最小消息示例

以下 JSON 只展示相关消息。完整请求还需要所选模型、工具定义、token 上限和其余对话。示例里的结果是为了说明结构而编写的,不能代替真实工具执行。

[
  {
    "role": "assistant",
    "content": [
      {"type": "tool_use", "id": "toolu_demo", "name": "lookup", "input": {"key": "demo"}}
    ]
  },
  {
    "role": "user",
    "content": [
      {"type": "tool_result", "tool_use_id": "toolu_demo", "content": "demo result"}
    ]
  }
]

不要根据聊天窗口显示的文字重建 assistant 消息,应保存 API 返回的完整结构化内容。根据模型和调用流程,思考数据等其他内容块也可能需要保留。签名校验是另一类问题,见 Claude thinking 签名错误排查

并行调用要返回完整的一组结果

如果同一条 assistant 消息调用了两个客户端工具,就收集两个结果,放入紧接其后的 user 消息。不要先交回一个结果,插入另一轮 assistant 回应,再给原调用补交第二个结果。允许附带的用户说明文字应排在全部结果块之后。

官方工具调用排错文档还说明了客户端工具与服务端工具混用的情况。如果同轮仍有未完成的服务端工具,user 消息应只包含客户端工具结果,请求也应保留 tools 数组。仅含客户端工具的最小示例不能直接套用到所有服务端工具流程。

工具失败时返回真实错误,不要补造成功结果

查询或命令执行失败,也可以返回配对正确的工具结果。对于文档所述的客户端工具错误处理方式,沿用同一个 ID,设置 is_error: true,并准确说明错误。消息是否正确配对,与底层操作是否执行成功,是两项独立检查。

客户端中断后,先确认工具究竟有没有运行。界面超时不能证明文件写入、部署或外部请求没有发生。再次执行会改变外部状态的操作前,应先检查实际状态。不要为了满足校验而伪造成功结果,也不要自动把重要操作执行两遍。

开发时可以在临时会话中,用无副作用的查询复现消息序列。只读示例能帮助定位配对问题,避免调试期间重复写入或交易。同时记录客户端版本,以及中断前后的消息。

怎样恢复损坏的会话

尝试修复前,先保存相关历史的本地副本。如果原始结果还在,就用客户端支持的恢复方式补回正确配对的消息。如果无法安全修复,保留旧会话供核对,再新建会话,简要说明已经确认完成的工作和待办事项。

随意删除工具块,可能改变模型对“哪些事情已经发生”的判断。因此,不应把删除全部会话文件作为默认修复办法。提交问题时,提供经过脱敏的最小消息序列,保留角色、内容类型和对应 ID,移除 API key、私人参数和敏感结果。

可以查看客户端发布说明,判断是否需要升级。但本文没有确认某个版本能解决所有此类问题。历史 issue 只能证明某个配置曾发生过故障,不能证明最新版仍有相同缺陷。

为什么只重试没有用

API 会在继续生成前校验消息结构。再次发送同一组没有配对的消息,结构问题依然存在。这是根据协议规则作出的判断,不是对所有客户端重试机制的实测结论。

HTTP 429 或服务过载需要另外排查。应用本文方法前,先读清状态码和错误正文。若是其他访问错误,可以参照模型找不到的排查指南(英文);那篇涉及另一种协议,不要与 Claude 工具消息配对混为一谈。

常见问题

工具返回错误,也能满足配对要求吗?

可以。真实错误结果可以对应原调用 ID。即使操作没有成功,也能在下一条消息中正确记录失败。

Claude 原生 API 应该用 role tool 吗?

不应该。原生客户端工具结果是 user 消息里的内容块。OpenAI 兼容适配器可能使用其他格式,需要遵循实际接收请求的端点协议。

新建会话算彻底修好了吗?

新会话可以隔离损坏的历史,但不能修复持续丢弃结果的适配器。还需要检查序列化逻辑,或客户端中产生错误消息序列的代码路径。

常见问题

为什么重试仍然报 tool_result 错误?
未配对的消息序列没有改变。先修复调用与结果的对应关系和顺序,再重试。
Claude 原生 API 的工具结果放在哪里?
放在 user 消息的 content 中,以 tool_result 块的 tool_use_id 对应前一条 assistant 消息的 tool_use ID。
工具执行失败,也能返回结果吗?
可以。沿用原调用 ID 返回真实错误,不要伪造成功输出。