一轮工具调用后,谁决定下一步?
假设模型要求运行一条命令,命令已经返回。**工具返回只是一个观察点,不等于 Agent 结束。**下一步可能再请求模型、等待当前调用或人工处理、也可能结束;决定权落在各项目的循环和停止契约中。下表对齐的是固定源码的一条路径,不是四个产品的功能排名。四篇均于 2026-09-23 核对,均为静态源码阅读,未录制同一任务的运行轨迹。
图的文字版 · 可编辑图源 · PNG 预览
| 固定范围 | 触发:谁决定下一步 | 状态:看什么 | 工具结果写回 | 停止、拒绝与等待 |
|---|---|---|---|---|
| Pi 核心循环 | runLoop;finishTurn 可改判。 | 消息、工具批次、steering / follow-up 队列。 | tool result;执行失败标 isError。 | finishTurn=end 优先停;steering 等轮间,follow-up 等结束点。 |
| mini-SWE 基类 | run() 每轮检查消息尾部。 | messages[-1].role。 | 环境 observation 追加到 messages。 | 尾部 exit 返回;格式错误可反馈再试,一般异常重抛。 |
| OpenCode 会话 | processor 返回结果;runLoop 再判断。 | ToolPart 状态与会话状态分开。 | tool-result/error 收束 part。 | stop 结束;模型流故障可在 processor 内退避重试;compact 转压缩。 |
| Kimi Code 单 turn | runTurn;非 tool_use 时问停止回调。 | steer 缓冲、步数、取消信号。 | 工具批次排空 tool.result 事件。 | tool_use 续步;steer 等步边界;取消/上限可终止。 |
固定源码证据
- Pi ·
earendil-works/pi@898ab804050730e9dcefb4443875d5a932aa6a32:回合与队列决策、工具结果和前置拒绝、整批结果的terminate判断。finishTurn=end优先于自然结束点的 follow-up。terminate检查针对整批已收束结果,其中可能有执行前形成的错误结果;它影响后续循环,单凭该标记不能断言工具都执行成功或 Agent 最终结束。coding-agent 还在message_end记录常规消息,这是外层职责。 - mini-SWE-agent ·
SWE-agent/mini-swe-agent@04d809ceab9df28f9adaed044884180159172930:循环、异常与尾部判定、本地提交哨兵。限额、成功提交、连续格式错误达阈值可产生exit;一般异常先记录再抛出。默认 CLI 的交互子类另有人工确认,表格未覆盖。 - OpenCode ·
anomalyco/opencode@18ef3cc7c5a25b82114c953a80ccc09f4988f74e:外层退出检查、processor 结果进入 loop、ToolPart 结果与清理、停止和退避。ToolPart的completed/error与会话的busy/retry/idle是两层;未收束 part 可在清理时记为 interrupted error。单个 parterror不自动令 session 停止或重试。 - Kimi Code ·
MoonshotAI/kimi-code@75a894e9ad5e8d49509664b3daaa1bbc9bb39432:通用循环、工具批次与 step 封口、steer 的缓冲与刷新。新 steer 在活动 turn 中先入缓冲,不立即取消 step。工具授权回调位于执行前;拒绝后的完整消息路径尚未核对。
怎样读这些差别
Pi 和 Kimi Code 都有“忙时新输入”,但等待点不相同:Pi 明分 steering 与 follow-up 两条队列;Kimi Code 将活动 turn 的 steer 暂存在 steerBuffer,在下一 step 或停止回调处刷新。mini-SWE-agent 的基类把结束折成消息尾部 exit;OpenCode 同时保留调用级的 ToolPart 和会话级的处理器结果。这些是控制结构差异,不是速度、可靠性或用户体验的实测比较。
读者练习:给四套路径各放入“命令返回权限错误,随即用户又发来一句新指令”。先标出错误进入哪种账本或状态,再指出下一次模型请求之前必须经过哪个判断。若证据只覆盖基类、单 turn 或处理器,不要替缺失的 CLI/提供商行为补答案。
失败与未知
- 失败不自动重试。 Pi 的工具错误可成为
isError结果;mini-SWE-agent 的格式错误反馈与一般异常分流;OpenCode 仅对策略接受的模型流故障退避重试;Kimi Code 此切面仅证明工具批次、停止与授权闸口,未验证工具拒绝消息如何呈现。 - 覆盖范围不等。 Pi 行连接 agent-core 与部分 coding-agent 外壳;mini-SWE-agent 只覆盖
DefaultAgent/本地环境,默认 CLI 的交互子类另算;OpenCode 只读session路径,未审计所有 provider、MCP 和插件;Kimi Code 只读agent-core的单个 turn,未追踪 CLI 输入接线、外层 goal 运行或持久化恢复。 - 均无同任务运行观察。 没有测并发工具副作用、人工等待时长、取消竞态、故障恢复或发布版本对应关系。正文中的“可继续”只说明固定源码允许该分支,不承诺现实任务一定成功。
图的文字说明 · loop-and-stop
图按行读,不是四个项目串行执行的流程。每行先给出固定源码切面,再从“工具结果写回”走向该系统自己的控制闸口:
- Pi:tool result 进入
runLoop的消息路径。steering 等轮间,follow-up 等本来将结束时;finishTurn=end可优先结束。 - mini-SWE-agent:环境观察进入
messages;DefaultAgent.run()在一轮保存后看最后消息,非exit再循环,exit则返回其extra。 - OpenCode:流事件把结果写成
ToolPart.completed/error;SessionProcessor的continue/stop/compact与外层runLoop才决定后续。图中的“流内 retry”指模型流处理器内按策略退避,不是与continue/stop/compact并列的返回值;调用级error本身也不等于重试。 - Kimi Code:工具批次排空
tool.result事件;tool_use后runTurn()进入下一 step。活动 turn 收到的 steer 在 step 边界刷新;无继续请求、取消或上限可能结束当前 turn。
方框颜色仅帮助辨认四行,不表示性能或证据强弱。图省略了各项目的 provider、CLI、并行工具副作用和恢复路径;具体停止/拒绝分支及固定 SHA 见正文表格。四行均是 2026-09-23 核对的固定源码静态切面,不是一条实际运行轨迹。mini-SWE-agent 行特指基类加本地环境;Kimi Code 行限单个 turn;Pi 行含部分 coding-agent 外壳;OpenCode 行限 session 路径,因此证据粒度不等。
在线预览稿:书稿仍在校稿,系统篇以文内固定源码版本为准;静态阅读不等于运行验收。