什么时候不该用 Agent?
Anthropic 的 Building effective agents 把 agentic 系统分成两类:workflow(代码定好路径)和 agent(模型自己决定下一步)。它的第一条建议是:先用最简单的方案,确实需要时再加复杂度。
对测开来说,选哪种模式,就决定了你要测哪几个点、端到端成功率怎么算、成本和延迟能不能提前估出来。
1先退一步看全局
这一周的其他章节会从零写 agent loop、做工具调用、写 MCP server、给 loop 加 trace。动手之前先回答一个更基础的问题:这个需求真的需要 agent 吗?
本章读的是 Anthropic 工程博客 2024 年 12 月 19 日发表的 Building effective agents(Erik Schluntz、Barry Zhang)。文章的结论来自他们和几十个客户团队一起做项目的经验:做得好的团队,用的都是简单、可组合的模式,而不是复杂的框架。
原文顶部后来加了编者按:文中提到的工具生态自 2024 年 12 月以来变化很大。编者按只说工具生态变了,并指向 Claude Managed Agents 的最新做法。我们的判断是:下面讲的模式和原则仍然适用。
2两个定义:workflow 和 agent
原文把所有这类系统统称为 agentic systems,再按"谁决定流程"分成两种:
- Workflow:LLM 和工具按预先写好的代码路径编排。先调哪个、再调哪个,是你的代码说了算。
- Agent:LLM 动态地决定自己的流程和工具使用,自己掌控怎么完成任务。
| Workflow | Agent | |
|---|---|---|
| 谁决定下一步 | 代码 | 模型 |
| 步数 | 固定,或有明确上限 | 不固定,靠停止条件兜底 |
| 成本和延迟 | 可以提前算出来 | 是一个分布,要看 P50 / P95 |
| 原文的适用场景 | 定义清楚的任务,要可预测、结果一致 | 需要灵活性、需要模型在规模化场景下自己做决策 |
| 测开怎么测 | 每个节点单独测,再算端到端 | 测端到端结果 + 看 trace + 测停止条件 |
3基本构件:增强型 LLM
所有模式都用同一块积木:增强型 LLM(augmented LLM),也就是加上了检索、工具、记忆的 LLM。现在的模型可以自己生成搜索词、自己选工具、自己决定记住什么。
原文给了两条要求:这些能力要按你的场景裁剪;给模型的接口要简单、文档写清楚。接第三方工具的一种方式是 Model Context Protocol(MCP),本周有单独一章。
测开视角:这一块就是一次调用。它能测的东西最多、最便宜:固定输入、跑 n 次、数成功次数,第 1 周的 rule of three、Wilson、pass^k 全都直接能用。
4Workflow 1:提示链(prompt chaining)
做法:把任务拆成固定的几步,每次调用处理上一步的输出。中间可以加程序化检查(原文叫 gate),确认流程还在正轨上。
适用:任务能干净地拆成固定子任务。用延迟换准确率:每次调用的任务更简单,更容易做对。原文例子:先写营销文案再翻译;先写大纲、检查大纲是否符合要求,再按大纲写正文。
测开视角:怎么测、哪里容易坏
- 端到端成功率是乘出来的:5 步各 95%,全对只有 \(0.95^5 \approx 77.4\%\)。这和 pass^k 是同一个公式,前提也一样:每步独立。
- 每一步单独测:把上游输出存成快照,固定喂给下一步。出问题时能定位到哪一步,不用每次都从头跑。
- gate 本身也要测:它放过了多少坏的中间结果?gate 漏检,错误就一路传到最后。
5Workflow 2:路由(routing)
做法:先对输入分类,再交给对应的专用下游处理。关注点分开,每个下游的 prompt 可以写得更专门。
适用:输入有几类明显不同、分开处理更好的情况,并且分类能做准(用 LLM 或传统分类器都行)。原文例子:客服问题分成一般咨询、退款、技术支持;简单问题交给小模型,难题交给大模型,省钱。
测开视角:怎么测、哪里容易坏
- 分类准确率是天花板:分类 92%、下游 95%,误路由按失败算,端到端最多 \(0.92 \times 0.95 = 87.4\%\)。
- 看混淆矩阵,不只看准确率:退款请求被分到"一般咨询"和反过来,代价不一样。每一类单独算准确率,并带上 Wilson 区间。小类样本少,区间会很宽。
- 按大小模型路由时,要测"难题被误判成简单题"的比例,那是质量下降的主要来源。
6Workflow 3:并行(parallelization)
做法:几个 LLM 同时干活,输出由代码聚合。分两种:
- 分段(sectioning):把任务拆成互相独立的几块并行做。例子:一个实例回答用户,另一个实例同时筛查不当内容(护栏);自动评测里每个调用评一个维度。
- 投票(voting):同一个任务跑多次,拿到多个结果。例子:用几个不同的 prompt 审查代码有没有漏洞;判断内容是否违规时,用不同的票数阈值平衡误报和漏报。
注意:原文的投票不限于过半。漏洞审查的例子是几个 prompt 各自审查、发现问题就标记,相当于任一票即报警的或规则;内容审核的例子是用不同的票数阈值平衡误报和漏报。阈值越低越偏召回,越高越偏精确。下面的计算以多数投票为例。
适用:子任务能并行、要速度;或者需要多次尝试、多个视角来提高把握。
测开视角:怎么测、哪里容易坏
- 分段:延迟约等于一次调用,但成功率仍然是乘积,3 块各 95% 就是 85.7%。聚合是普通代码,写普通单测。
- 投票和 pass@k 的关系:pass@k 是"k 次里有一次对就算对",默认你有一个可靠的检查器能挑出那一次(比如单测)。多数投票没有检查器,要求过半的票是对的;换成“任一票报警就算”的阈值,召回更高,误报也更多。单票 80%、5 票:pass@5 = 99.97%,多数投票只有 94.2%。
- 单票低于 50% 时,投票越多越差:单票 40%,3 票 35.2%,9 票 26.7%。
- 票与票之间要独立:同一个模型、同一个 prompt 跑 5 次,错误往往扎堆,这就是第 1 周"独立性假设"讲的簇内相关。换 prompt、换模型能降低相关性。
7Workflow 4:编排者-工人(orchestrator-workers)
做法:一个中心 LLM 动态拆解任务,分给若干工人 LLM,再汇总结果。
和并行的区别:拓扑看着像,但子任务不是预先定义的,而是编排者根据具体输入决定的。原文例子:每次要改多个文件的编程产品(改几个、改哪些取决于任务);要从多个来源收集、分析信息的搜索任务。
测开视角:怎么测、哪里容易坏
- 工人个数不固定,成本就不固定。评测报告里要给调用次数的分布,不能只给平均值。
- 拆解本身要测:拆出来的子任务有没有漏掉需求、有没有重复。这一步错了,后面每个工人都做对也没用。
- 汇总要测忠实度:最终结果里的每句话,能不能在某个工人的输出里找到出处。
- 要能排查问题,必须有 trace:记下编排者拆了什么、每个工人收到什么、返回什么。本周 trace 一章专门讲。
8Workflow 5:评估者-优化者(evaluator-optimizer)
做法:一个 LLM 生成,另一个 LLM 评估并给反馈,循环修改。
适用:有明确的评估标准,并且反复修改确实能带来可衡量的提升。两个信号:人给出反馈后,LLM 的回答明显变好;LLM 自己也能给出这种反馈。原文例子:文学翻译(译者模型可能漏掉细节,评估者能指出来);需要多轮搜索的复杂搜索任务,由评估者决定还要不要继续搜。
测开视角:怎么测、哪里容易坏
- 评估者就是一个 Judge,它会判错。两种错:漏判(坏稿子被放行)和误杀(好稿子被打回)。
- 只要漏判率 m > 0,上限就到不了 100%:轮数再多,成功率也收敛到 \(\dfrac{p(1-f)}{p(1-f) + (1-p)m}\),其中 p 是生成器单次做对的概率,m 是漏判率,f 是误杀率。p = 60%、f = 10%、m = 20% 时,上限是 87.1%。这个模型偏保守:它假设每轮生成器独立重来、成功率不变,相当于拒绝采样。原文用这个模式的前提是反馈有用,反馈真能让下一稿变好时,成功率和上限都会更高。但不管反馈多有效,被放行的坏稿子都没机会再改。
- 误杀费钱:好稿子被打回,多一轮生成和评估。
- 评估者要先拿人工标注校准,算一致率和 Cohen's κ,这是第 5 周「Judge 与错误分析」的内容。
- 必须有最大轮数,否则评估者和生成器可能一直来回改。
9自主 Agent
做法:从用户的指令或讨论开始,任务明确后 agent 自己规划、自己行动,必要时回来找人确认。每一步都从环境拿"真实情况"(工具调用结果、代码执行结果)来判断进展。常见的停止条件是最大迭代次数。
原文说,实现上它们通常就是一个 LLM 在循环里根据环境反馈调用工具,所以工具集和工具文档的设计至关重要。本周"从零写 agent loop"一章就是写这个循环。
适用:开放式问题,很难或无法预测需要多少步,也没法把路径写死;模型可能要跑很多轮,你得对它的决策有一定信任。原文例子:解决 SWE-bench 任务的编程 agent(一个任务改多个文件);让 Claude 操作电脑的 computer use 参考实现。
测开视角:怎么测、哪里容易坏
- 只能测端到端:路径每次不一样,没有固定的"第 3 步"可以单独断言。评测看最终结果,按任务算 pass^k(τ-bench 就是这么评客服 agent 的)。
- 步数、成本、延迟都是分布:报 P50 和 P95,门禁也要设在 P95 上。
- 测停止条件:卡住的时候会不会在最大步数处停下?停下时有没有给出可用的中间结果?
- 测恢复能力:故障注入(工具返回错误、超时)后,agent 能不能从环境反馈里发现并纠正。这是 agent 相比固定链路真正的优势,第 4 周会专门做。
10可靠性账:步骤越多,越要小心
把链路上每一步的成功率乘起来,就是端到端成功率:
$$P_{\text{端到端}} = p_1 \times p_2 \times \cdots \times p_n$$| 每步成功率 | 5 步 | 10 步 | 20 步 |
|---|---|---|---|
| 90% | 59.0% | 34.9% | 12.2% |
| 95% | 77.4% | 59.9% | 35.8% |
| 99% | 95.1% | 90.4% | 81.8% |
- 这就是 pass^k 的公式,只是 k 从"同一请求跑 k 次"换成了"链路上的 k 步"。前提也一样:每步独立,且每步的成功率要在真实上游输出上测。如果各步错误正相关(难的输入每步都难),真实成功率反而会比乘积高,这和第 1 周 Agent B 的例子是同一个道理。真正会让成功率低于乘积的,是每步只用干净快照测出的 p:上游“做对了但质量偏差”的输出,会让下一步的实际成功率低于快照测出的值。
- 反推每步要多可靠:10 步想要端到端 90%,每步要 \(0.9^{1/10} \approx 98.95\%\)。
- 每步 99% 怎么证明:按 rule of three,零失败要跑约 300 次(精确法 299 次)。步数越多,要证明的东西越多。
- 乘积也可以被打破:gate 检出错误后重试、agent 从环境反馈里发现错误并纠正,都能把端到端成功率拉回来,代价是多出来的调用次数和延迟。
11原文的核心建议
原文 Summary 部分给出了三条核心原则:保持简单;让 agent 的规划步骤透明可见;认真设计 agent-computer interface(ACI)。另外,它对框架单独给了建议。
原则 1:保持简单,先用最简单的方案
从单次调用开始,只有当更复杂的方案可以证明效果更好时才加复杂度。"可以证明"就是评测的活:新方案和旧方案在同一批用例上比,数字说话。
原则 2:让规划步骤透明
agent 打算做什么、为什么这么做,要显式地展示出来。对测开来说,这就是可观测性:规划和每一步决策都进 trace,出错时才能定位(本周 trace 一章)。
原则 3:认真设计 ACI(把工具接口当成产品)
ACI 要像人机界面一样投入:工具要写好文档、充分测试。具体做法见下面的列表。
另外:谨慎使用框架
框架能帮你省掉调用 LLM、定义和解析工具、串联调用这些底层工作,但多出来的抽象层会遮住底层的 prompt 和响应,让调试更难,也容易让人加上本来不需要的复杂度。建议先直接用 LLM API,很多模式几行代码就能写出来。如果用框架,要搞懂它底层在做什么;原文说,对"底层到底在干什么"的错误假设,是客户出错的常见原因。
ACI 的具体做法
- 站在模型的角度看工具描述:只看描述和参数,能不能明白怎么用?
- 参数名和说明写得像给新同事看的 docstring;写上例子、边界情况、和其他工具的分工。
- 用很多不同的输入试调用,看模型会犯什么错,然后改工具。
- 防呆(poka-yoke):改参数设计,让错误更难犯。原文的例子:做 SWE-bench agent 时,他们花在优化工具上的时间比优化整体 prompt 还多;模型切换目录后用相对路径老出错,改成必须传绝对路径后,模型就再也没用错过。
测开视角:ACI 就是被测系统和模型之间的"接口契约"。工具契约测试(参数校验、错误信息是否能让模型看懂并自我纠正)是这一章最直接能落地的测试工作。
▶模拟器:选模式,调参数,看成功率、成本和延迟
两个成功率要分开:p₀ 是一次调用做完整个任务的成功率(单次调用、投票、评估者-优化者的生成器用它);p 是拆小以后每一步的成功率(提示链、路由的下游、分段、编排者-工人、agent 的每一步用它)。模型都假设各步独立。
所有模式对比(各模式用各自的当前参数)
▶场景判断:给需求,选模式
按原文的判断标准选最合适、最简单的一种。选完看解析,再点"下一题"。
✎练习
12面试要点与代码
一句话讲清楚
Workflow 是代码定路径,agent 是模型定路径。Anthropic 的建议是先用最简单的方案,单次调用够就不上 workflow,workflow 够就不上 agent。从评测角度看,链路上每一步的成功率要相乘,步数越多越难做到可靠;agent 的步数不固定,成本和延迟要按分布报 P95。每种模式有自己的薄弱点:路由看分类准确率,投票看独立性,评估者-优化者看评估者的漏判率。
常见错误说法
❌ "每一步都 95%,整体应该也差不多":10 步乘下来只有 59.9%。
❌ "投票次数越多越准":单票低于 50% 时越投越差;同源的票相关,提升也比独立时小。
❌ "加一个评估者自动把关就行了":评估者自己会漏判,只要漏判率 m > 0,成功率的上限就到不了 100%。
❌ "agent 平均一次花 8 步":只报平均值,看不到长尾。门禁要看 P95。
❌ "先上一个框架再说":原文建议先直接用 LLM API,搞懂底层再决定要不要框架。
from math import comb
def chain(p: float, n: int) -> float:
"""提示链:n 步各自成功率 p,各步独立时的端到端成功率。"""
return p ** n
def majority_vote(p: float, m: int) -> float:
"""m 票(奇数)多数投票,每票独立、正确率 p。"""
if m % 2 == 0:
raise ValueError(f"票数要是奇数,收到 m={m}")
return sum(comb(m, k) * p**k * (1 - p)**(m - k) for k in range(m // 2 + 1, m + 1))
def evaluator_optimizer(p: float, rounds: int, miss: float, false_reject: float) -> float:
"""每轮生成器成功率 p;评估者漏判率 miss、误杀率 false_reject;
最多 rounds 轮,最后一轮被打回也照样输出。"""
accept_good = p * (1 - false_reject)
accept_bad = (1 - p) * miss
reject = 1 - accept_good - accept_bad
ok = sum(reject**i * accept_good for i in range(rounds))
return ok + reject**(rounds - 1) * p * false_reject
print(chain(0.95, 10)) # 0.5987
print(majority_vote(0.8, 5)) # 0.9421
print(evaluator_optimizer(0.6, 3, 0.2, 0.1)) # 0.8318
公式显示依赖 KaTeX(CDN),断网时公式会显示成原始 LaTeX 源码,交互部分不受影响。