Agent Loop 分层与机制选择
一个简单循环跑通以后,不必立刻升级成复杂工作流。先看实际遇到了什么问题:会卡住,就补停止机制;任务很长,再补计划;需要重启后继续,再考虑持久化执行。下面按问题选择机制,不把分层图当作必经升级路线。
版本与资料依据
last_verified:2026-08-24version_scope:stable engineering conceptssource_type:primary-paper + engineering synthesisstability:stable-concept
1. 五层演进
flowchart LR
A[Minimal Loop] --> B[Reliable Loop]
B --> C[Planned Execution]
C --> D[Workflow]
D --> E[Durable Execution]
| 层 | 新增状态 | 主要目标 | 不是默认加入 |
|---|---|---|---|
| Minimal | messages、step、tool result | 跑通 observe-think-act | planner、memory |
| Reliable | budget、validation、error、stop reason | 可停止、可诊断 | 多 Agent |
| Planned | plan、dependency、progress、replan reason | 长任务分解与跟踪 | 每轮 reflection |
| Workflow | node、transition、approval、compensation | 确定性控制 | 开放式全自主 |
| Durable | checkpoint、lease、attempt、idempotency key | 崩溃恢复与至少一次执行治理 | 把数据库当消息队列随意轮询 |
2. 机制决策卡
ReAct / Tool selection
- 要解决什么问题:模型需要根据观察选择下一动作。
- 怎样解决:在推理与行动之间循环,将 tool result 作为新 observation。
- 需要保存什么状态:messages、available tools、step、budget。
- 容易出什么问题:重复调用、错误工具、把工具输出当可信指令。
- 什么时候适合用:动作空间小到中等、每步结果影响下一步。
- 什么时候不必用:固定步骤可由普通程序稳定完成。
- 一个小例子:读取文件→定位符号→生成补丁→运行测试。
- 实际运行还要处理什么:tool schema、permission、timeout、evidence、loop guard 由 Harness 强制。
Plan / DAG / Scheduler
- 要解决什么问题:任务有可描述依赖、并发机会或长时间进度。
- 怎样解决:Plan 描述目标与依赖;DAG 表示静态偏序;Scheduler 选择 ready task 并分配资源;失败后按证据 replan。
- 需要保存什么状态:task status、dependencies、artifacts、attempt、owner、deadline。
- 容易出什么问题:计划过期、伪并行、共享文件冲突、完成状态没有证据。
- 什么时候适合用:多文件迁移、构建/测试/部署等具有独立验收点的工作。
- 什么时候不必用:两三步可直接完成的任务。
- 一个小例子:
edit -> unit tests -> build,只有前置成功才解锁后续。 - 实际运行还要处理什么:原子状态转移、lease、幂等、取消传播、并发资源锁。
Output Parser / Validation
- 要解决什么问题:自由文本不能直接驱动程序。
- 怎样解决:优先使用 provider 原生 structured/tool output;随后 schema parse、语义校验、状态机校验。
- 需要保存什么状态:raw event、parsed decision、validation errors、repair count。
- 容易出什么问题:JSON 合法但语义错误、旧 schema、重复 tool call id。
- 什么时候适合用:任何会触发副作用或状态转移的模型输出。
- 什么时候不必用:纯展示文本可直接渲染,但仍需内容与引用检查。
- 一个小例子:
{type:"tool", name:"read_file", args:{path:"..."}}。 - 实际运行还要处理什么:解析失败不执行;错误作为受限 observation 回填,repair 次数有上限。
Retry / Loop Guard / Termination
- 要解决什么问题:暂时错误与无限循环需要不同处理。
- 怎样解决:只对可重试错误退避;用 step/time/token/cost/duplicate-action/oscillation guard;以 final、goal validator、用户取消或预算耗尽停止。
- 需要保存什么状态:attempt、error class、next delay、budgets、last action fingerprint、stop reason。
- 容易出什么问题:重试副作用、把确定性错误重试到超时、停止后仍有子进程。
- 什么时候适合用:所有可靠 Agent。
- 什么时候不必用:不存在“无限预算”的例外。
- 一个小例子:网络 503 最多三次指数退避;schema 错误最多一次修复。
- 实际运行还要处理什么:idempotency key、cancellation token、child cleanup、最终状态持久化。
Reflection
- 要解决什么问题:候选结果可能需要基于反馈修正。
- 怎样解决:让 verifier、测试或独立 rubric 产生可执行反馈,再进入候选更新。
- 需要保存什么状态:candidate、evidence、feedback、revision。
- 容易出什么问题:同一模型无新证据地自我肯定,token 成本升高。
- 什么时候适合用:有测试、lint、judge 或清晰 rubric。
- 什么时候不必用:每轮机械反思或没有新 observation。
- 实际运行还要处理什么:修订次数、回归集和 accept/reject 条件固定。
3. 状态机底线
允许状态集合必须封闭,例如 ready → running → succeeded|failed|cancelled;failed → ready 只能由明确 retry/replan 事件触发。每次转移记录 who/when/input/evidence,这样 trace 才能用于回归而不只是日志堆积。
用一次中断决定是否需要更重的运行时
先做一个可以重新运行的只读搜索任务。它失败后从头查一次,通常容易处理。再把任务改成“创建工单后等待负责人确认”:进程此时崩溃,重新从头执行可能创建两张工单。
这才是引入持久执行的具体理由。保存一份聊天历史,解决的是以后能看见过程;执行引擎还需要记录哪些步骤已完成、哪一步结果未知,以及恢复时怎样处理。Pydantic AI 的文档也明确区分了步骤存储与持久执行引擎。
练习时在工具返回前、返回后但保存检查点前各模拟一次崩溃。若只在最后一步保存 done=true,第二种故障仍可能重复执行。要给外部动作稳定的业务幂等键,或先查询其真实结果。检查点的存在本身,不是“外部副作用恰好一次”的证明。
本节的核验依据
2026-10-25 查阅。下面的链接支持本节的机制说明;练习场景和选型建议是本教程的教学设计。