Agent 失败了先别急着重跑,三类失败的判据完全不一样

2026-07-29

数据截至 2026-07,各产品的额度与报错口径以官方最新说明为准。

多数人把 Agent 失败归成了同一件事——「它又抽风了」,然后统一处置:重跑。真正的问题是,这三类失败共用一个动作,其中两类会被这个动作越搞越糟。 可重试的失败重跑是对的;该换路的失败重跑只是在烧钱和烧时间;必须交人的失败重跑还可能把一次小事故放大成需要回滚数据的大事故。分类这一步花不了两分钟,省下的往往是半天。

这篇文章和站内另外两篇有明确分工:Agent 执行失败后怎么恢复 讲的是确认可重试之后怎么恢复——退避怎么设、半路失败该回滚还是补偿;重试之后发现同一件事做了两遍 讲的是重试的前置条件,也就是幂等键怎么设计。本篇只管它们之前的那一步:现场看到一个失败,怎么在几分钟内判断它属于哪一类。判错了类,后面两篇讲得再细也用不上。

一、一个问题就能分出三类

分类不看现象,看的是同一个问题:在完全不改变任何输入和环境的前提下再跑一次,结果有没有可能不同?

  • 有可能不同 → 可重试类。失败来自瞬时状态:网络抖动、对端排队、服务端临时不可用、并发争抢。时间本身就是变量,所以什么都不改也可能成功。
  • 不可能不同 → 该换路类。失败来自确定性的不匹配:给的上下文里根本没有那个文件、工具签名对不上、模型不具备完成这一步的能力、路径压根走不通。再跑一次输入相同、环境相同,输出就算措辞变了,卡住的地方还是同一个。
  • 不该由机器决定 → 必须交人类。这类不看技术上能不能重试,看的是后果。动作涉及不可逆的写入、涉及钱、涉及权限提升、涉及删除,或者失败点本身暴露了任务定义有歧义——这时候机器无论重试还是换路都是在替人做决定。

第三类的边界最容易被忽略。它和前两类不是并列的技术分类,而是一道优先级更高的闸门:先判有没有越过交人的红线,再判可不可以重试。 顺序反了,你会碰到一个技术上完全可重试的失败,重试成功了,但重复扣了一次款。关于这道闸门怎么在流程里落成机制,可以看 Agent 的人工确认环节该卡在哪

还有一类值得单独点名:失败但报告成功。Agent 说任务完成了,实际上文件没写、测试没跑、改动没落盘。它不出现在你的失败列表里,所以永远不会被分类。这类的识别方式只有一个——不信自述,验产物,详见 Agent 谎报成功怎么办

二、现象到成因的判别表

下面这张表按现场能直接看到的现象组织。用法是从左往右:先对上现象,再看怎么验证成因,验证过了再做动作。跳过验证列直接照抄动作列,是这类排查最常见的错误。

