派大猩 · Agent 工程笔记

Back

「让 Agent 给自己打分,评测集就开始变成作弊集。」自进化闭环跑起来之后,判断的方向要换:闭环会自己爬分,闭环跑得越顺,越看不出哪一层其实是空的。带这类环节的系统要判断自己站在哪、哪一层还是个洞,加指标没用,得有一张能逐层问出「这一层是空的吗」的表。

我现在用的是一张八层检查表。这张表不是评分卡,是审问清单:每一层问同一个产品一件不同的事,任一层答不上来,产品就有一个确定的洞。这张表不负责讲怎么做,每一层的做法散在对应的那几篇里,本篇只把八层钉成一张能带着到处走的表。

八层怎么分:判据只有一条,拿什么判断一层是空的#

八层怎么切,依据不是技术栈,是「一次任务要成立,需要依次满足什么」。从上往下走,越往下越工程,下面几层也常被当作已经做完。八层依次是任务、上下文、能力、编排、执行、验证、状态、信任。

层这一层问什么空了会露出什么样子判据见哪一篇
任务想改变什么状态,目标值怎么量「智能化程度提升」这类没法验收的目标《先画依赖图,再写评测》
上下文做对这一步必须知道哪些东西答复通顺,依据全是猜的《给上下文定预算》
能力什么能做,边界画在哪什么都答应,做不出来也不报错《代码不是真相》
编排怎么拆、怎么排、什么时候停长任务跑不完也停不下来《自治等级不是模型说了算》
执行动作怎么真正发生连得上管不住,权限、幂等、补偿全无《自治等级不是模型说了算》
验证怎么证明结果不是看起来合理演示好看,真实流量一塌糊涂《可验证性就是能力边界》
状态断了之后怎么接上会话断了就得从头再来《自治等级不是模型说了算》
信任用户凭什么授权给它不可逆动作没有把关,出事追不到人《自治等级不是模型说了算》

任一层缺了,对应的失败形态是固定的。任务层没定义,就是「做完了但没人知道做完了没有」;上下文层没定义,答复通顺但依据靠猜;能力层没定义,什么都答应然后什么都做不到。反过来也成立——看到某种失败,能直接指回某一层没做。八层之外我盘算过要不要列第九层「知识」,最后没列。

知识不单独占一层,因为它走的是一条同时穿过上下文层和能力层的路径,运行时只从它身上经过,不为它设单独的位置。上下文层问的是这次推理必须知道什么,能力层问的是什么条件下触发、允许调哪些工具、结果怎么校验,知识在这两个问法上各占一半。一份指标口径的定义、一条例外和适用条件,回答的是这次凭什么判断;一份进入条件、校验规则和异常退出的路径,回答的是这次按什么动作执行。前半段落在读取路径上,后半段落在执行路径上,抽掉任何一段,另一段都没有依靠。

判断一件知识该落在哪一半,只看一句:这句话回答的是判断问题,还是执行问题。业务语义、指标口径、例外、适用条件、历史决策的结论都归上下文层;进入条件、槽位、守卫、停止条件、异常退出的路径归能力层。落到哪一半,一句话只占一个位置。

历史决策是横跨两层最典型的例子:上次为什么这么定,是一次判断的结论,这条结论进知识。要用这条结论继续往下走,上下文层负责取到它,能力层负责在触发时校验这条结论还是不是有效版本。

订单状态、库存、剩余额度这类每次都在动的东西归能力层现取,不写进知识。把这类东西写进静态知识,读到的一定是过期版本,还会盖住真正需要改的口径。

放错位置有两个方向,代价都不小。规则本该进能力层却躺在上下文层,规则就以自然语言散在读取路径上,每次靠模型现场读、现场判适用,没有唯一生效版本。同一个口径在上下文层和能力层各解释一次,就解释成两样东西。动态事实该由上下文层现取,却写死进了能力层,能力就替业务系统扛了它扛不住的实时性,上游改了规则,这里还按旧值执行。

