展开本页目录
开始前准备什么
- 保存脱敏历史顺序、原始 call ID、工具名称与执行状态。
- 使用只读虚构工具测试;真实写操作先确认是否已经执行。
- 确认当前请求是 Chat、Responses 还是原生 Messages。
- 定位缺失阶段
- 保留原 call ID
- 执行并校验结果
- 补齐全部回传
- 继续模型回合
3 组缺失、错配、并行结果的完整前后 JSON。
只验历史结构,不执行工具或联网。
完整 Chat 循环的顺序
工具参数来自模型事件,工具结果来自实际执行。保留 assistant 消息后,再附工具结果;不要只保留“库存 7”正文。示例库存为固定虚构数据,不能挪作真实业务结果。
固定虚构库存的正确历史
{"messages":[
{"role":"user","content":"查询示例库存。"},
{"role":"assistant","content":null,"tool_calls":[
{"id":"call_demo_a","type":"function","function":{"name":"lookup_stock","arguments":"{\"sku\":\"QR-SKU-001\"}"}}
]},
{"role":"tool","tool_call_id":"call_demo_a","content":"{\"stock\":7,\"fixtureOnly\":true}"}
]}三组错误,都有完整历史修复
下载 JSON 给出每组完整 before、illustrativeError、after。错误文字是结构演示,未声称来自本次 apizt 400;实际供应商可能返回不同 code 与 message。
| 修复前 | 示意报错 | 修复方式 |
|---|---|---|
| assistant tool_calls 后直接出现 user | tool_calls 缺少对应 tool 结果 | 先回传真实结果,再继续 user |
| call_demo_a 返回后用 call_other 回传 | No matching tool call for tool_call_id | 使用原始 call_demo_a,不生成新 ID |
| a / b 两个并行调用只回传 a | Missing tool response for call_demo_b | 执行 b 并回传,不能跳过 |
- 修复前
- assistant tool_calls 后直接出现 user
- 示意报错
- tool_calls 缺少对应 tool 结果
- 修复方式
- 先回传真实结果,再继续 user
- 修复前
- call_demo_a 返回后用 call_other 回传
- 示意报错
- No matching tool call for tool_call_id
- 修复方式
- 使用原始 call_demo_a,不生成新 ID
- 修复前
- a / b 两个并行调用只回传 a
- 示意报错
- Missing tool response for call_demo_b
- 修复方式
- 执行 b 并回传,不能跳过
三种 ID 不可直接改名互换
Responses 的 item.id 不等于 call_id。适配器应转换整个请求、返回、历史和流式事件,不只是把一个字段改名;SDK 升级后复跑固定循环。
| 协议 | 工具请求 | 工具结果字段 |
|---|---|---|
| Chat Completions | assistant.tool_calls[].id | role=tool,tool_call_id |
| Responses | function_call.call_id | function_call_output,call_id |
| Messages | tool_use.id | tool_result,tool_use_id |
- 协议
- Chat Completions
- 工具请求
- assistant.tool_calls[].id
- 工具结果字段
- role=tool,tool_call_id
- 协议
- Responses
- 工具请求
- function_call.call_id
- 工具结果字段
- function_call_output,call_id
- 协议
- Messages
- 工具请求
- tool_use.id
- 工具结果字段
- tool_result,tool_use_id
工具失败时,按真实状态恢复
- 未执行:按权限与参数校验记录失败,回传真实错误结果,不宣称业务已完成。
- 已执行:从可靠业务记录取出实际结果,避免再次扣款、发送或写入。
- 状态未知:先回查工具的稳定业务 ID,暂停后续副作用,不用占位成功绕过。
- 并行工具可能分别成功或失败;每个 call ID 保留自己的状态与输出。
用离线夹具检查历史,再验 SDK
夹具检查漏结果、错配和并行缺项,固定 3 组前后对照。它不执行任何工具、不验证自然语言答案或全部 SDK 格式。浏览器工具也只检查粘贴历史,完整 SDK 循环可用库存示例另测。
下载文件放同一目录
python3 check-request-fixtures.py tool-history-fixtures.json回传正确后,最终回答也要验收
| 对象 | 应当保留 | 通过条件 |
|---|---|---|
| 调用 | 原 ID、函数名、完整参数 | schema 可解析且权限允许 |
| 执行 | 时间、状态、实际输出 | 业务记录和结果能对应 |
| 回传 | 所有 call ID、正确协议历史 | 没有孤立结果和未补齐调用 |
| 回答 | 模型最终正文 | 只依据真实工具输出 |
| 账单 | 全部模型回合和工具成本 | 不能只计算第一回合 |
- 对象
- 调用
- 应当保留
- 原 ID、函数名、完整参数
- 通过条件
- schema 可解析且权限允许
- 对象
- 执行
- 应当保留
- 时间、状态、实际输出
- 通过条件
- 业务记录和结果能对应
- 对象
- 回传
- 应当保留
- 所有 call ID、正确协议历史
- 通过条件
- 没有孤立结果和未补齐调用
- 对象
- 回答
- 应当保留
- 模型最终正文
- 通过条件
- 只依据真实工具输出
- 对象
- 账单
- 应当保留
- 全部模型回合和工具成本
- 通过条件
- 不能只计算第一回合
怎样确认已经完成
- 每个工具结果对应原始调用 ID。
- 并行调用全部回传后才进入下一回合。
- 已执行和未知副作用分别恢复。
- 最终正文与真实工具结果一致。
常见问题
可以手动生成一个 tool_call_id 吗?
回传必须引用模型原始 ID。自己生成的新 ID 无法正确对应之前调用;测试夹具的 demo ID 仅用于离线演示。
工具报错也要回传吗?
应按具体协议回传真实错误结果,让模型知道状态;不能伪装成功。写操作是否已发生要先回查。
并行工具返回顺序必须一样吗?
关键是每个结果对应正确 ID、同一待处理组全部补齐且历史结构符合协议。按框架约定保留稳定顺序更便于排错。