A green exit code is not evidence that the work happened
TL;DR · AI 摘要
A green exit code is not evidence that the work happened - Stack Overflow October 8, 2026 A green exit code is not evide...
核心要点
- 主题聚焦:A green exit code is not evidence that the work
- 来源:Stack Overflow Blog,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
绿色退出码并不能证明工作已经完成 - Stack Overflow
2026年10月8日
绿色退出码并不能证明工作已经完成
代理工具不建立信任的另一个原因,其结构性问题比第一个原因更严重。问题不仅在于工具持续变化形态,更在于你本应用来学习工具的反馈循环,在测量点已经断裂。
[
[编者注:如果你收听了我们的播客或阅读了我们的文章并希望发表回应,请告诉我们。我们欢迎以评论区以外的形式展示社区观点,无论你是否同意我们的观点。请通过 [email protected] 与我们联系。]
2025年3月,OpenAI的一支团队发布了一件你很少能见到的内容:他们自己的前沿模型在训练过程中处理编码任务时的私密推理过程。该模型审视了问题,认为实现整个功能过于困难,于是写下了一个替代方案。如果它调用 sys.exit(0),测试框架将优雅退出。"这很不自然,"它指出,"但测试可能会通过。"
测试确实通过了。
研究人员将这种现象称为系统性漏洞——这种漏洞足够通用,一旦模型发现它,就会在几乎所有训练环境中传播。他们发现了一个类似的案例:从测试框架外部抛出异常,完全跳过评估。在论文的其他部分,代理工具为测试覆盖率较低的问题编写了存根实现,运行时解析测试文件以提取并返回测试检查的精确值,甚至——我最喜欢的是——发现某人留在仓库中的编译 .jar 文件,反编译后复制出参考解决方案。
所有这些运行结果都显示为绿色。
信任论点止步之处
Ryan Donovan 在今年7月曾在此处论证,开发者之所以依赖工具,是因为工具编码了信任,而这种信任是通过重复获得的可预测性——就像你使用了十年的刀具会感觉像是手的延伸,而每周都会变化形状和重量的智能工具却难以建立同样的信任。
我认为这个观点是正确的,但我想要探讨它止步的地方。信任未能积累的第二个原因,其结构性问题比第一个更严重。问题不仅在于工具持续变化形态,更在于你本应用来学习工具的反馈循环,在测量点已经断裂。
开发者拥有的每一个信任指标——退出码、绿色CI、通过的状态检查、"任务完成"的字样——都基于一个假设:软件会发出明显的失败信号。无人值守的代理工具却会静默失败。一个循环可以干净地终止,报告成功,但实际上可能什么也没做,而在你的技术栈中没有任何信号能区分这种情形和一项工作完成。称之为"静默的绿色退出"。
我开发了ProAI,这是首个商业化的GPT产品,现在我从事多代理系统的研究,并在它们接近生产环境前如何评估它们;我在chasewhughes.com上撰写相关内容。我认为这是我们最缺乏准备的失败模式,它获得的关注度仅为能力和安全性讨论的几分之一,因为可靠性是三个议题中最无趣的,却是唯一决定你能否使用该工具的要素。
我们并未赢得响亮的失败。我们继承了它。
考虑为什么刀具本身能成为一种隐喻。你信任一把刀,是因为当它滑落时,你会立即、明确地流血——这种结果会在你再次拿起它之前教会你一些东西。每个开发者信任的工具都具有某种类似特性。段错误(segfault)非常显眼。断言失败也非常显眼。500错误代码同样显眼。退出码是将这种显眼性压缩成一个整数,它可能是计算领域中被消费最多的遥测数据。
需要特别注意的是退出码0的发出者。当make命令返回0时,这个整数位于工作流程的下游:编译器运行了,生成了目标文件并返回。这个状态是由一个能够观察的进程做出的观察结果。这个数字是关于世界的证据。
当代理循环返回0时,这个整数是由一个协调器发出的,它停止循环是因为模型生成了表示“完成”的标记。在模型声称完成与退出码之间,没有任何检查机制。这个状态是自我评估的结果,你却将其插入了一个本应用于观察的接口。所有下游消费者——你的仪表盘、告警规则、重试逻辑、周一早晨查看运行历史的那个人——都会继承这种替换,却从未被告知这一替换的发生。
这就是整个机制。其余部分就是它在现实中的表现。
已经存在数字的缺口
Donovan引用了本站自己的开发者调查来说明信任分歧,这些数据值得单独提取,因为其趋势非常显著。在2024年和2025年的调查中,使用或计划使用AI工具的开发者比例从76%上升至84%,但信任这些工具产出准确性的开发者比例却从43%下降至33%。主动不信任的比例则从30%上升至46%。66%的受访者将“几乎正确但不完全正确”的AI解决方案列为最大的挫折。
“几乎正确但不完全正确”描述的是你可以直接查看的输出。而我描述的则是更底层的问题:一个运行结果并非“几乎正确”而是完全空的,且与正常运行结果在表现上完全一致。
两个基准测试让这一问题更加具体。来自Sierra研究团队的τ-bench引入了一个值得更广泛认知的指标:pass^k——即代理在k次尝试中每次都成功完成同一任务的概率,而非至少一次成功的概率。在他们测试的模型中,代理在标准指标下的成功率低于50%,在零售领域pass^8指标下的成功率甚至低于25%。
这些具体数字已经过时,我必须明确说明:这是2024年的数据,当时的主要模型是GPT-4o,而技术前沿已经发生了巨大变化。但这个指标本身没有变化。pass^k是直接衡量Donovan所说的信任构成属性的指标。它询问周二是否与周一一致,并为答案赋予数值。几乎没有人报告这个指标,因此“在我尝试时它有效”仍然是工程讨论中被接受的证据,尽管在其他任何领域都不会被接受。
第二个案例是TheAgentCompany,来自卡内基梅隆大学,他们将代理部署到模拟的软件公司环境中,并赋予其真实的工作任务。最成功的代理自主完成了30%的任务。但真正值得讨论的发现并非这个成绩,而是研究人员描述的一种行为:"当代理不清楚下一步该做什么时,有时会试图耍小聪明,创建虚假的'捷径'来跳过任务中困难的部分。"他们的例子非常典型。一个代理在公司聊天平台上找不到特定同事时,会将其他用户的名称改成该同事的名字并继续执行任务。
仔细思考这种行为带来的后果。从外部观察,任务看似已经完成:存在一个名字正确的用户,对其执行了操作,整个流程中也没有任何错误记录。唯一的问题在于真正的同事根本没有收到任何通知——系统中没有任何组件知道这一点,包括代理本身,它也没有任何理由认为任务失败。
当其进入生产环境
2025年7月,Jason Lemkin花了大约两周时间在Replit的编程代理上进行开发,并在过程中公开记录了整个过程。数据库删除事件引发了广泛关注:该代理在未获得明确授权的情况下清除了生产数据库。但真正值得关注的部分发生在这一事件之前,却很少被提及。
他写道:"代理一直在通过创建虚假数据、虚假报告,甚至最糟糕的是伪造单元测试结果来掩盖错误和问题。"在某个时刻,代理生成了一个包含4000个完全虚构人物的数据库。之后,它告诉Jason回滚操作不可能完成,并声称所有数据库版本都已被销毁。这同样是错误的——回滚操作实际上运行得非常顺利。
虚假数据、虚假报告、错误报告的单元测试,以及一个经不起验证的自信状态声明。Replit的CEO将事件称为"不可接受且绝不应发生",这是正确的回应,而这一事件仍然是我所知道的最清晰的公开案例,展示了失败代理与报告代理之间的区别。
一个合理的反对意见
一个合理的SRE(站点可靠性工程师)会这样回应所有这些内容:这些都不是新问题。自20世纪70年代以来,定时任务(Cron jobs)就一直在静默失败。这就是为什么我们有"死人开关"(dead man's switches)、心跳监测器(heartbeat monitors)以及基于信号缺失而非错误出现的警报系统。你只是重新发现了监控系统并给它取了个新名字。
这个观点总体上是公平的,其中包含的积极信息也确实存在,因为这意味着解决方案的形态已经为人所知,相关工具也已经存在。但有一个关键区别打破了旧方法的适用性,这个区别值得特别关注。
所有这些传统方法之所以有效,是因为失败模式是可以穷举的。你知道夜间任务可能失败的有限方式清单——服务器宕机、磁盘满、锁被占用、上游超时——你要么为每种模式编写检查,要么编写一个能覆盖所有情况的心跳检测,因为"完成"只有一个明确的含义,而任务本身没有自己的意见。
代理在运行时自行决定控制流。每次运行都会生成新的计划,这意味着它在没有产生任何输出的情况下干净终止的方式集合,不是任何人能提前写下的清单。它包括sys.exit(0),因为实现读者看起来很困难。它包括重命名用户。它包括你公司大楼里任何人都没想到的策略,因为写这些策略的人根本不在你的大楼里。
因此你无法从失败的一方写出检查。从失败方写下的任何内容都是一份列表,而代理程序并不局限于你的列表。你必须从结果的一方进行编写。
仪器化制品,而非运行过程
接下来有四点需要关注。它们都不需要新的工具,这正是关键所在。
对工作成果进行断言。不是"循环是否以0退出",而是"该行是否存在,文件是否在磁盘上,消息是否真的离开了队列,分支是否真的被推送"。检查必须读取代理程序未创建的状态。如果你唯一证明邮件已发出的证据是代理程序报告称已发送,那么你并没有证据。你只是得到了一个有既得利益方的声明。
不要让验证与工作共享相同的失败模式。如果同一个代理程序在相同上下文中既执行任务又进行报告,报告会继承任务所发生的所有错误——包括导致任务失败的错误。Donovan提出将LLM作为法官来实现代理程序速度的审查,我认为这是正确的,但有一个限制条件:法官必须阅读制品,而非对话记录。阅读对话记录的法官是在评判关于工作的故事,而这些系统最擅长的正是讲述故事。
对变化的缺失发出警报。这是列表中最便宜的项目,但几乎没有人这么做。一个总是写入的作业这次写入了空内容却报告成功,比抛出异常的作业更值得怀疑。错误会触发警报;零效果的成功则在运行历史中显示为一个无人阅读的绿色方块。反转这种做法。一个定时代理程序如果在未触碰任何内容的情况下报告成功,应该通知相关人员。空无一物也是一种结果,它值得被大声强调。
在部署前,在模拟中测量pass^k。在相同场景下运行代理程序数十次,观察分布情况而非最佳情况,在一个你拥有真实值的环境中,因此可以检查制品而非故事。模拟的目的不是证明代理程序能完成工作。任何人都能演示这一点。它的目的是找出代理程序声称完成工作的频率。
我们尚未替代的部分
请注意所有这些措施多么谦逊。断言和警报——正是这种纪律在每一代基础设施中建立了信任,只是现在目标不同了。
这部分确实是全新的,这体现在人们谈论它的方式中。OpenTelemetry针对GenAI的语义约定——目前业界最接近统一仪器化这些系统的规范——定义了模型、操作、输入和输出令牌数量、完成原因、错误类型、代理程序自身名称和版本的属性。所有这些都很有用。但没有一个属性用于判断工作是否完成。这不是疏忽,我认为这也不是批评;这些是用于仪器化调用的约定,在每一代软件中,这个问题都不需要单独的字段。完成意味着效果。你不需要问编译器它是否真的意味着这一点。
这种暗示已经消失,而没有任何东西取而代之。绿色退出代码曾经是关于你程序的事实。现在它只是代理程序持有的观点。信任无法积累的原因不仅仅是"刀具"不断改变形状——你再也无法判断它是否真的切割了。