现象大概率成因怎么验证处置动作
报 429,间隔一段时间后正常限流触发,属于瞬时状态隔一段时间用同样输入单独发一次请求,看是否通过可重试:指数退避加抖动,并降低并发
报 429,稳定复现且退避多久都一样不是速率限流,是额度或配额层面的拒绝换一个独立的凭据或独立账号发同样请求,若立刻通过则是账号级问题换路:切备用凭据或备用模型,别继续重试
报 401 或 403凭据无效、过期,或权限范围不够用最小的一条只读请求验证凭据本身;再确认凭据的权限范围是否覆盖这个动作换路:换凭据或补权限,重试无意义
报 500 或 502,偶发对端服务端临时故障同样请求隔几分钟重发,看是否稳定复现可重试:退避重试,同时记录发生频率
报 500,稳定复现请求体本身触发了对端的异常分支把请求体逐段裁剪,定位到哪一段引发换路:修请求构造,或换一条调用路径
ETIMEDOUT、ECONNRESET网络链路或中间代理不稳定在同一台机器上对同一域名做多次连通性测试,看丢包与耗时分布可重试:退避重试;连续多次失败则转排查网络
证书链校验失败处在做 TLS 拦截的网络环境,或对端证书配置有问题在另一条网络(如手机热点)上重试同一请求换路:补信任链配置;不要用关闭校验来绕过
Agent 反复读不到某个文件工作目录不对,或文件被忽略规则排除先打印它实际使用的工作目录并用绝对路径确认文件在;文件确实在就查忽略配置有没有把它排掉换路:修正路径或显式提供内容,重跑不会变
同一个错误改了三轮还在原地上下文里缺关键信息,模型在猜把三轮改动并排看:改法在变但报错一字未变,说明它没拿到能推翻当前假设的信息换路:补上真实报错全文与相关代码,或换人接手
工具调用参数总是对不上工具描述与实际签名不一致拿它生成的参数对照工具定义逐字段核换路:修工具定义,重试只会重复同样的错
输出被截断在中间单次生成长度触顶,或流式传输中断看结束原因是正常结束还是长度触顶换路:拆任务分段产出,不要靠重试碰运气
涉及付款、删除、外发的动作失败后果不可逆,不看技术成因无需验证交人:就地停住,保留现场,人工确认后再动

表里有个规律值得单独说:同一个状态码可以落进不同的类。 429 既可能是可重试的速率限流,也可能是该换路的额度耗尽;500 既可能是对端抖了一下,也可能是你的请求构造有问题。所以状态码只是入口,判别列才是分类依据。各家平台对这些情况的返回口径不同而且会调整,具体以官方最新说明为准。

三、判定可重试之后,先过三道前置

确认属于可重试类,别急着加 for 循环。重试之前有三道前置,缺一道就会把一次失败变成一堆脏数据。

第一道:这次调用是不是写操作。 读操作重试没有副作用,写操作重试的默认后果就是重复执行。判断方法很直接——这个动作会不会改变对端的状态。会改就必须先有幂等键。

第二道:失败判定是不是可靠。 超时不等于对端没执行。你的请求超时了,对端可能已经写完只是响应没回来。把超时当成「没发生」来重试,是重复执行的主要来源。稳妥的做法是超时后先查询状态,确认没执行再重试。

第三道:重试会不会加剧问题。 对端已经在排队,你的重试是在往队列里加压。所以退避必须带随机抖动,且要设总次数上限,别让所有并发在同一时刻齐刷刷重来。

这三道过完,再去看那两篇讲得更细的文章就顺理成章了。幂等键的粒度、状态查询接口的设计、退避参数的取值,都在它们的射程之内,这里不重复。

四、该换路类:换什么、按什么顺序换

先划清适用范围:下面这个阶梯针对的是「任务卡住」型的换路——它试了但做不成。如果换路的成因是凭据、额度、权限这类账号层面的拒绝(表里 401、403、稳定复现的 429 那几行),别走这个阶梯,直接切备用凭据或补权限就行,补再多上下文也不会让额度回来。

针对任务卡住,换路不是一个动作,是四个层次,从代价小的开始试:

换输入。 最常见也最有效。Agent 卡住的大部分原因是它手里的信息不足以完成判断。把真实的报错全文、相关文件的实际内容、约束条件明确补给它。注意是补「事实」不是补「催促」——再说一遍「请仔细检查」不会改变它掌握的信息量。

换切法。 一个任务连续失败,往往是粒度太大。把它拆成能独立验证的小步,每一步跑完就检查产物。拆完之后你会发现失败点其实集中在某一小步上,那一步单独处理比整体重跑便宜得多。

