让 Agent 长时间工作,最难的部分通常不是让它继续生成代码,而是让它知道:刚才的改动到底有没有用。

我尝试过把一项事件采集任务交给 Codex 持续执行。真正改变结果的,是把代码修改、页面操作、数据查询和失败修复连成了一条反馈链。任务结束后仍然需要人工复核,合入和发布也继续遵循原有流程。

问题不在“怎么写”,而在“怎么验”

给已有应用补充事件采集,表面上只是增加几个调用。实际验收却需要回答更多问题:用户能否进入对应页面?事件是否在正确的时机触发?字段是否符合约定?采集请求成功之后,数据是否真的出现在接收端?

静态检查能发现语法和类型错误,却无法证明整条链路成立。浏览器里出现请求,也不等于下游查询已经能看到记录。把这些证据混为一谈,Agent 就容易在“代码已经改完”时提前停止。

先跑通一个最小闭环

我会先挑一个简单场景,例如演示应用里的“保存偏好”,只做一次完整验证:

  1. 根据事件规范修改实现。
  2. 用 Playwright 操作测试页面,真实触发行为。
  3. 检查请求与接收端的记录,核对事件、字段和时间范围。
  4. 如果失败,定位原因、修改,再跑同一条验证路径。

这一步验证的是工具链本身。测试账号、页面入口、查询权限或环境配置没有准备好时,扩大任务规模只会放大阻塞。

把反馈分成几层

层次 需要的证据 能证明什么
静态检查 类型检查、lint、差异审查 改动符合部分代码约束
页面行为 可复现的操作步骤与断言 用户路径能够执行
请求发送 请求内容、响应状态 客户端确实发起了预期请求
接收端验证 指定测试范围内的事件记录 数据确实进入了目标系统
最终验收 覆盖清单与独立复核 任务满足事先约定的完成条件

每层都有自己的边界。接收端可能存在延迟,因此查询应使用有界重试;构造的错误响应可以验证前端错误分支,但不能证明真实后端在生产环境中的行为。

让“继续”和“停止”都有依据

一个可复用的任务说明可以很短,但要把目标、证据和边界说清楚:

GOAL
Implement the agreed events in a demo application.

EACH ITERATION
Make a small change, run checks, trigger the scenario,
and inspect the receiver's records.

VERIFY
Match the expected event and fields to the test action.
Record evidence for every scenario.

STOP
Stop when all required checks pass, the budget is exhausted,
or a dependency requires human input.

REPORT
List passed, failed, blocked, and unverified scenarios separately.
Do not merge or deploy as part of this task.

这是提示词示意,不依赖某个产品的命令名称。实际运行还需要由工具或运行时执行预算和权限限制,不能只期待模型记住它们。

“被阻塞”不等于“通过”。遇到登录、额外验证或缺失权限,应记录阻塞点并请求必要的人类输入。不能为了让循环继续而绕过原有安全机制。

经验应该留下来,凭据不应该

第一次跑通后,值得保存的是启动方式、验证入口、事件契约、常见失败原因、停止规则和结果格式。它们可以放进项目文档或 Skill,帮助下一次任务复用已验证的路径。

账号密码、令牌和密钥则应由受控的凭据机制提供,不应作为“记忆”写进仓库。执行记录也应区分代码提交、测试运行、数据查询和最终审核,避免把某一步的成功扩写为整个任务完成。

开放任务也需要可检查的目标

同样的思路可以用于页面还原、性能调优或模型运行环境配置。开放的是解决路径,不应开放到连验收条件都没有。

页面还原可以比较截图,但还要检查交互和可访问性;模型服务可以验证启动与示例请求,但一条成功响应不代表性能、质量和稳定性都达标。指标要覆盖真正关心的结果,并避免让 Agent 只优化容易拿分的代理指标。

怎么判断 Loop 是否有价值

我更关心三件事:它发现了哪些静态检查遗漏的问题,结果能否重现,以及人为了得到这些结果花了多少注意力。运行时长和 token 消耗只是成本,不是成效。

Loop 让 Agent 有机会根据反馈修正判断,但不会自动消除偏差。验证器本身也可能不完整;独立复核的价值在于检查证据和目标,而不只是换一个模型重复说“完成”。

我的实践顺序是:先跑通最小闭环,再扩展覆盖范围,最后把稳定的部分沉淀为可复用流程。长任务的基础,是每一轮都能知道自己有没有向目标前进。

两类任务,两种 Loop

回头看,我觉得 Loop 最适合两类任务。

第一类是流程繁琐,但结果可以客观验收。批量事件采集、代码迁移、兼容性修复,都有相对明确的交付范围。难点在于把执行与验证接起来,避免几十个场景里漏掉几个。这里的循环围绕覆盖清单展开:找出未通过项、修复、复验,再更新状态。

第二类是目标明确,但解决路径开放。性能优化、模型实验、页面还原都可能有很多候选方案。这里的循环更像实验:提出假设、做一个受控改动、测量结果、保留或回退,然后选择下一条路径。预先写死每一个步骤,可能反而限制探索。

两者都需要终态,但终态的形式不同。前者可以是“全部必需场景通过验收”;后者则需要目标阈值、优化预算或停止改善的条件。“尽可能快”没有天然终点,必须补充约束。

什么样的任务值得放进 Loop

