让智能体盯 PR 状态:一夜跑了 243 次、纯浪费 $63.10、0 提交(失败结果)
速览卡
- 分类:编程搭建 / 失败账本
- 结果:243 次运行、约 31M 输入 tokens、$63.10 纯浪费、0 提交(已实现,失败结果)
- 状态:作者本人复盘,数字与代码均在原文公开;非第三方审计
- 成本:见上;单次运行成本当晚从约 $0.12 涨到约 $0.45
- 耗时:事故持续约 8 小时(每 2 分钟触发一次)
一句话
把“每 2 分钟看一眼 PR 状态”的便宜轮询,接到了一个每次都要花钱买 tokens 的智能体上——而判断条件写的是“历史上有人提过修改意见”,于是它对同一条早已处理的意见重复派工了一整夜。
原作者怎么做的
- 作者在自己的看板系统 Camelot 里加了一个轮询器:PR 进入待处理阶段后,每 2 分钟查一次 GitHub,合并了就标完成、CI 挂了或评审要求修改就把智能体再派进去修。
- 触发器本身只有三行(Ash/Oban 定时 + 状态条件),由 Claude Code 写、作者本人审过并合并——“看起来就是我平时写的代码”,所以审得特别快。
- 埋点:GitHub 的评审记录是不可变历史,不是可清除的标志。只要历史上出现过一次“要求修改”,条件永远为真;轮询每 2 分钟派一次工,智能体每次带约 13 万 tokens 上下文进去、发现无事可做、干净退出,如此 243 次。
- 三道本该拦住它的保险全部失效:新鲜度检查只在另一条分支上、这条路径走不到;防重复计数器在派工时被传参 0 每次重置;分支顺序把“已批准”排在“要求修改”之后,批准了也轮不到。
- 循环最后不是被保险拦下的,而是运行器自己崩了才停。作者第二天手写修复:先按评审人取“最新一条有结论的评审”,再要求该评审比最新提交更新、且此前没处理过,才允许派工。
结果
- 243 次运行、约 31M 输入 tokens、总花费 $64.25,其中 $63.10 为纯浪费,产出 0 个提交(已实现,失败结果,作者实测)。
- 单次成本随当晚对话变长而加速:从约 $0.12 涨到约 $0.45——循环不只浪费,还越跑越贵。
- 修复后按作者测算:那条评审在循环启动前就已过期(评审时间 11:46:46Z,最新提交 11:52:34Z),一次时间戳比较就能在第一轮拦下。
提示词结构
(据原文复盘反推的审查清单,非原文照录)
「审这个改动时,只回答三个问题,答不出就不要合并:1)它靠什么触发?触发条件是‘事件发生了且我还没处理’,还是‘某个历史状态曾经为真’?2)它靠什么停?停止条件必须落在持久化记录上(时间戳/计数器存数据库),且受保护的分支内部不许重置自己的计数器。3)跑一轮多少钱?写出单轮 token 量级与最坏情况一夜的总价。另外:链式调用里只要有一步是‘可选增强’,必须单独包成永远返回成功的函数,不许让它拖垮整条链。」
中国读者怎么迁移
不写 Elixir 也一样中招:任何“定时任务 + 智能体”的组合(GitHub Actions 定时跑编码智能体、n8n/定时脚本轮询工单再调大模型)都要先过上面三问。国内团队常见的微信/飞书机器人轮询群消息再调模型,同理要把“处理过哪条”落库,而不是靠模型自己记得。
风险与限制
- 金额小($63.10)是因为当晚运行器先崩了;若按 API 计费且无人值守,上限只取决于发现得有多晚。
- 本案技术栈为 Elixir/Ash,代码不能直接抄到其他栈,但三个失效模式(不可变历史当标志、死代码路径上的保险、分支内重置计数器)是跨栈通用的。
- 作者是系统所有者本人,数字为自报账单口径,无第三方审计;结论的可信度主要来自其公开的完整代码与时间戳细节。