一个任务烧了54亿token,我盯着账单看了十分钟
前天晚上刷到 Codex 仓库里的一个 issue,标题平平无奇,点进去看完我沉默了。
一个开发者跑了个长任务,系统递归拉出了 74 个子 Agent ,嵌套三层,烧了 53.9 亿 tokens。
其中 53 个 Agent 干的是"审查"类的活:同一个 pytest 命令跑了 13 遍 ,同一个 memory 测试跑了 5 遍。有一个审查子树,单独就膨胀出 39 个 Agent,烧掉 32.6 亿。
最有意思的是结局。这位老哥实在扛不住了,手动跟根 Agent 说了一句:
"别再创建子 Agent 了,剩下的在当前会话里直接干。"
然后剩下的活,3 小时 15 分钟就干完了,只多花了不到一亿 token。
我盯着这句话看了半天。合着前面烧的那么多钱,大部分是在 Agent 之间互相商量"要不要再审一下"。
说实话,这事我有共鸣,因为我自己也翻过车。
大概一个月前,我让两个 Agent 协作改一个模块,一个写一个审。配置的时候觉得挺合理:写代码的负责实现,审查的负责找问题,互相制衡。
跑完打开 diff,两个 Agent 都写了 done,审查那个还回了句 LGTM。
我打开代码一看------
- 错误处理就是把异常
print出来
- 数据库连接连超时都没设
- 还有三处合并冲突:写代码的那个改了接口,审查的那个基于旧版本改的实现,两边都没发现
我当时的第一反应是模型不行。换了个更强的模型重跑,结果还是类似。
第二个反应是提示词不行。我熬夜把 prompt 改了三版,好了一点,但根本问题还在。
后来我才想明白:问题不在模型,也不在提示词。问题在于------
这两个 Agent 各自都在"正确地做事",但没人负责"把事做对"。
那个 Codex 的 issue,其实是同一个病的晚期版本。
病是怎么长出来的
根 Agent 接到任务,拆出一批子 Agent。某个子任务被判定需要审查,就创建一个审查 Agent。审查 Agent 觉得不放心,再拉一个二次确认。二次确认发现了问题,触发修复,修复完再审查,再修复......
每一层委托在当时看都是合理的,但合在一起,就变成了一棵停不下来的树。
而且这些 Agent 互相之间不共享状态。同一个 pytest 跑了 13 次,说明至少有 12 个 Agent 各自独立地觉得"我得跑一下测试确认一下",但没人知道别人已经跑过了。
每个 Agent 在自己的小世界里都是对的,全局看就是在烧钱。
这让我想起一句话,忘了在哪看到的:
多 Agent 系统最贵的不是模型,是 "Agent 觉得还需要再确认一下" 。
我的三条土办法
我后来的调整其实挺土的,没什么技术含量,就是三条规矩。
第一条:子 Agent 不许再拉子 Agent
所有委托必须经过根 Agent 显式批准。这条一加,那种递归审查树根本长不出来。
Codex 那位老哥最后手动喊停的,其实就是这一条------只不过他是事后补救,我是提前焊死。
第二条:审查循环超过两轮就熔断
一个交付物被退回两次,自动升级到我自己看。
多 Agent 最吓人的不是 Agent 犯错,是它们在"修复 → 审查 → 再修复"里空转:看起来忙得不行,实际上在原地打转。熔断就是强制把这个发散的过程按停。
第三条:把"协商"换成"门禁"
这一条是我后来用 Markus AI Agent 之后体会最深的。
它的设计里,Agent 干完活不能自己说 done 就完事,必须 submit,另一个 Agent 审查通过才能 merge。不通过就退回,没有"我们再讨论讨论"这个选项。
一开始我觉得这设计有点死板------Agent 之间难道不应该灵活沟通吗?
用了两周之后我改主意了。灵活沟通的结果,就是我前面那个 53.9 亿 token 的故事。
固定的判断节点虽然笨,但它收敛。通过或者不通过,二选一,不给无限循环留空间。
最后
写这些不是想说哪个工具好哪个不好。我自己也是踩了坑才慢慢摸到一点门道。
如果非要总结点什么,大概就是:
多 Agent 系统能不能跑起来,早就不是问题了。现在的问题是------它跑起来之后,你能不能看懂账单,能不能在它跑偏之前踩一脚刹车。
那个 Codex 的 issue 最后有个细节我印象很深:开发者手动喊停之后,剩下的活 3 小时就干完了。
也就是说,系统本身是有能力干完的,它只是不知道什么时候该停。
这件事,可能比"Agent 能调度多少个"重要得多。