换执行者。 换模型或换工具。这一层要有事先设计,临时切往往切不干净。路由与降级怎么搭,见 多模型 fallback 怎么设计。这里补一句现实约束:若你考虑的候选里有海外工具或模型,需要清楚不少产品官方对中国大陆有区域限制、不支持直接访问,可用性与合规边界以官方最新说明为准。本文不讨论任何绕开区域限制的做法。就工程角度说一句:把一条你无法确认合规状态、也无法从官方拿到可用性承诺的通道放进自动降级链路,等于给系统埋了一个你控制不了的故障点——它挂掉的时候,你连找谁问都不知道。稳妥的做法是降级链路里只放能拿到正式服务条款和可用性口径的通道。

换方案。 承认这一步不该由 Agent 做。有些任务对上下文的依赖是隐性的——依赖只存在于某个人脑子里的历史决策,依赖线上环境的实际状态,依赖跨系统的口头约定。这类任务喂多少上下文都补不齐,人写十分钟比调三小时划算。

换路的顺序不能颠倒。直接跳到换模型,你会发现换了还是同样卡住——因为问题在输入不在执行者,只是又花了一份钱重新证明了一次。

五、什么情况下别再折腾

止损点要在开工之前定,不能在纠缠到第三小时的时候临时定。人在沉没成本里定不出合理的止损点。下面这几条我用来当硬线:

同一个错误连续三轮没有变化,停。 注意判据是「错误没变化」,不是「改了三次」。改法在变但报错一字不差,说明它在错误的假设里循环,再来第四轮只是换个说法重复同一个错。这时候要退出来重新看假设,而不是继续催。

改动范围开始扩散,停并回滚。 原本要修一个函数,现在它动了七个文件、加了两个依赖、顺手改了配置。这不是修好了,这是在用扩大搜索范围掩盖没找到根因。这时候要先把工作区退回到最后一次提交的状态,顺序是先看清楚、再整体封存:

git diff --stat HEAD                  # 先看清楚到底动了多少文件、多少行
git status --short                    # 看有没有它新建的未跟踪文件
git stash push -u -m "agent-run-1"    # 连未跟踪文件一起封存,工作区随之回到 HEAD
git stash list                        # 确认这一笔已经进栈,编号是 stash@{0}

三个细节容易翻车。一是顺序不能倒过来:git stash 本身就会把工作区恢复到 HEAD,先 stash 再 git diff --stat HEAD,你只会看到一片空白,什么都没记录下来。二是默认的 git stash 只封存已跟踪文件,Agent 新建的文件多半还是未跟踪状态,不加 -u 就会被留在原地,等你下次排查时误以为是自己写的。三是 git checkout -- . 这类直接丢弃工作区改动的命令,除非你已经 stash 过,否则不要用——它没有回收站。

保留现场比清理现场重要。封存之后随时可以 git stash apply stash@{0} 捞回来看它到底想干什么(applypop 稳,栈里那笔还在,看错了也不用重来)。还要注意 HEAD 未必就是「最后一次能通过测试的提交」,如果 HEAD 本身已经是坏的,回退到 HEAD 只是回到另一个失败态,得另外找那个绿色的提交点。

触到不可逆动作,立刻停。 涉及生产数据删除、资金流转、对外发送、权限变更的动作,一旦失败在这里,不管技术上多像瞬时错误,都停下来交人。这条没有例外,因为判错的代价不对称:多停一次浪费十分钟,少停一次可能要一整天来收拾。

成本或时间超过预算的两倍,停。 事先估「这事值得花多久」,超过两倍就说明当初的判断本身错了,继续投入是在为错误的判断追加投资。这类超支往往在事后账单上才被发现,所以成本监控要提前挂上,别等账单出来才知道。

环境不确定时,停。 你不确定它跑在哪个分支、哪个环境变量生效、连的哪个数据库——先把这些确认清楚再动。在不明环境里排查,你得到的每一个结论都不可靠。

六、避坑清单

坑一:把「重试成功了」当成「问题解决了」。 为什么会踩:重试成功带来强烈的正反馈,人会停止追问。但如果失败原因是并发争抢,重试成功只说明这次抢到了,下次量再涨还会失败,而且是在更糟的时刻。 怎么避:重试成功也要记一笔,统计重试率。重试率持续上升就是容量或并发设计出了问题,那是要改架构的,不是加重试次数。

