第 4 章:智能体(Agent)、收件箱(Inbox)与轮次/步骤
1. 本章定位
这一章沿新版 ReactLoopAgent 追踪一次输入如何变成多个模型与工具步骤。
2. 学习目标
- 区分
followup()、steer()、inject()。 - 解释轮次(Turn)与步骤(Step)。
- 追踪
turn()、step()、buildRequest()、prepareCall()。 - 解释取消如何穿过模型流与工具执行。
3. 前置知识
可把 Agent Loop 类比为 reducer 加 effect 的状态机,把 Inbox 类比为带边界的事件队列。局限是模型和工具是长异步任务,取消是协作式的,Turn/Step 边界还必须写入 durable log。
4. 对应源码
packages/core/agent-loop/src/agent.ts:70:ReactLoopAgent。packages/core/agent-loop/src/agent.ts:122:send/followup/steer/inject。packages/core/agent-loop/src/agent.ts:255:turn()。packages/core/agent-loop/src/agent.ts:341:step()。packages/core/agent-loop/src/agent.ts:453:buildRequest()。packages/core/agent-loop/src/agent.ts:489:prepareCall()。
5. 工作原理
followup 建立下一 Turn,steer 在下一 Step 改变正在运行的方向,inject 只排队、不主动唤醒。一次 Turn 可以包含多个 Step:每个 Step 派生历史、装配 Prompt、准备 LLM 调用、消费 chunk;若得到 tool/call,就执行工具、写回 tool/result,再进入下一 Step。
6. 执行流程
无图回退:UI → Inbox → turn() → step() → SystemPrompt + deriveMessages() → prepareCall() → LLM stream → ToolRuntime(可选)→ Session Log → 下一 Step 或 turn/end。
7. 关键源码讲解
公开输入方法只返回入队结果,不代表最终回答。最终状态通过 Session events 被 UI 或协议层观察。prepareCall() 把适配器选择冻结到一次调用;取消信号需要同时约束 LLM iterator、工具任务和 Turn 收尾,不能只改变 UI 状态。
8. 调试与观察方法
断点:turn() 开始/结束、step()、prepareCall()、工具结果写回处。观察 Inbox 边界、当前 phase、AbortSignal、最后事件 seq。事件停在 request/start 后通常指向 LLM;停在 tool/call 后通常指向策略、批准或工具 body。
9. 本章实践任务
用 mock LLM 先返回一个 tool/call,再返回最终文本;断言一个 Turn 包含两个 Step,tool/result 位于两次模型调用之间。再中途 abort,证明终态只有一次。
10. 常见误区
- 一个用户输入不等于一个 Step。
inject()不保证立即执行。- 取消不是删除已经写入的 durable event。
11. 自测题
followup、steer、inject的唤醒语义有何不同?- 为什么工具结果会触发下一 Step?
prepareCall()在哪一层发生?- 如何从事件判断卡在 LLM 还是 Tool?
- 设计一个“取消恰好发生在工具完成时”的测试。