大可的 AI Builder 手记
跟随系统
颜色主题
长沙小桌实战
大可 Dako
大可 Dako大可 DakoAI Builder · Agent 实践者用 AI 做真正能用的产品。专注探索 Agent 工程化落地、Vibe Coding 实践与商业化交付。
内容平台即将上线,敬请期待
「停」是五件不同的事,要分别确认模型流结束本次请求收到结束信号,可能是截断工具批次返回工具停 ≠ 这一轮停,模型还要看结果turn 结束结果已交回、无待处理、收件箱无新消息driver idle暂无下一条 turn,仍可被 followup 唤醒Goal 结束持久状态落定:complete / blocked / paused每层结束原因独立记录,idle 不是完成
工具停了不代表这轮停了,idle 不代表做完了。

循环工程:准入与停止

Loop 不是定时调一次 prompt。它有七项准入条件、五层停止语义和一条消息队列续行规则——「定时调用一个 Prompt」不构成 Loop,idle 也不等于完成。

Loop 不是「定时调用一个 Prompt」。一次定时调用没有持久游标、没有幂等键、没有独立验证,失败既不能恢复也不能审计——它不构成 Loop。真正的循环工程要同时回答两组问题:凭什么让任务循环起来(准入),以及凭什么算停了(停止语义)。while (hasToolCalls) 在 demo 里够用,一进生产就不够:结束要在好几个不同的地方分别确认。

Harness 管一次,Loop 管多次

分工先划清:Harness 定义一次运行的能力、约束和恢复机制;Loop 管理多次运行之间的触发、状态、验证和持续改进。一个完整的 Loop 走五步:Discover → Execute → Verify → Persist → Schedule——发现任务、执行、验证结果、把状态存到对话之外、再次调度 dsh-pi-stop。

其中两条硬规矩:执行状态必须保存在对话之外(内存里的状态进程一挂就没);每个工作项要有稳定的幂等键(同一项被重复触发时不产生重复副作用)。Loop 也不许改自己的 P0——自动修改自己的审批规则和安全边界,等于把刹车也交给油门 agent-trend-2026。

七项准入,缺一项就退回

条件 要求
重复性 任务周期性出现或可由稳定事件触发
可验证性 结果可自动检查、看环境状态或有明确人工 Gate
可操作性 Agent 有受控的读取、修改、测试和交付能力
可恢复性 执行可隔离、可重试、可回滚、可停止
经济性 单轮成本和单位成功成本可预算
可治理性 有 Owner、权限、审计、Kill Switch 和升级路径
可沉淀性 loop 失败也应留下夹具、规则或技能,而非只留聊天记录

任一关键条件缺失,就退回单次 Agent、Workflow 或人工流程。这张表和 多 Agent 什么时候才值得 的准入条件是同一类工具:不是劝你别建,是逼你在建之前把每一项答出来。准入之后还有第二层问题——loop 里面装什么、会怎么坏,见 循环工程:控制面与失败模式。

「停」是五件不同的事

一个真实故障把五层拍在桌上:Agent 接工单建 PR 遇到 504——页面看不到 PR,但服务端可能已经创建;盲目重试可能建出重复 PR,就此收工又可能埋掉真失败;PR 建好了 CI 还在排队,「模型说已完成」算完成吗 dsh-pi-stop?

这时候「停」必须分层确认:① 模型流结束,只说明本次请求收到结束信号——可能是 max-tokens、报错或取消;② 工具批次返回,工具停了不代表这轮停了,模型还要看结果;③ turn 结束,工具结果已交回、无待处理回复、收件箱无新消息;④ driver idle,暂无下一条 turn;⑤ Goal 结束,持久状态落定为 complete / blocked / paused。idle 不是完成——外层的 Goal Driver 下次检查仍可能 followup 把它叫回来。平时一路顺利看不出差别,一旦 504、取消、进程崩溃、CI 排队同时发生,日志说不清「到底停在哪一层」,恢复就变成猜。

续行写消息队列,不合并布尔值

多个插件、多个 hook 都想表达「先别停」,怎么合并?布尔回调是最糟的答案:一堆 should_continue 标志位互相打架,谁也说不清是谁在什么时机续的行。正确做法是让续行意图走消息队列:插件要续行,就向下一 step / turn 的收件箱写一条消息,核心循环在 stopping hook 之后重读收件箱,再决定停还是继续 dsh-pi-stop。

好处有两个:多插件的续行语义不需要合并布尔值,每次续行意图都留下可审计记录——出事时你查得出「是哪个插件在 turn 结束后又塞了一条消息」。这和 事件只在安全点被消费 是同一个设计:队列在边界被读,而不是在执行中途横插一脚。

结束原因分开记,截断的参数不可执行

每层结束的原因要独立记录,且分清六种:completed / blocked / max-tokens / aborted / error / interrupted。两个最容易混的:aborted 是收到取消后主动清理,interrupted 是进程消失后由恢复层补上的状态——副作用审计和重试决策完全不同,混用会把你引向「对可能已建出的 PR 再重试一次」。turn 级的结束原因要保留到 turn 结束:第 1 步撞了 max-tokens、后续步骤补完,turn 仍记 max-tokens,只盯最后一个 step 会把截断看成成功 dsh-pi-stop。

还有一条写操作的安全线:max-tokens 截断要发生在工具参数解析之前。半截 JSON 就算解析器补全、schema 校验通过,参数的意思可能已经变了——写操作的副作用落地就收不回来。状态说不清时先停,不盲目重试,这条判断又回到 故障要先分类再计数:分类在先,重试决策才有依据。

参考资料

  1. Agent Loop 什么时候该停?DSH 和 Pi 给了两种答案
  2. Agent 开发指南:技术太多,该怎么学?