还没变成可引用知识的那部分,先记为知识缺口,别悬在半空。落不下来的缺口不进任何一层的补法,等于没记。判断一条缺口值不值得补,看该覆盖的领域里尚无覆盖、当前版本给不出有效引用、多个会话里重复出现这三样。判出来先补哪半边,看这条缺口卡在读取这一半还是执行这一半,卡在读取那一半就先补上下文层。

这张表的用法很机械:逐层问,每层只许答「过了」「没过」「不适用」。不许用形容词,「不太确定」就是没过。用形容词回答是常见的逃避——「上下文处理得还可以」不算回答,「这次要读哪三份材料、从哪取、读不到怎么办」才算。

八层问下来,团队里对同一层的描述如果不一致,说明这层还没人给它下过定义。这种不一致比空项更容易被忽略,因为每个人描述的都是自己负责的那一半。

八层的判据各是一句什么话#

任务层要把六样东西定死:作用对象是谁、发生在什么场景、现在基线多少、目标值多少、目标值怎么量、红线在哪。缺一样,后面所有讨论都会变成口味之争;没有基线的目标值只是愿望,「从 15 分钟降到 3 分钟」才是目标,中间状态也得有一个系统能读到的信号。

目标值还要带样本口径和时间窗,否则复盘时目标值会自动变松。评测集用什么铺、铺在哪几个指标上、口径固定多久取一次,一次写死,中途不换。目标还要能拆出可观测的中间状态,每类任务至少留一个中间指标,中间指标不一定要暴露给用户。

把上下文、记忆、状态当成一回事,是上下文层最常见的误判。上下文层只问一件事:这次推理必须知道的东西,每一样都答得出从哪取、取不到怎么办。三者是三样不同的东西,上下文层只管上下文和记忆,状态独立成一件,归状态层。

缓存前缀该盯的是加速比:缓存读取相对重新生成的加速比衡量缓存策略,模型的能力单独算。把两者混在一起看,前缀排得再好也解释不了成本为什么没降。前缀按全局稳定、会话稳定、易变三段排好,命中率才有一个不漂的分母。命中率上不去,稳定段里常混进每次都变的内容——一处变动会把后面整段缓存全部打掉。

上下文出毛病的方式基本就三种,分辨清楚才好下药:起作用的排到了后面、该取的不在范围里、塞进去却没当依据,三种都是白费。带得多不等于用得上。

记忆的读取分三级,判据是命中:常驻的每次都带,可预测的开头取,其余按需查询。常用的东西每次都要重新检索,就是分级放错了。记忆写入走异步抽取、不占用户等待时间,这是上下文层唯一不能让步的一条。

能力层要写的是边界,不是本事:什么条件下触发、允许调哪些工具、结果怎么校验、异常怎么退、输出长什么样。少了校验和异常两样,能力就只有正常路径,而线上大部分问题发生在正常路径之外。边界画得对不对,有一个能直接盯的数:转人工率,口径是转人工的会话占总会话的比例。能力层的验收不看这一问答得对不对,只看用户要不要再问一次。

提示词和能力的分工有个经验起点:某个指令在三分之一以上的流量里都要用到,就进常驻提示词。低于这个比例做成按需加载的能力,三分之一这个分界要用真实流量去调。编排层只多问一件事:什么条件下退出。

编排的六种退出条件里,费用上限最容易被漏,它是六条里唯一能在无人值守时自动生效的刹车。并行到什么程度也是编排层要定的,任务之间共享的大段上下文越多,越不该并行。编排还要区分确定性和判断:主链上能确定化的部分写成固定流程,只在真需要判断的地方放循环。整条链路都交给模型自由发挥,出问题就定位不到是哪一步偏的。

执行层先定的是挡在调用前,还是补在调用后。按动作风险分四档——只读直接放行、要一次确认、可先执行后复核的必须可撤销、不可逆的每一步都要人点头。身份绑定、幂等键、熔断、补偿接口和审计留痕这五样由框架兜,不指望模型自觉,其中幂等的代价最高:重试一个写操作带来的重复副作用,排查成本极高。查询类动作放开重试,处置类动作必须带幂等键和证据链,把查询和处置混在一个动作空间里,重试策略就没法定。

