Agent 的关键外部能力要预留降级路径

2026-08-25

我自己搭了一个写公众号文章的 Agent,从一条链接开始,读原文、定方向、过提纲、核资料、写正文、出封面,中间几处必须我点头才能往下走。这套东西的第一步永远是「把这条链接里的文章读进来」——读不到,后面十几步一步都开不了。

有一次它就卡在这一步。这篇写的是那一次,以及我从那一次里改掉的东西。

现象:卡住的位置比失败本身更靠前

任务发起后,它停在最开始那一段。不是内容读得不完整,不是格式解析出错,而是负责渲染网页的那个后台进程根本没有起来。也就是说,失败发生在「准备读」这个动作上,还没走到「读到了什么」。

这个位置很关键。如果是读回来的内容有问题,我至少还有一份东西可以看、可以判断;而启动就失败,手上是空的——没有半份素材,没有可比对的中间产物。对整条流水线来说,这一步的产出物是后面所有步骤的唯一输入:方向要基于原文选,提纲要基于方向排,正文要基于提纲写。输入为空,后面全部悬空。

我当时的第一反应不是「怎么修好这个进程」,而是「这一步失败了,整件事是不是就该停在这里」。回头看,这个反应本身是错的。

当时是怎么发现的:它被写进了已知问题清单,而不是被当场绕过去

这一段我特意要写清楚,因为发现方式比问题本身更值得留下来。

关于这次失败是怎么被察觉的,我手上留下的唯一痕迹是一份文档:它被写进了这个 Agent 的说明书,和其它几条已知问题排在一起——那份说明书里有一节专门列「目前还有哪些没弄好」,这条就在里面。至于当时到底是我盯着任务看出来的,还是回头翻记录翻出来的,我没有记录,也不打算在这里补一个听起来合理的说法。真正被留下来的不是那一刻的场景,而是这条失败最后被放进了哪一栏。

我觉得这个动作比修复动作重要。一次外部依赖启动失败,最省事的处理是当场换个方式绕过去、事情办成了就翻篇,不留任何痕迹。这样做的问题是:这类失败会重复发生,而每一次都要重新想一遍怎么绕。写进已知问题清单,意味着它从「一次意外」变成了「一个待处理项」,下次再遇到不用重新判断。

我这条流水线上,能被复用的从来不是当时那个临场的解法,而是「这类失败被登记在哪里、归成了哪一类」。

另外一点:这类失败在流程设计上本来就有落点。这个 Agent 的流程图里,有一个专门的人工介入点管「外部能力或授权异常」,还有一个管「由人提供可读的替代素材」。也就是说,读不到东西这件事,在设计阶段就被预留了位置,只是我一开始没意识到那个位置应该先被自动路径试一遍。

为什么会这样:我把能力和它的某一种实现绑死了

这个 Agent 的能力清单里,那一项写的是「网页读取」——写的是一种能力。但在实际执行时,这项能力事实上等同于一个具体的后台进程。进程起不来,能力就没有了。

启动为什么会失败,我没有记录,也不打算在这里补一个听起来合理的原因。能确定的只有一点:失败发生在启动阶段。

我更在意的是设计上的那层错位。岗位卡那一段输入写的是文章链接或主题,工作流里的第一个判断点是「输入是否足够开始」——这两处关心的都是目标:手上有没有一份可以往下走的原文。而实现层面关心的是手段:那个进程活着没有。目标和手段之间没有留缝,手段一断,整件事就被判定为不可继续。

这是我自己搭的时候偷的懒:一件事只写了一条路,那条路就默认成了唯一的路。

改成了什么:换一条路把同一份东西拿回来

那次的处理很朴素——改用命令行的抓取方式去请求同一条链接,文章读到了,流程继续往下跑完了。

这之后我把这一步的写法调了一下:读取原文这件事,我不再只写一种做法,而是写成「先试哪一条、不成再试哪一条、都不成再怎么办」。最后那一档不是继续自动重试,是停下来交给我——这正好落在流程图里那两个原本就存在的人工介入点上:外部能力异常归一处,需要我提供替代素材归另一处。

顺带说一句,从「失败即中止」改成「降级后继续」,中止那条路并没有被删掉,它只是从第一档挪到了最后一档。这个区别很重要:如果只有降级没有中止,那就是另一种偷懒了。

可迁移的判断:降级换的是实现,不是权限

如果只能带走一句话,我希望是这一句:降级路径只允许换实现方式,不允许换访问权限。

我给这个 Agent 写的红线里有明确一条:不能绕过登录、付费墙或访问权限去读取文章。这条红线在正常路径上成立,在降级路径上同样成立——而且降级的时候最容易松动,因为当下的心态是「就差这一步了、换个方式拿到就行」。

我自己用的判据是一句问话:换了这条路之后拿到的,是不是原来那条路本来就能合法拿到的同一份东西?

  • 是同一份 —— 这是降级。渲染进程读和命令行读,读的是同一个公开页面,公开的东西换个方式取回来,性质没变。
  • 不是同一份 —— 那就不叫降级,叫越权。比如原来读不到是因为要登录、要付费、要特定权限,而新路子恰好把这道门绕开了,此时「成功了」反而是最坏的结果:事情办成了,红线破了,而且不会有任何报错提醒我。

第二种情况的正确动作不是想办法读到,是停下来。我这套流程里,「链接不可访问、需要登录或付费」本来就是人工介入条件的第一条——它触发的是把这件事交回给我,由我来提供一份可以合法读取的替代素材,而不是由 Agent 自己去想办法穿过去。

再往外收一层:值得预留降级路径的,是那种「失败了就没有输入、后面全部走不动」的能力。不是每一个外部调用都要配备用方案。我这里用的还是同一个问法:判断一个动作要不要做回查确认时,我问的是「这一步的产出会不会被后面当作前提使用」;这次我把同一句话拿来判断要不要配第二条路。会被当作前提,它一断就是全线停摆,值得提前想好;不会,配了也是给自己增加维护量。

我这次踩的这一脚,恰好就是最靠前、最要命的那一步。

这篇写的是我自己那套流程里的一次实际情况,不是通行做法。你的场景、工具和团队规模不同,结论未必适用,判断方式可能比结论更值得拿走。

延伸阅读

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