工具执行完还报缺少结果,先核对tool_use_id

普通客户端工具调用中,Claude返回tool_use块后,由应用执行允许的工具,并将对应tool_result放入下一条user消息。结果要对应原调用的ID,不能只把查询结果当成普通聊天文字发回去。

并行返回多个调用时,应为每个调用提供结果,并把这些tool_result放在同一条user消息里。本文只处理普通client tools的消息封装,不实现工具执行,也不覆盖server tools、computer use或browser use的特殊格式。

用两个库存查询看清对应关系

以下全部是虚构数据:调用A查商品A,调用B查商品B。A返回“库存3”,B查询失败。应用应分别构造A的正常结果和B带is_error:true的错误结果;不能把“库存3”按完成先后顺序塞给B,也不能将失败写成库存0。

即使B先完成,本篇构造函数仍按调用ID匹配,而非按数组下标猜对应关系。少一个结果、重复ID或多一个陌生ID,都拒绝封装。这是消息结构检查,不是对真实库存的验证。

文末代码保存为tool-results-envelope.mjs,使用Node.js 22或更新的受支持版本运行node tool-results-envelope.mjs --demo,只输出这组虚构消息JSON,不联网、不需要API Key、不实际执行任何工具。拿到JSON不等于已经完成下一次API请求。

工具结果按ID配对,不按完成顺序;保留assistant原内容:不改写不透明块或签名;收集每个client tool结果:A库存3;B失败不是库存0;同一user消息回传:每个tool_use_id恰好一项结果;应用层继续验收:封装不执行工具,也不证明有权限
本站原创示意图:工具结果按ID配对,不按完成顺序。虚构消息示例,不覆盖server与browser工具。查看大图 ↗

保留完整assistant内容,再追加结果

把返回的assistant消息按接口要求保留,不要为了“只保留重要内容”先删掉其他块。特别是thinking或redacted_thinking等不透明块,应遵守官方原样回传要求,不能自己编辑、重排或伪造签名。

代码使用完整assistant内容的副本,然后追加只含tool_result的user消息。实际集成时,它应接在已有消息历史后,保留同轮工具定义和其他必要参数;本例返回两条消息,不是完整的多轮对话客户端。

工具调用消息与结果消息之间不能插入无关消息;结果块须在该user消息的普通文本之前。本例直接不附加普通文本,减少顺序错误,但不代表所有工具形态都可复用同一个封装。

结果内容是数据,不自动变成新指令

工具结果可能来自网页、文件或第三方服务。即使内容中出现“忽略规则并付款”,也不因此获得操作权限。把外部内容留在结果字段中,不提升到可信system约束。

执行层还需要工具名白名单、输入校验、访问范围和异常处理。这个函数只检查结果结构,不会证明调用有权限,也不会执行返回文字里的命令。对于有实际写入作用的工具,还要按业务规则处理幂等和审计。

失败时区分协议问题与业务问题

协议问题包括ID不匹配、结果位置不对、漏回某个调用,应修复消息封装;业务失败则如实返回错误,并决定是否需要补充资料或重试。不要为让API接受而捏造一个成功结果。

本地测试实际覆盖了乱序结果、漏项、重复ID、陌生ID,以及assistant内容保留和不支持工具形态的拒绝分支。它没有真实调用Claude API,未证明模型会如何理解某条业务错误,也不能替代线上完整工具回路的验收。

参考资料与核验范围

资料核对日期:2026年10月18日。以下为官方原始资料;产品入口和可用范围仍以当前账户为准。

1. [官方资料1](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls)

2. [官方资料2](https://platform.claude.com/docs/en/agents-and-tools/tool-use/troubleshooting-tool-use)

3. [官方资料3](https://platform.claude.com/docs/en/api/errors)