验证层的证据有强弱之分,弱的不算验过:静态检查、规则层面的比对、隔离环境里真跑一遍、真实流量下的表现。只做过第一级就发结论,等于什么都没验;负例和相邻能力的边界用例必须各占一部分,否则改动容易在边界上退化。覆盖率也有起步规模:每个用户流程按 50 到 100 个评测用例起步。够不够不看条数,看铺没铺到核心路径和高风险边界,随机抽样凑不出这个覆盖。

对照做法同样不可省:新老版本在同一批用例上同时跑,按单条粒度看清赢在哪输在哪,只看平均分的变化会把「这里赢一点、那里输更多」的改动放过去。发布门禁上再配三件套——每次变更自带用例、负例和边界用例,能力改动先走金丝雀,并留一个能单独关掉某个能力的开关。

同一批用例上看版本之间与人工的一致率、看硬冲突率归不归零,比看一个总分多报了两件事:对得更准,和错得更少。降级率也别被平均分吃掉,它单独盯的是真实流量里走了降级分支的请求占比。

状态层和信任层常被当成细节,任务层、编排层、验证层这三段做得再漂亮,状态层和信任层空着,出事那天没人能交代。状态层的判据很朴素:把当前会话里最新的一条消息删掉,系统能不能从断点继续往下跑。恢复就两条路,选哪条看任务形态:检查点把中间状态整体存下来、恢复时直接读回,适合状态紧凑的;事件溯源只记动作、恢复时重放,适合动作可重放但状态很大。选错这条路线,代价在中断时才会暴露。

任务跑到一半等外部审批、等人工输入、等下游回包,这三种等待的持久化方式都不一样,一个结论成形之前已经发生的副作用能不能安全重放,也得先想清楚。已经写下去的那几步不回滚,重放就只会再写一遍。检查点的粒度也有判据:恢复时重放的动作超过一次人工能等的时间,就说明切得太粗。验收时直接把断点掐掉再跑一遍,比在设计稿上讨论有用。

信任层不看平时,只看出事那一刻用户拿到什么:走到哪一步、哪些状态已被改变、还能用哪部分产物、什么时候停、怎么接管或回滚。信任层的头号检查项是「系统有没有可能在回答里谎称完成」,降级之后仍报告成功,用户会拿一个空结果当结论往下走。

这张表真正的用法:动手之前过一遍,之后跟着版本重问#

八层表最好用的时候不在验收现场,在设计阶段。动手之前把八层过一遍,会发现大部分被推迟的工作不是「以后再说」,是压根没进过计划。验收现场还要防演示路径代替评测:演示里那条路通常被调过很多次,它证明存在一条能走通的路,大部分请求走不走得通它一句也证明不了。演示之外要有一批验收方现场提供的用例,验收方现场跑,提前谁也不跑。

要合成判断的时候按五个维度分别打分,不合成一个数:可信度、稳定性、适应能力、是否符合约定、效率。分别打的意义是一个产品可以效率很高同时可信度不及格,合成一个数之后这个结构就看不见了。

成本单独占一格,看的是完成一次任务的总量,与单轮花费分开算。总 token 从 875,352 降到 676,987,降幅 22.7%,算式是差值 198,365 除以 875,352。单轮输入从 1,030,000 降到 634,905,降幅 38.4%,算式是差值 395,095 除以 1,030,000。降幅不在首次那一轮,在后面几十轮不再重复携带原始数据。

主 Agent 端到端 token 从 708,783 降到 315,266,降幅 55.5%,算式是差值 393,517 除以 708,783,轮次从 17 降到 9。轮次降了近一半,说明省下来的不是某一轮的冗余,是链路里原本多余的往返。

从进入到拿到可信结果要多久,这个指标比准确率更贴近用户,也比盯任何一个单层的分数更接近真实体验。它把等待、澄清、返工和人工确认全算进去,八层里任何一层做不好都会拖低它。

拿这张表过 12 个已上线的 AI 功能#