坑二:给所有失败套统一的重试策略。 为什么会踩:统一策略实现最省事,一个装饰器全局包上就完事。代价是 401 这类永远不会因为等待而变好的错误,也会白白重试完全部次数,把响应时间拖长几倍。 怎么避:重试判定要按错误类型白名单,只有明确列入的错误才重试,其余直接快速失败。默认不重试比默认重试安全。

坑三:用关闭证书校验绕过 TLS 报错。 为什么会踩:报错信息里往往就带着「跳过验证」的建议参数,一加就通,看起来问题解决了。 怎么避:证书链校验失败通常说明网络里有拦截设备(企业网关、安全软件)或对端配置有误。正确做法是把拦截方的根证书导出来加进信任库,而不是把校验关掉。各语言栈都有对应的信任链入口,常用的几个环境变量是:Node.js 用 NODE_EXTRA_CA_CERTS 指向一个 PEM 文件,Python 的 requests 用 REQUESTS_CA_BUNDLE,走 OpenSSL 的工具链通常认 SSL_CERT_FILE。这些变量的具体生效范围各版本有差异,配之前以对应运行时的官方说明为准。关掉校验是把一个可见的告警换成了一个不可见的风险,而且这个配置往往会跟着代码一路进到生产。

坑四:失败之后先清现场再排查。 为什么会踩:现场乱,本能想先收拾干净。但日志、临时文件、未提交的改动、当时的环境变量,恰恰是判别成因唯一的依据。 怎么避:先固化现场再动手。把关键日志和当时的输入落到一个目录里,改动用 stash 存起来,然后再清理。

坑五:让 Agent 自己判断要不要重试。 为什么会踩:把重试逻辑写进任务描述看着很优雅,「失败了就重试」一句话搞定。实际结果是它对失败的判定不可靠——把成功当失败重做一遍,或者把确定性失败重试到额度耗尽。 怎么避:重试是编排层的职责,用代码控制次数、退避和终止条件。Agent 负责执行单步,不负责决定自己该被执行几次。

坑六:忽略「静默失败」这一类。 为什么会踩:分类的前提是你知道它失败了。后台任务、异步流程、无人值守的批量作业,失败之后没人看,几天后才从下游数据对不上发现。 怎么避:给每个任务定义可验证的产物,跑完由外部检查产物是否存在且合规,而不是读它的自述。没有产物校验的自动化,等于没有失败分类。

坑七:分类结论只存在于当事人脑子里。 为什么会踩:现场排完就过去了,下次换个人从头再来一遍。 怎么避:把「现象—成因—处置」三元组记进一个共享文档,一行一条即可。这张表攒到二三十条,新人的排查效率会有明显不同。

收束:一份现场自检清单

失败分类不是理论工作,它是一个每次都要做、每次只花两分钟的动作。真正让它省时间的,是把顺序固定下来,不要每次凭直觉起手。

下次 Agent 报失败,按这个顺序过一遍:

  1. 这个动作可逆吗?不可逆 → 立刻停,交人,不用往下看。
  2. 什么都不改再跑一次,结果有可能不同吗?不可能 → 归到该换路类,别重跑。
  3. 是写操作吗?是 → 先确认有幂等键,再谈重试。
  4. 超时的话,先查状态确认对端到底执行了没有,再决定重试。
  5. 要换路的话,按输入、切法、执行者、方案的顺序来,别一上来就换模型。
  6. 止损点提前写下来:同错三轮、改动扩散、成本翻倍,任意一条触发就停。
  7. 停下来之前,先把现场固化——日志、输入、未提交改动,一样都别丢。

这七条里最值钱的是第二条。它把「我再试试」这种模糊状态,变成了一个能当场回答的问题。多数无效的排查时间,就浪费在没问这个问题上。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。