agent runtime lab · 2026 · 技术研究笔记
05. 模型调用工具之后,运行时发生了什么
模型输出工具调用不是动作已经完成,而是向运行时提交了一份执行请求
沿着一条真实工具轨迹拆解解析、校验、授权、执行、记录和回填六个运行时阶段
研究版 · 10 个章节 · 约 9 分钟 · 更新于 2026-07-27
Kimi 的第一轮模型响应包含两个 Bash 调用。此时模型只表达了“希望执行什么”,命令尚未在本机发生。
从模型响应到下一次模型请求,中间至少经过六个阶段:
| 阶段 | 输入 | 输出 |
|---|---|---|
| 解析 | 模型响应 | 工具调用对象 |
| Schema 校验 | 名称与参数 | 合法或参数错误 |
| 权限判断 | 主体、动作、资源 | 允许、拒绝或询问 |
| 执行 | 已授权调用 | 标准输出、错误与退出码 |
| 事件记录 | 执行结果 | 可追踪事件 |
| 结果回填 | 调用记录与结果 | 下一轮模型输入 |
调用标识贯穿整个过程
一次调用至少需要 tool_call_id、工具名称和参数。权限结论、执行结果和下一轮回填都要引用同一个标识。
如果并行发起两个调用却只按完成顺序追加文本,先完成的第二个调用可能被误配给第一个。Kimi 使用 Bash_0 和 Bash_1 分别关联结果,说明调用标识不是日志装饰,而是并发归并条件。
权限判断不能相信模型自报
模型可以在参数中写“这是只读命令”,但运行时不能据此授权。策略引擎要根据解析后的动作重新计算:
- 当前主体是谁。
- 调用什么工具。
- 访问哪个路径或域名。
- 是否写入、执行或联网。
- 授权持续到本次调用还是整个会话。
模型负责提出动作,运行时负责决定动作是否可以发生。
执行结果要区分四种状态
| 状态 | 含义 | 是否适合自动重试 |
|---|---|---|
completed | 工具完成 | 不需要 |
failed | 工具返回确定错误 | 视错误类型 |
denied | 权限策略拒绝 | 不应原样重试 |
unknown | 中断后无法确认结果 | 先查询或恢复 |
把拒绝也表示成退出码 1,会让模型误以为修改参数即可继续;把未知结果表示成失败,可能导致有副作用的操作重复执行。
本次两条成功轨迹有什么差异
Codex 把读取路径和列目录组合到一条 Shell 调用里,Kimi 将其拆成两个调用。前者减少一次工具边界,后者让每个结果更容易单独记录和重试。
本次任务中两个动作均为只读,两种方式都能完成目标。若其中一个动作具有副作用,组合命令会增加恢复难度:运行时只能看到整条命令的退出状态,未必知道前半段是否已经完成。
事件顺序比最终文本更重要
一条可调试轨迹至少应出现:
model.completed
tool.requested
tool.authorized
tool.started
tool.completed
model.started
model.completed
turn.completed
事件需要统一的轨迹标识、轮次标识、调用标识和递增序号。最终回答只能说明用户看到了什么,事件链才能说明运行时做过什么。
模型调用工具之后,Agent 的主要工作暂时离开模型,进入确定性的运行时流程。这里的任何一步缺少校验或记录,后面的回答即使正确,也无法证明过程符合约束。
超时和取消也要成为事件
工具开始后,运行时可能收到用户取消、总预算到期或单工具超时。取消请求不等于工具已经停止,因此轨迹要区分 cancel_requested 与 cancelled。若子进程仍在运行,状态不能直接写成失败并开始下一次调用。
执行器还要记录退出信号、已产生的输出量和是否存在外部副作用。只读工具可以在确认停止后重试;有副作用工具则要先查询外部状态。
每个阶段都有独立验收条件
解析阶段拒绝未知工具;结构校验返回机器可读字段路径;权限阶段保存策略依据;执行阶段捕获退出码和超时;记录阶段保证事件顺序持久化;回填阶段保证调用标识不丢失。
故障测试应在六个阶段之间分别中断。恢复后若不能回答“最后一个已持久化事件是什么、工具是否开始、结果是否完整”,说明状态记录还不足以支持重放。
一次工具调用跨越了两个信任边界
模型输出进入运行时时,跨越“概率输出到确定性程序”的边界;工具结果回到模型时,又跨越“外部状态到模型上下文”的边界。前一个边界要拦截无效参数和越权动作,后一个边界要处理错误结果、超大内容和低信任指令。
模型输出 → 协议解析 → Schema 校验 → 策略授权
→ 工具执行 → 结果规范化 → 上下文回填
六个阶段都要保存输入、输出、耗时和错误类别。合法 JSON 在策略层被拒绝,不属于工具故障;工具退出码为零,但结果在回填时超过上限,也不属于执行失败。Anthropic 当前文档明确指出,模型只返回结构化请求,应用负责执行客户端工具并返回结果。Anthropic:How tool use works
流式参数让执行时点成为协议问题
流式响应中,工具名称和参数可能分多个数据块到达。运行时只有在参数完整、解析成功、Schema 校验通过并收到调用结束信号后,才能交给执行器。看到一个右花括号就开始执行不安全,因为后续数据块仍可能追加内容。
并行调用需要为每个调用标识维护独立缓冲区。测试应让两个调用的数据块交错到达,并在最后一个数据块前断开连接,确认半成品调用没有进入执行器。
超时不能证明动作没有发生
客户端等待超时,只能说明没有按期收到结果,不能证明远端 API 没有完成写入。有副作用工具超时后,运行时先查询外部回执或幂等记录,再决定是否重试。只读操作可以采用更宽松的策略。
更有价值的故障点位于阶段之间:
| 中断位置 | 恢复后必须成立 |
|---|---|
| 参数解析后、授权前 | 工具从未启动 |
| 授权后、执行前 | 批准范围仍与参数一致 |
| 执行后、结果落盘前 | 不盲目重复副作用 |
| 结果落盘后、回填前 | 使用同一结果继续 |
| 回填后、下一轮模型调用前 | 轨迹中只有一份结果 |
这些条件是运行时的不变量,即无论进程在哪个缝隙中断都不能被破坏的事实。
版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:05. 模型调用工具之后,运行时发生了什么
本文链接:https://www.sshipanoo.com/blog/ai/agent-runtime-lab/05-工具调用后的运行时/