这张表不只在自家系统上有用,我拿这张表过了一遍已经上线的 AI 功能。12 个系统,覆盖零售问数、排障、文档生成、客服答疑这几类,都在真实流量上跑着,不是 demo。口径这样定:「过了」是某一层有能被系统读到的东西,一段配置、一份用例、一条门禁、一个接口都算。「空」是被问到某一层现在靠什么机制保证时,只能给出口头承诺,上面那些一样也拿不出来。

评审按层项记,12 个系统乘 8 层是 96 个层项,一个个记,不记整体印象。96 个层项里 28 个是空的,28 ÷ 96 = 29.2%。空项按层排下来,顺序很整齐,整齐本身才是值得警惕的地方:

层空项数占 12 个系统
验证650%
上下文541.7%
编排 / 信任4 / 433.3%
执行 / 状态3 / 325%
任务216.7%
能力18.3%

排在前面的验证层和上下文层有个共同点:空着照样能演示。验证层空就没有门禁,问题只在真实流量里显形;上下文层空,答复通顺到肉眼根本看不出来。编排层和信任层紧随其后,理由一样。

空着也看不出来,是因为验证层、上下文层、编排层、信任层这四层的结果都不在每日检查里。任务层和执行层反而不空,「目标含糊」一问就露,「不可逆动作」一跑就出事,它们空不住。

验证层排在最空还有个结构性原因:验证层最晚才被要求做。产品先上线,评测集和发布门禁跟着第一次事故补,补的时候又缺样本,于是验证层长期停在「发布前自己看一眼」。

同一批系统在三个月后我重问了一遍,96 个层项里 31 个结论翻转,31 ÷ 96 = 32.3%。翻转最密的是验证层 7 个和编排层 5 个,加起来 12 项——翻转数可以大于空项数,因为从「过」翻回「空」也算一次。验证层和编排层这两层补一次就能从空变过。

能力层只有 1 个翻转,边界改一次很慢,多数层的翻转落在 3 到 4 个。所以这张表不是一次性工具:验证层和编排层的结论跟着版本走,每次发版都要重问;能力层的空更像长期欠账,评审问出来就挂着等那次改动。

还有一组数讲这张表实际怎么被问:同一轮评审里 96 个层项有 22 个压根没人问,22 ÷ 96 = 22.9%。状态层和信任层各有 5 个系统没被问到,各 41.7%(5 ÷ 12);执行层 4 个;能力层 0 个。跳过的正是出事那天才用得上的层,能力层一次也没跳过,因为能力层直接决定演示好不好看。问不出「这一层是空的吗」,多半是这一层压根没人问。

哪几层必须提前做,哪几层可以后补#

28 个空里,13 个属于上线前必做,15 个有干净的降级替身可以后补,13 加 15 正好是 28。分界看的是空了之后还有没有一条替路。必须提前做的是验证层、上下文层和任务层,这三层空了没法事后补。验证层要的是评测集和发布门禁,得先有样本和真实流量;上下文层要的先是取数、再是组织,得能稳定取到料。

任务层要的是基线和量法,不补它,后面每层都无从判定。可以后补的是编排层、信任层、执行层和状态层,这四层都有「先降级到能跑」的替身。编排空就先串行跑单轮,信任空就先全量转人工兜底,执行空就只放开只读,状态空就把长任务切短。能力层那 1 个要等上游能力就位才能补,单独记一笔工期。

这张表的价值不在一次答全八层#

用过这张表之后我改了一个习惯:不再问一个产品聪明不聪明,而是问信任层答得出来吗。任务层到验证层做得再漂亮,信任层空着,这个产品就还是个演示品。这张表标出的不是八层全过的那个分数,是 96 个层项里哪几层现在是空的。除了空项,这张表还标出一层关系:哪一层空了会连累哪一层。

上下文层空着,验证层再全也验不出依据;状态层空着,执行层跑得越顺,烂摊子铺得越开。12 个系统里一次过八层的只有一个,知道哪几层空、空了往哪层传染,比把八层一次填满更有用。