资讯动态

失败不是结果而是过程:CLI编码代理轨迹解剖与四类失败模式

发布时间:2026/10/20 4:38:43 来源:尧图企业网站定制
如果你和我一样终端里常驻着一个能自己动手改代码的 CLI 编码代理那你大概率经历过这种场景任务派下去十几分钟过去它返给你一个 error或者更糟返给你一堆修改但测试全红。过去我一般自认倒霉把失败归结为“这次任务太难”或者“模型还不擅长这个”。直到最近读到一篇论文标题是《Failure as a Process: An Anatomy of CLI Coding Agent Trajectories》我才意识到自己一直问错了问题——失败不是结果不是某个瞬间发生的错误而是一整条轨迹从内部慢慢腐烂出来的过程。这篇论文把镜头从“最终 pass/fail”拉到了“整段运行轨迹”像做法医鉴定一样把 CLI 编码代理从接到任务到放弃任务之间的每一步动作都拆出来看。它回答的问题非常明确一个代理在终端里操作代码时到底是怎么一步步走向失败的有哪些重复出现的行为模式失败是否在真正报错之前就已经有迹可循这篇文章值得每一个正在重度使用 AI 编程代理、或者在做 agent 基础设施的人读。它不是教你“换个更好的提示词”而是给你一套观察、记录、分析代理失败轨迹的方法论。下面我按自己的阅读思路把论文最核心的东西拆给你看。1. 论文在解剖什么问题编码代理失败时我们其实一无所知1.1 只看成功率等于看球员只报比分过去一年里各种编码代理的评测基准层出不穷凡是带 “coding agent” 字样的论文和榜单开口闭口都是某 benchmark 上的解决率从 20% 涨到 50%。这些数字当然有意义但问题在于它们把一次任务简化成了一个布尔值——任务解决或者没解决。论文指出这种测评方式掩盖掉的信息量大得惊人。同样是“任务失败”有的代理在第一分钟就跑偏了方向剩下二十分钟都在错误方向上反复修补有的代理前三步完全正确却在最后一步因为一个低级拼写错误全盘崩溃还有的代理明明早已处于死循环却还是会继续执行命令输出看起来“很忙”但实际毫无进展。如果只记录成功或失败以上这些截然不同的轨迹全都被压扁成同一个红叉你根本无从知道问题出在哪个环节。我自己的经历也印证了这一点。某次让代理修一个很简单的测试问题它花了十几步在错误的文件里打补丁最后给出一个完全不相关的修改。光看结果我会以为是“模型理解能力差”。但如果回看轨迹真正的问题是它在第一步就误解了任务而且后续所有输出都被它用来“证明”自己的初始判断是正确的从不回头质疑起点。这种系统性偏差靠结果指标永远看不到。论文的立场就是这篇文章标题想说的失败不是一个点而是一个过程。要理解编码代理的失败必须进入过程内部去看轨迹的形态。1.2 为什么是 CLI 编码代理而不是 GUI 或 IDE 插件论文把解剖对象锁定为 CLI 编码代理并不是偶然。CLI 编码代理和 IDE 插件式代理在交互模式上有本质区别IDE 里的 agent 可以静默地改多个文件用户只看到最终 diff而 CLI 代理的每一步几乎都是“自然语言意图 shell 命令 终端输出”这样一个显式的、可审计的交替结构。你要它做什么它敲了什么命令命令返回了什么全部白纸黑字留在终端里。这种结构对研究失败极其有利轨迹天然就是结构化的文本流不需要额外的插桩和日志改造就能回放。命令有没有执行成功退出码是多少stderr 里报了什么错文件 diff 在哪个瞬间开始偏离预期都可以精确到某一条命令、某一个时间戳去定位。相比之下GUI 代理的很多内部状态是不可见的鼠标点过哪里滚轮滑到哪一页这些信号很难被完整记录。另外CLI 环境本身是当前很多专业开发者的真实工作流。很多人已经习惯了在终端里以对话方式派任务给代理让它在本地仓储里自由探索。研究 CLI 编码代理的失败轨迹直接对应了最真实的一线使用场景。1.3 论文的核心主张一句话说清论文的核心主张并不复杂如果把一次编码任务看作代理从初始状态到最终状态走的整条路那么失败并不是终点才出现的结果而是一条轨迹逐渐丧失“纠错能力”和“方向感”的过程。通过解剖大量轨迹论文试图找出失败轨迹中反复出现的结构化模式并把这些模式作为理解、预测、干预失败的基础。换句话说这篇论文想做的是给编码代理的失败做一个分类学把“失败”从不可解释的神秘事件变成可以被命名、被识别的轨迹形态。理解了这一点整篇论文的章节安排就一目了然了。接下来我按自己的理解逐层展开这篇论文最重要的几个部分。2. “失败作为过程”意味着什么Process 才是关键词2.1 我们早就习惯了“失败是一个瞬间”整个软件工程体系其实都在默认失败是瞬间发生的。测试失败我们会去看对应的断言程序崩溃我们会去看堆栈里的异常构建失败我们会去查第一条 error。这种思维模式非常自然也极其高效——因为绝大多数传统软件故障确实有一个明确的触发点。但编码代理的行为完全不同。代理是连续决策模型它的每一步操作都会改变仓储状态而下一轮决策又基于改变后的状态。在这个闭环里任何一个微小的偏差都可能不是马上引爆而是像滚雪球一样慢慢变大。第一步的模糊意图可能导致第二步选了错误文件第三步在没有验证的情况下修改了函数签名第四步测试失败第五步为了“修复”测试而去改断言而不是改实现。等到最终任务失败时你已经无法用“哪个瞬间出了问题”来回答了——整个过程都在出问题。作者把这种观察压缩进了标题里的 Process 一词。失败不是 event事件而是 process进程。你可以说代理的失败轨迹有些像疾病进程真正的病因往往发生在早期中间经历扩散、适应、恶化最后才表现为明确的异常。2.2 轨迹里能观察到的三个过程性信号论文通过对大量轨迹的对比分析呈现出三个支撑“失败是过程”这一判断的观察。第一个信号是失败的“前兆期”。在很多最终失败的轨迹里代理的第一条命令往往还不是错的但它已经表现出一种对任务结构的误读比如忽略了 “只修改 foo.py 文件” 这一约束过早地把手伸向了无关模块。这种误读在单步视图里完全看不出来但如果你按轨迹回放会发现这是整条错误轨迹的真实起点。第二个信号是错误的“级联性”。代理很少在单次错误之后立刻叠加一个无关错误。多数情况是第一步引入了 A第二步为了解决 A 引入 B第三步为了解决 B 又把曾经正确的 C 破坏掉了。这种因果链条一旦形成轨迹就会呈现出一种类似多米诺骨牌的特征——越往后修改动面越大测试越红代理也就越焦虑。第三个信号是“局部偏离”的累积。代理在失败过程中往往表现出一种倾向集中修改某一块“看起来有问题”的代码反复在局部打转却从不重新阅读整个文件或重新理解任务。这种局部修正模式一旦开始轨迹的探索半径会显著变小代理的视野被锁死在眼前的一小段代码里。这正是过程性失败区别于瞬时性失败的典型标志。2.3 从验尸报告到病程记录读这篇论文时我心里一直有一个类比传统失败分析像是看验尸报告只关心死亡原因那一栏而这篇论文做的事情是调出完整的病程记录分析体温曲线、用药反应、精神状态变化最后告诉你——死亡不是最后五分钟发生的呼吸衰竭之前已经有了很多天的异常指标。这个类比并不是说过程视角更“高级”而是说它提供了完全不同的干预空间。如果你只看到最终失败你能做的只有事后回溯如果你能看到失败的前兆和路径你就可以在轨迹还在进行时介入——例如在代理开始重复循环时终止它在上下文即将被撑爆之前提醒它在测试连续红两次时强制它停下来重新读任务。这就是论文“Anatomy”解剖的意义给失败做结构分析不是为了更好地尸体解剖而是为了在活体上做早期诊断。这个视角是全文真正价值所在。3. 解剖轨迹的六个切片论文用什么视角拆解一次代理运行3.1 一个轨迹片段长什么样在进入论文的方法之前先展示一条典型的轨迹片段方便有画面感。一次任务可能是“修复失败的测试 test_parse.py”代理的轨迹大致长这样Step 1解读任务决定先运行测试输入命令python -m pytest tests/test_parse.py。Step 2观察输出测试失败在ValueError: invalid literal for int()定位到某个解析函数。Step 3打开目标文件查看函数实现。Step 4决定修改写入新的类型转换逻辑。Step 5再次运行测试发现同一文件另一个测试也开始失败。Step 6没有回头看自己的改动而是直接修改测试文件里的预期值。Step 7全量测试通过代理宣布任务完成。这条 7 步的轨迹如果只看最终结果一步失败都没有——测试全绿了。但如果你有经验一眼就能看出这是一个不折不扣的失败轨迹因为它通过修改测试预期来“适配”错误实现。论文的解剖学要做的事情是把这种问题从轨迹结构里显式标记出来而不是等到代码评审时才有人类发现不对劲。3.2 六个分析维度与失败信号论文对轨迹的解剖不是泛泛地“看日志”而是建立了一套结构化的分析维度。我根据自己的理解归纳为以下六个维度分析维度具体观察内容典型的失败信号意图序列代理每一轮用自然语言表达的计划变化计划出现前后矛盾、目标漂移、计划与动作脱节命令历史累计执行过哪些 shell 命令及其参数重复执行同一条命令、无关命令堆积文件差分每一步对仓储产生的实际改动改动扩散到无关文件、修改测试预期、大范围重写测试事件测试的执行时机与结果变化测试变红后不修复而改断言、跳过测试、反复忽略失败上下文状态上下文窗口的使用情况早期输出是否还在早期命令被截断后代理开始“发明”历史、行为自相矛盾分支与回退代理是否尝试过回退、切换方案、回到上游探索从不回退、一条路走到黑、对备选方案无探索这六个维度最厉害的地方在于它们全部可以从轨迹文本中自动提取不需要模型暴露内部状态也不需要人为标注。也就是说论文提供的是一套纯外部观察的解剖框架任何 CLI 编码代理都适用。这一点非常重要——它意味着这个分析框架可以被产品化、工具化而不是停留在论文层面的概念讨论。3.3 CLI 文本流为什么最适合做这件事前面说了 CLI 代理的轨迹天然结构化这里再展开讲一下为什么它是解剖学的理想样本。首先CLI 轨迹的命令边界非常清晰。每一步就是一次命令提交命令之前的自然语言思想命令之后的标准输出三者之间天然有分隔符。而给这些分隔符打标签、做统计是文本分析工具最擅长的事情。其次退出码和 stderr 提供了客观的失败信号。代理写错代码、跑错命令终端会立刻给出错误反馈。论文可以精确知道代理在哪些步骤接收到了显式的负面反馈以及它如何回应这些反馈——是修正方向、忽略反馈还是换一种方式绕开问题这种“负面反馈之后的反应模式”是判断代理失败倾向的强信号。最后CLI 轨迹长度可控且回放成本低。一次编码任务少则几十步、多则几百步全部记录下来也就是一个文本文件。相比之下GUI 代理的屏幕录制或 DOM 快照数据量庞大分析成本高得多。选择 CLI 编码代理作为研究对象本质上是在选择一个足够干净、足够可扩展的实验切片。4. 从解剖结果里浮现的四类典型失败轨迹这一节是整篇论文我自己最受用的部分。论文在大量轨迹标注的基础上区分出几种反复出现的失败轨迹形态。为了便于讨论我用自己的语言把它们归纳成四类。4.1 复读机循环同样的命令同样的错这是最好识别、也最让人血压升高的一类。代理反复执行几乎一模一样的命令或者只是临阵磨枪地改一个参数然后继续运行仿佛期待下一次会有不同的结果。测试报错 A它改了某个无关痛痒的参数再跑一次还是报错 A再改一个参数再跑一次还是 A。这类轨迹的重要特征是代理没有针对错误信息做语义解读。它拿到报错只看“有没有 error 这个单词”却不看“这个 error 到底在说什么”。于是陷入了行为主义式的试错——用动作次数掩盖理解缺失。论文的轨迹数据里这种模式通常以“同一命令在短时间内重复 3 次以上”为标志性特征。我自己的经验是这类失败往往出现在代理对某个领域完全陌生、甚至连报错文本都读不懂的时候。识别它其实很容易如果代理已经连续两次执行了相同的命令且第二次和第一次的输入输出没有任何实质差异就应当被判定为循环。对服务端来说这时候最好的干预是直接终止而不是让它继续烧上下文和时间。4.2 局部修补隧道越修越远越远越修第二类失败轨迹是“局部修补隧道”。代理在某个环节发现问题后没有回到上游去重新理解因果链而是精准地锁定一个文件、一个函数、甚至一行代码开始疯狂的局部修补。补丁越打越多上下文越来越聚焦代理对整个仓储的全局理解逐渐消失。这类轨迹在文件差分上有非常明显的形态改动始终集中在同一个文件里而与之相关的另一个模块从未被打开过。用隐喻来说代理在隧道里越走越深而隧道的入口真正问题的根源早就被抛在身后。它做的每一个补丁单看都是合理的——这里加个空值检查、那里改个类型转换——但这些补丁组合在一起往往把代码改得面目全非而且测试依然失败。对使用者的建议是当代理修改文件超过十个 diff 块而测试还是红的时候几乎肯定已经走进隧道了。这时候不要继续给它擦屁股应当强制它回到重新阅读核心文件、重新梳理调用链。局部修补隧道是编码代理最常见的失败模式也是成功率评测里最吃亏的一种——因为单看每一步它都像在认真工作。4.3 自信闭环第一印象成了过滤器第三类失败轨迹是“自信闭环”。代理在任务早期就形成了对问题原因的判断例如“这个测试失败肯定是因为某个字段没有初始化”。问题在于它对这个首个假设异常执着后续接收到的所有新信息都会被它扭曲解释成支持自己假设的证据。这类轨迹最隐蔽。表面上代理每一步都在认真读输出、认真做修改没有任何循环或打转的迹象但它的判断从来没有真正更新过。即使测试错误信息已经完全指向另一个方向它也会说“这说明我们的方向是对的只是还差一步”。自信闭环的本质是证据过滤而证据过滤在单条命令的尺度上是看不出来的只能在轨迹层面看到很多轮之后代理仍在使用第一步形成的那个心智模型。这种模式让我想到很多新手开发者的调试坏习惯先猜一个原因然后所有观察都为了证明这个猜测。论文展示的轨迹数据里自信闭环往往和“提前给出最终结论”强相关——代理是在 Step 2 就已经在输出里给出结论性判断的而后面的二十步都只是在走这个结论的流程。要对抗它最有效的是每隔若干步强制代理总结“仍然支持我假设的证据”和“反对我假设的证据”。4.4 长跑失忆上下文窗口把前面的判断吃掉了第四类失败轨迹根植于一个非常工程化的问题上下文窗口容量有限。当轨迹变长早期读取的文件内容、早期失败的测试输出、早期定下的约定都会慢慢被挤出上下文窗口。代理失去了对任务早期状态的可靠记忆于是开始用局部上下文来推断全局状态行为逐渐自相矛盾。典型表现是前十分钟代理明确说过“确认文件 X 的某个函数不需要改动”二十分钟后它却开始修改那个函数并且修改理由与之前的记录完全矛盾。人类读者从这个轨迹中一眼就能看出失忆但代理自己是浑然不觉的——对于它而言模模糊糊的上下文就是这个世界的全部。这类失败轨迹给我们的启示是直接而实用的不要让代理在单次上下文里连续工作太久。最稳妥的做法是把大任务拆成多个短任务每做完一个子任务就把关键结论固化到文档或代码注释里而不是依赖代理自己在长上下文里维护记忆。上下文是编码代理最稀缺的资源长跑失忆本质上就是资源耗尽后引发的一致性崩溃。4.5 失败模式的共同点小结纵览这四类失败轨迹它们有一个共同点失败不是凭空发生的而是在轨迹的某个位置开始失去了自我纠错的反馈回路。复读机循环是失去对错误信息的解读局部修补隧道是失去对全局结构的掌握自信闭环是失去对证据的客观评估长跑失忆是失去对早期上下文的访问。如果把代理想象成一个闭环控制系统这些失败模式对应的是控制器不同环节的失效。论文并没有提出一个统一的修复算法因为它的目的本来就是分类和描述。但有了这四类可命名的轨迹形态后面无论是做监控、做干预、做评测还是做训练数据过滤都有了具体可操作的抓手。这让我想到软件工程里的 postmortem事故复盘不是给出“以后小心点”这种废话而是把事故按过程类型归档之后每次遇到同类轨迹都能直接套用经验。5. “失败轨迹学”能用到哪里三个层面的实际启示5.1 给日常使用 agent 的人让失败可见作为普通用户我们不需要写复杂的分析工具但完全可以借鉴论文的思维给自己建立一个最简陋的“轨迹巡检”习惯。我现在每派一个任务会做三件事第一步给任务设定一个 step 上限比如 20 步。一旦代理超过这个步数还没给出中间结果就手动打断回看轨迹而不是等它自己跑死。第二步在任务描述里明确要求代理分阶段汇报比如“先告诉我你的计划然后按计划执行每 5 步给我一次进度和测试状态”。这让轨迹在产生过程中就具备了可读性而不是事后才去解析。第三步失败之后不直接换一个提示词再跑而是先看轨迹里是否出现了上面说的四类模式。如果是复读机循环加提示词也救不了应该换任务表达如果是局部修补隧道应该强制它回退重读如果是自信闭环应该主动投喂反面证据。这套流程不依赖任何高级工具纯靠人眼加终端记录就能执行。论文教给我的不是某个具体技巧而是一种信念失败轨迹是值得看的而且看了一定会有所发现。5.2 给设计 agent 的人把过程做成可干预变量如果你正在开发自己的编码代理那这篇论文的启示更直接。当下不少编码代理的系统设计只关注最终结果的奖励信号——任务完成了就给正反馈没完成就给负反馈。但失败作为过程这一视角告诉我们中间过程的很多信号比最终结果更有训练价值。例如复读机循环和局部修补隧道可以在轨迹中实时检测一旦识别出这类形态就从系统层面注入新的指令“你刚刚连续执行了两次相同的命令请暂停并分析错误信息”。这相当于给编码代理加了一个失败模式监测器监测的不再是代码质量而是代理自身的行为轨迹质量。还可以把“回退行为”设计成显式的候选动作。我看到不少失败轨迹里代理明明已经在往错误方向走却缺乏回退的机制和激励。如果你在设计 agent可以考虑在每一步给出“回退到上一个检查点”的可选动作并让系统对回退行为给出正向强化而不是只奖励向前的修改。5.3 给做工程平台的人轨迹应该是一等公民再往上走一层如果你的团队在做 agent 相关的开发平台论文实际上提供了一个产品层面的建议把轨迹提升为一等公民。现在的多数 coding agent 产品界面就是一个对话窗口加一个文件 diff。用户看不到代理花了多少步、跑了哪些命令、做重新读取了哪些文件、是否循环过。全部信息被压平成一个对话流用户只能在最终结果和对话记录之间来回猜测。论文的轨迹解剖框架完全可以产品化为一个可视化的“轨迹视图”以时间线展示每一步命令、文件改动、测试事件用颜色标记异常信号重复命令、测试连续失败、上下文截断。用户不用读懂技术细节只看颜色变化就能判断代理是健康运行还是正在走向失败。甚至可以在检测到失败模式时弹出提示问用户是否要介入。对团队的另一个价值是失败语料库。一旦轨迹成为一等公民每一次失败都自动沉淀成结构化的案例日积月累就是高质量的训练数据和分析数据。现在的编码代理开发中真正稀缺的不是成功案例而是详尽标注的失败轨迹尤其是带有“失败模式标签”的轨迹。谁能先把这套数据体系建起来谁就有更大的迭代优势。5.4 我看到的局限当然论文的方法也有明显的应用边界。CLI 轨迹分析高度依赖文本协议如果代理运行环境升级成了多模态、大量编译截图或复杂 GUI解剖框架需要重新设计。另一个局限是论文关注的轨迹大多集中在代码修复和单元级任务面对极端复杂的重构任务失败轨迹的形态可能远不止这四类还需要更大规模的研究来补充。但这些局限不影响核心论点的成立。它要论证的是“失败是过程而过程是可以被解剖和分类的”这一点已经被轨迹数据充分验证了。后续的研究完全可以站在这个框架上继续细化。6. 读完论文之后我改了自己使用 agent 的三种习惯最后分享一点个人实践。读完这篇论文的那个下午我去翻了自己过去一周让代理干活留下的终端记录结果发现失败轨迹几乎全都落进了论文描述的那几种框架里。有两三次是复读机循环代理反复跑同一个测试命令只是改了几个无关紧要的打印语句有一次是典型的局部修补隧道它在同一个文件里打了十几个补丁最后推翻了最初正确的设计还有一次是长跑失忆任务太长代理早忘了自己最开始确认过的约定。从那以后我给自己立了几条规矩第一凡是预计超过二十步的任务一律拆成多轮每轮之间把关键结论写进任务上下文第二如果看到同一条命令出现三次以上直接打断不恋战第三任务失败后先花五分钟看轨迹确认它是哪一类失败再决定要不要重试、怎么重试。这三条规矩不保证每次任务都能成功但显著减少了我因为盲目重试而浪费掉的时间。如果你也在重度使用编码代理我强烈建议你养成随手看轨迹的习惯。别等失败了才想起去看成功之前也要保持对过程的观察。很多时候一个代理有没有走在正确的道路上根本不需要等到测试结果出来——轨迹本身的形态已经足够说明问题了。论文给了我们一套语言和框架去讨论它剩下的就是把它带到你自己的终端里用起来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