我会先检查四个条件:

  • 结果可以判断。 每轮能回答“改善了吗”,并且指标与真实目标有关。一个好看的分数不能替代功能正确性。
  • 执行链路可达。 Agent 能用受控工具完成修改、运行和查询。如果每一轮都要等人手动操作,先改善工具接口往往比加长提示词更有用。
  • 反馈足够及时。 一轮需要很久才能得到结果时,可尝试的方案会变少。可以先用廉价检查淘汰明显错误,再让候选方案进入昂贵的端到端验证。
  • 存在可调空间。 如果每一步都完全确定,普通脚本可能已经足够。Loop 的额外价值来自对失败的诊断和对不同解决路径的探索。

例如,页面性能优化可以以固定测试条件下的加载指标为目标,同时保留功能和可访问性约束;重构可以要求行为回归通过,并减少一项明确的维护负担。目标越具体,越容易区分有效探索与无意义返工。

我会遵循的五条设计法则

1. 约束目标与边界,给路径留空间

给 Agent 清楚的验收条件,也给它完成任务所需的工具、文档和测试环境。不要一边要求它自主探索,一边让它只能读文件、不能运行最小示例。

自由度应该来自授权范围内的工具能力。允许它选择实现策略、编写验证脚本或构造测试输入,并不意味着开放生产权限或允许任意副作用。先说清楚能改什么、能操作哪里、什么需要人决定,再让它在这些边界里试错。

2. 缩短反馈周期,而不只是增加重试次数

同样的预算里,反馈越快,就越有机会排除错误假设。先做类型检查和最小复现,再跑相关测试,最后做完整验收,通常比每次都从头运行全套流程更有效。

但快速检查只是筛选。不能因为局部测试便宜,就删除最后的真实链路验证。对于有延迟的外部系统,应设置合理的等待窗口与重试上限,避免把“尚未可见”误判为“实现错误”。

3. 先稳定测量,再讨论优化

固定环境、测试输入、数据版本和比较口径,先建立基线,再判断改动是否有效。指标噪声很大时,一次上升不能证明方案更好;必要时重复测量,并把波动与稳定改善分开记录。

同时保护验收标准。实现者如果能随意删测试、放宽阈值或改掉评分逻辑,就可能在没有改善产物的情况下“达标”。验证器确实需要修改时,要把它作为独立变更审查,不能悄悄和实现混在一起。

4. 记录失败,让下一轮不用重新猜

失败记录至少包括假设、改动、验证条件、结果和下一步。一句“这个方法不行”太模糊;可复现的失败路径才有助于排除重复尝试。

重要状态应落到文件或其他持久存储中,并定期压缩成简短的交接摘要。摘要需要保留未验证项、已否定的方案和当前约束,而不只是成功进展。数值比较交给脚本,避免模型在长上下文中凭印象判断。

5. 把完成判断从执行者的自述中分离出来

Agent 可以提出“我完成了”,但放行应依赖外部证据。能够机械验证的条件交给脚本、测试或接收端查询;目标偏移、过度设计等难以机械判断的问题,再交给独立复核。

独立 Agent 并不是绝对可靠的裁判。它也可能共享相同盲点,所以结论需要附上证据;多个相同回答不能代替一次真实验证。没有验证结果时,应明确标为未验证,而不是根据回答的自信程度决定通过。

从单个 Loop 到并行任务

Loop 的潜在收益不只是单个任务更完整,也包括减少人被反复打断的次数。当操作、查询和状态更新都能自动完成,人可以从逐步陪跑转向检查关键决策与最终产物。

不过,无人值守并不自动意味着可以无限并行。多个任务可能争抢同一个测试账号、修改同一份文件,或者污染彼此的测试数据。扩大并发前,需要隔离工作目录、分配测试资源,并限制同时进行的外部操作。

因此我会同时观察任务质量、总成本和人的注意力:少了多少次人工介入?结果是否更容易审核?失败后能否从明确的位置恢复?如果只是让更多结果同时涌向一个人,瓶颈可能只是从执行转移到了审核。

工具之外,还需要环境和触发器

一个适合 Agent 的测试环境,应该有明确的启动入口、稳定的测试数据、可查询的运行状态,以及可重复的验证路径。权限、额外验证或环境切换应通过既有授权机制解决;不能把敏感凭据写进项目记忆来换取方便。

Loop 也可以由定时检查、告警或代码仓库事件触发。触发器决定“何时开始”,Loop 决定“如何推进”,权限和发布规则决定“能够做到哪里”。接入触发器之后,还要处理事件去重、重复运行与错误恢复;自动发现问题不等于自动获得合入或发布权限。

两个帮助我理解 Loop 的类比

第一个类比是研发工程师。如果只能看代码,不能启动应用、操作页面或查询结果,即使是人也很难判断实现是否正确。给 Agent 接入反馈,本质上是在补齐它观察实际运行结果的能力。

第二个类比是强化学习中的探索与利用:根据反馈尝试不同路径,同时复用已经有效的方法。这个类比只解释执行策略,不意味着每次 Loop 都在训练模型权重。普通 Agent Loop 往往只是更新上下文、文件和下一步动作。模型仍然有偏见,也可能反复选择相近方案;必要时要主动引入不同假设和独立验证。

Spec 与 Loop 也不是二选一。Spec 负责把目标与约束说清楚,Loop 用执行反馈检验实现。再往后,当部分控制流程稳定下来,可以用 Dynamic Workflow 将调度写成代码,让模型把注意力留给判断和探索。

延伸阅读