最近,我在开发一个课堂互动工具时,遇到了几段持续很久的编程 Agent 任务。有些最终完成了,有些在经历大量修改、审核和验证后,仍没有满足完整交付要求。
其中一次正式交付任务的累计 Goal 计时超过 40 小时。主实施阶段使用 Astra,目前最好的AI之一,作为全局负责人。但到我停止推进时,要求中的完整容量验证仍未完成。
这不禁让我深思:一个已经设定好了所有执行规则和边界的 Agent Team,为什么会囿于设定好的规则,陷入局部优化陷阱,从而导致迟迟无法交付?我们能否在保持质量要求的前提下,让一个Agent Team更可靠、更有效率?
我决定基于上个月我花了10B Token进行的项目获得的Bitter Lesson,在此开启一个项目,研究为什么Agent在执行的时候会陷入局部最优陷阱,为什么一个Agent Team在设定好了规则和边界之后仍然无法高效协作。第一步我将先写出这篇blog,为这个项目立项,完成:发现问题,提出问题这两步,后续的日子里面,我会进一步把我分析问题,尝试解决问题的努力,同步到我的github或者blog上面,欢迎各位读者斧正我的错误,以及和我交流,期待听到各位的新鲜见解。
根因猜测与分析:Agent 到底卡死在了哪里?
为了搞清楚这几十个小时到底在跑什么,我先把这五段长任务拖出来在Codex的辅助下,做了一轮复盘。按 Codex 任务系统记录的累计时间算,这五个任务分别跑了 42.4、40.1、24.0、21.2 和 19.6 个小时。
这里要先标清楚:Goal 计时是系统层面的累计等待时间,不能直接等同于模型的净推理时间。而且这五个案例本来就是我挑出来的异常值,并不能代表所有 Agent 日常的执行任务时间(虽然也没有几个任务的执行时间短于12h就是了…)。
但顺着上下文里的决策链、提交历史和系统输出翻下去,我发现事情没那么简单。这几十个小时的无休止消耗,背后其实是这三个无尽的深坑:
- 拆任务时,把原本完整的业务语义给砍断了 最典型的就是处理 Start 请求恢复的时候。服务端的会话其实已经创建入库了,但前端网络响应丢失;等前端发现超时,防抖和重试限制又卡死了用户,直接导致创建好的会话拿不回来。
如果只看局部,最直觉的改法就是“允许拿着旧请求 ID 重试”。但在后端,这往往包含两个隐蔽的分支:查到持久化记录,就直接返回历史状态;如果没查到,就得按新逻辑走一次初始化。一旦房间状态在这期间发生了变更,一个旧请求就可能在一个完全错误的状态机阶段里被首次触发。
如果 Agent Team 还是按传统的“前端改交互、接口加字段、数据库加校验”各自领任务,整个业务语义链就会被直接撕裂。一个合格的Agent Team Leader必须先摸清全局的状态演进,再画定修改边界;否则Team里面的Agent还是只是各自修各的,表面上单点测试全绿,连起来业务逻辑全是洞。
- 动了一行验收脚本,连带把几十小时的验证全作废了 另一次在容量验收时遇到的问题更让人血压升高。当时仅仅是验收脚本对合法大厅状态的判断逻辑有 Bug,我们修的东西压根没动任何业务代码。
但构建流程里,把整个工作区都打进了同一个运行镜像,镜像哈希又死死绑定着提交版本。验收器一改,镜像变了,工件也全变了。这就陷入了一个经典的死循环:即使业务逻辑一行没改,你也没法拿旧的测试结果去证明新镜像。
在那次正式交付里,Agent 跑了 14 次完整的压力验收、11 次 smoke 测试,包含各种半途挂掉的运行。这里面确实有抓到真实 Bug 的时候,不能全说是无用功;但更折磨人的是:我们每一次重新跑全套验证,到底是真有必要,还是在凭感觉盲跑? 到底哪些证据在改动后依然有效,哪些必须推倒重来?如果这点算不明白,整个项目的推进节奏就会一直陷入在对小细节改动几十秒,但是跑完一次完整的测试要大几十分钟的泥潭里面。
- 系统在持续运行,不代表它正在推进交付 还有一个让人哭笑不得的案例:整个任务在长达 9 小时 26 分钟的时间里,没有任何实质性的进展输出。已有的单测早就跑完了,后台日志还在疯狂滚动,但在外界看来,你根本不知道执行链究竟卡死在了哪个未知分支。
反过来,另一场容量测试留下了详尽的吞吐数据和阶段快照,看起来一片大好,最后却因为宿主机休眠被直接掐断。(晚上睡觉的时候电源线松动了…)
这给我上了很生动的一课:控制台有日志输出,根本不等于任务在接近交付;反过来,暂时没有新动作,也绝不能成为我们盲目杀掉重跑的借口。恢复机制不能只靠对agent下一句one shot的指令,必须把当前的执行阶段、进程状态、阶段产物和最终验收标准绑定在一起让agent综合进行分析。
怎么证明这个研究不是纸上谈兵?
说实话,第一轮梳理只能算把事故现场给扒明白了,做了一些只读的诊断,但我脑子里那套解决方案还没落地,更谈不上能帮系统提速。
而且中间我发现一个很有意思的分歧点:在处理复杂的状态恢复逻辑时,强行要求 Agent “先列清楚所有持久化分支再写代码”,确实帮它抓住了几个致命遗漏;但如果是简单的格式化或改改文案,强推这套流程纯粹是在浪费时间。所以,能够解决我遇到的问题的方案,必须要实事求是,让Agent执行的时候具体问题具体分析,不能搞形式主义。
接下来,我打算按这三个节点一步步来推进:
-
做最小复现案例。 先不做big picture的后续展望,抽几个自己过去做过的玩具项目,把观测代码、验收器、资源参数和业务逻辑这几类变化切开,还要专门设计几个“一旦改动必须全量重测”的反例进去,作为基准。搭建后续研究的banchmark。
-
构思一套能跑的原型工具或者轻量化的skill。 设计一套记录验证证据的规范,做个 CLI 工具之类的。每次改了代码,通过工具来判定:哪些旧证据可以继续继承,哪些缺了必要条件,哪些由于底层变动必须重跑。
-
拉出来做真实对照。 同样的交付目标,一边让基线 Agent 自由发挥,一边挂上这套证据裁决工具。先在我的课堂工具项目上测,再换一个完全不相关的项目看这套逻辑能不能复用。
至于我的首要标准,第一交付质量,其次才是执行速度:如果为了省测试把 Bug 漏过去,或者误以为搞定提前交卷,那这套工具就是零分。只有在守住严苛交付底线的前提下,再去算我们省下了多少重复验证的命令时间和无谓等待。
哪怕最后测出来,这套维护依赖关系的额外开销远超它省下的算力,或者它其实只能处理极其狭窄的边缘场景,我也能学到东西——证伪一个伪需求,同样也可以是这个项目的产物。
接下来我想开源什么
我不想只写几篇感想就完事。顺着这个计划,我希望能把踩过的坑变成真正可用的东西:包括五次事故的复现材料、验证证据的标准结构、那个判断证据适用性的小工具,以及最真实的对照数据。
第一阶段的目标很简单也很克制:哪怕只针对一类最常见的改动场景,能精准说清楚哪些测试不用重跑,同时保证交付质量不打折,而且在别的项目上能跑得通,这一步就算走成了。
现在这个项目刚把问题定义清楚,方案设计才起步,代码一行都还没推。后续我会把最小案例集和 v0.1 的架构设计先放出来。
如果你在平时指挥 Agent 干活的时候,也见过它们对着同一个单测反复打补丁、为了微小的改动把耗时半天的测试从头重跑,或者日志刷得飞起但任务就是推不动——非常欢迎和我交流具体的翻车现场。不管是后来被证明管用的办法,还是折腾到最后彻底摆烂的失败记录,对大家一起研究Agent Team的编排来说都是极具价值的一手素材。
