本文是「Agent 开发实践与思考」系列第 14 篇。系列目录:
- 2024
- 2025
年初给转码 Agent 换过一版模型。自测的十几个例子都比旧版顺,上线后接的第一个真实迁移单元里,验证契约三层全绿,评审时才发现弹窗提交成功后不再刷新父列表——这个行为在旧代码里没有测试覆盖,新版本模型也没有主动去排查。类型检查和构建通过,不代表迁移完成。
做完巡检 Agent 的异步改造后,评估更躲不过去。它会自己消费告警、查日志,有时还会执行可逆的处置动作。离线跑通一条告警链路,不等于它会在长期运行中稳定地做出同样判断,也不等于它会一直守住转人工的边界。
最初我把评估理解成”准备一批任务,统计通过率”。实际搭下来,至少有四件不同的事:任务结果对不对,过程有没有走歪,资源有没有失控,线上有没有出现离线集没覆盖的新问题。混成一个总分,最后很难决定该改什么。
评估维度不止一条通过率
梳理内部评估体系时,我把常见文献里的维度摆到了同一张表里。业界大多数文献确实把主要精力放在任务完成率上(“Beyond Accuracy: A Multi-Dimensional Framework for Evaluating Agentic AI”, 2024),但企业内部落地时,成本、可靠性和安全性这几项经常是先被通过率掩盖、后被事故揭穿的部分。
| 维度 | 典型指标 | 我在意的原因 |
|---|---|---|
| 任务完成率 | Success Rate、Resolve Rate | 最基础,但只回答”这次做成没做成” |
| 推理步骤效率 | Steps-to-completion、Token 消耗 | 两个都完成任务的方案,成本可能差一个数量级 |
| 工具调用准确率 | API Call Correctness | 参数和 schema 是否正确,是机械判据 |
| 规划能力 | Plan Quality Score | 多步任务是否走了合理的分解路径 |
| 鲁棒性 | Error Recovery Rate | 撞到工具失败、环境异常后能不能恢复 |
| 泛化能力 | Cross-domain Transfer Score | 换一个仓库、换一类告警是否还稳定 |
| 成本效率 | $/task、Token/task | 决定这套系统能不能长期跑 |
| 安全性 | Constraint Violation Rate | 越权、误操作,一票否决级别 |
| 可靠性 | Variance across runs | 同一个任务多次跑,结果稳不稳定 |
| 自主性 | Human Intervention Rate | 需要人介入的比例是升还是降 |
| 多轮交互 | Context Retention | 长会话或长任务里,早期约束是否还生效 |
| 可解释性 | Decision Justification Quality | 出问题时能不能定位原因 |
我不会对每个任务都填满这十二项。一次性、单轮的问答类任务,前四项加安全性基本够用;巡检 Agent 和转码 Agent 这类会长期运行、能改外部状态的系统,可靠性、自主性和安全性权重要显著提高,否则一次”看起来通过”的评估会掩盖它在真实环境里逐渐跑偏的过程。
代码类任务还有一层维度是通用列表覆盖不到的。转码和重构不是”写出新代码”就算完成,它要求旧行为在新实现里原样保留,这和普通功能开发的评估要求不一样。
| 专有维度 | 评估方法 | 核心挑战 |
|---|---|---|
| 语义保持性 | 单测 PASS_TO_PASS + 接口兼容检查 | 测试覆盖不足时,无法证明改动前后完全等价 |
| 代码质量提升 | CodeBLEU、圈复杂度变化、重复率变化 | 质量指标主观性强,自动化只能覆盖一部分 |
| 安全性(不引入新 Bug) | 编译通过 + 回归测试 + 类型检查 | “部分重构”最容易漏改引用方 |
| 跨文件上下文理解 | 多文件编辑正确性 + 依赖链追踪 | 大仓库里上下文窗口和检索都可能不够 |
拆解 Coding Agent 那篇里的迁移说明、影响图和验证契约,本质上都是在为这四项专有维度收集证据:迁移说明里的 contract 和 behaviors 字段对应语义保持性,verification 对应安全性,影响图对应跨文件理解。评估不是另起一套流程,而是把这些证据结构化地跑一遍、记下来、可以复现。
按优先级排,我现在的顺序是:任务完成率、语义保持性、安全性放第一梯队,必须每次都过;代码质量、成本效率、可靠性放第二梯队,常规迭代要看;跨文件理解、规划能力、自主性放第三梯队,作为加分项跟踪趋势。这个排序不是通用真理,是我们当前任务分布和风险偏好下的取舍。
评估前先写任务契约
一条任务不是一个可评单元。评估需要知道初始世界是什么、允许 Agent 做什么、什么叫完成、什么情况应该停止。这四项合起来,我现在叫它任务契约。
转码 Agent 的契约通常落在仓库中:基线 commit、允许修改的目录、不可改的接口、验收命令、预算和需要人确认的问题。拆解 Coding Agent 那篇里的迁移说明、阶段权限和验证契约,都是把任务条件写成程序和人都能读的记录。代码、测试和文档互相冲突时,needs_review 也应该是契约允许的结果,系统应停止写入,等人确认。
巡检 Agent 的任务契约还要多两项:动作的影响范围和幂等条件。查日志、查 trace 可以自动做;重启实例、摘流等可逆动作要记录事件 ID、目标对象和执行结果;回滚、改配置、写业务库这类动作只能生成待办。评估要检查它是否在对应条件下停在正确的权限边界,排障报告写得通顺不能证明这一点。
任务契约写不出来,题目先不进评估集。很多所谓 Agent 评估的困难,其实发生在这一步:团队没有把业务验收条件表达出来,却希望模型替自己补齐。
结果、轨迹和约束要分开看
一个 Agent trace 里可以拆出三种评价对象,判据和价值都不同。
第一种是终态。文件是否生成、代码是否通过测试、告警是否被正确处置,都是终态。终态校验接近工程真正关心的结果,也允许多条正确路径同时通过。WebArena 把网页任务放在可重置环境中,检查页面、数据库或文件的最终状态;转码任务的终态检查同理,重置到基线 commit,跑完验证契约,看状态而不是看过程有多漂亮。
第二种是轨迹。终态正确不代表过程可靠。一个 Agent 可能先越权调用,再碰巧拿到可用结果;也可能重复查十次相同接口,最后才改对文件。轨迹里至少可以查四件事:选的工具是否属于当前阶段允许的集合,参数是否符合 schema 和权限,动作顺序是否违反前置条件,是否超过轮数、时间或费用预算。
轨迹不是越细评越好。很多任务有多条合理路径,把唯一的”标准调用序列”当答案,容易误伤正常方案。我的做法是只约束不能变的部分。例如转码任务里,写操作必须带 expectedVersion,不能在 Investigate 阶段调用写工具;巡检任务里,重启前必须先查过日志和 trace。其余搜索和检查顺序留给 Agent。需要检查语义合理性时,再从 trace 中抽样给 LLM 或人工看。
第三种是边界。信息不足时有没有停在 needs_review 或 needs_decision,越权请求有没有拒绝,审批未通过时有没有继续执行。这类任务往往没有”成功的业务终态”,却直接决定系统会不会越权。我会把它们单列成拒绝题和升级题,不和普通成功题混在一个通过率里。总分上涨时,也要确认系统没有只是更愿意硬做。
工具调用本身还有一层机械检查,对应上面维度表里的”工具调用准确率”。JSON 是否可解析、字段是否齐全、路径有没有越过白名单,这些应该由代码断言。它们能判合规性,判不了”该不该选这个工具”。把两类问题分开,才不会把 schema 通过误当作工具选择正确。
判据按确定性分层
我把判据从便宜到贵排成三层。不是每条任务都要走完三层,能在前面结束就不要往后送。这个分层和业界推荐的”自动化功能测试 + LLM-as-Judge + 抽样人工”组合是一回事,只是我更习惯按成本顺序描述。
第一层是确定性校验。测试结果、退出码、文件 diff、工具 schema、权限和预算,都应该由程序判断。转码任务跑 typecheck、单测、构建和受影响的流程检查,验证契约里声明的每一项都在这一层。巡检任务的确定性校验包括事件 ID 是否记录、目标对象是否匹配、执行结果是否成功返回。工具调用记录由执行器输出结构化结果,别让模型从一段 stderr 里自己判断到底是参数错误、环境故障还是权限拒绝。
第二层是规则化的答案校验,重构领域常用 CodeBLEU 结合语法树和数据流做代码质量的自动打分。检索也应单独评。在 embedding 召回评测里,我用真实查询、相关性分级、Recall@K、MRR 和 bad case 检查检索结果。检索分数好,只说明正确材料进入了候选集,不能替代端到端任务通过率。
第三层才是 LLM-as-Judge 和人工。它们处理的是程序不容易定义的问题,例如重构后的代码可读性是否提升,诊断是否引用了足够证据,多个等价方案哪个更适合当前约束。LLM 可以扩大覆盖面,人用来抽审、校准裁判和处理低置信或争议样本。让人工全量打分慢且不稳定;把所有判断都交给 LLM,问题也一样,只是成本更低、速度更快。
一条 trace 的常见流向是:全量跑第一层,命中硬错误直接失败;需要文本判断的子集进入第二、三层;规则与 Judge 不一致、Judge 置信度低或涉及高风险副作用的样本进入人工队列。人工结论要回写题目、规则或 Judge few-shot,不能只停在一次 review 里。
LLM 裁判要校准
LLM-as-Judge 不适合直接拿一个 1 到 5 分当结论。实际使用中,有几个偏差反复出现。
位置偏差最容易测。把两个候选答案放在一起,排在前面的答案经常占便宜。每次比较我都会交换 A、B 再跑一遍,两次结论一致才采用,不一致判平或交给人。MT-Bench 的裁判研究也提到过这种偏差。
还有自我偏好。让模型 X 评模型 X 的答案,分数容易偏高。裁判模型和被测模型最好分开;至少在一次版本比较里,不要同时更换生成模型和裁判模型。
绝对分数常常挤在中间,还容易偏好更长的回答。把”改动好不好”拆成可观察的问题会稳定一些,例如是否遗漏了调用方,是否引入了新的圈复杂度,是否有没有依据的行为假设。两版 Agent 对比时,配对比较通常比绝对打分更有用,只问”在当前任务契约下哪个更符合要求”。
裁判也会随模型版本和 prompt 改动漂移。每次评估结果要记录裁判模型、prompt、温度和 rubric 版本。每周抽几十条给人复核,如果人不同意裁判的比例超过一成,先修裁判,再讨论 Agent 是否退化。没有这层校准,模型升级后的一条分数曲线没有可比性。
通过一次不等于可靠
第一批数据集只有两百多题。有次改动通过率涨了 5%,看起来不错,但多跑几次又回去了。温度设为 0 不能让整条链路确定,检索排序、工具响应和外部状态仍会变。
现在每次大改都会固定同一份数据集跑三遍。看总体通过率,也看每题三次的结果。提升幅度小于这几次运行的方差,就不记进发布记录。这个办法不严格,但能挡住单次运行带来的错觉,对应维度表里的”可靠性”。
τ-bench 的 pass^k 把同一个问题说得更清楚:同一任务独立跑 k 次,要求每次都成功。pass^1 是”这次有没有做成”,pass^k 才开始接近”能不能稳定交给它”。论文里 pass^1 到 pass^8 的差距很大,说明单次成功常常不是可靠性。我的三次重复可以看作一个成本较低的近似,至少先把不稳定的改动挡在发布前。
每次比较也要有 baseline。新版本只和同一数据集、同一环境、同一裁判条件下的旧版本比。数据集更新、工具 schema 更新、裁判模型升级时,绝对分数会变,不能拿不同条件下的两个分数直接宣布提升。
成本和过程错误要进报告
一次改版的通过率没变,平均工具调用次数却从 4 次涨到 11 次。答案质量一样,成本翻了一倍多。只报一个通过率,这次改动会被误判为没有影响。不同 Agent 之间的 Token 消耗差异可以到十倍以上,成本效率必须单独作为一项跟踪,不能被完成率掩盖。
所以每次任务还要记录轮数、工具调用数、输入输出 token、折算成本、延迟、重复调用和预算耗尽次数。两个 Agent 都完成任务,一个调 3 次工具,一个调 15 次,线上体验和账单不会一样。上下文成本那篇算的是单次调用,这里需要算整个任务。
轮数上限也应该进入失败统计。它不是单纯的兜底开关。Agent 撞到上限,说明它已经在错误路径上消耗了资源,即使最后一段回复碰巧还能用,也不能算正常完成。
离线集之外,还有线上回归
离线集解决的是回归比较。它能告诉我一个改动是否伤到了已知任务,不能保证线上不会出现新的分布。
所以线上要持续采样 trace。转码 Agent 看测试通过率、人工修改 diff、PR 被拒绝和回滚;巡检 Agent 看重复告警、错误处置、人工撤销和漏报。这里的指标不能直接当作模型能力分数,因为它们会受产品流量、权限和外部系统状态影响,但它们可以帮助发现离线集没收进来的新 case。
新 case 不能看到一次就马上加进集。先确认它是产品需求变化、外部系统故障、任务契约缺失,还是 Agent 能力问题。只有最后一类才适合写成稳定的回归题。否则评估集会变成线上事故的杂物箱。
公开基准放在什么位置
SWE-bench、WebArena、τ-bench、GAIA、AgentBench、ToolBench 各自测的东西不一样。SWE-bench 测代码修复和测试通过;WebArena 测网页环境里的多步操作;τ-bench 测带政策约束的多轮工具任务;GAIA 偏通用助手的浏览、工具和推理;ToolBench 更接近 API 编排。它们可以用来筛选模型、理解一个 harness 会暴露什么问题,也可以借鉴环境和判据设计。
代码重构方向最近两年也在补专项基准。RefactorBench 用 100 个手工构造的多文件任务测状态化推理,最佳系统通过率只有 30% 到 40%;SWE-Refactor 从真实 Java 项目挖掘了上千个开发者重构实例,区分原子重构和复合重构两个粒度,复合重构的顶级成绩也只有 39.4%;SWE Atlas Refactoring 用真实开源项目的多文件生产代码做第三方独立评测,当前最好成绩 48.57%。三个基准报告都提到同一类失败模式:上下文丢失、跨文件状态不一致、依赖遗漏——这和我们在转码任务里遇到的问题几乎一样。这也说明多文件重构目前仍是行业公认的难点,不是我们内部工程不到位。
它们不能替我证明内部转码 Agent 或巡检 Agent 可以上线。任务分布、工具描述、权限模型和执行环境都会改变结果。同一个模型换一套工具封装或 prompt,分数可能就不同。比较基准结果时,至少固定模型、工具集合、提示词、最大轮数和环境版本;不同 harness 下的分数不要当成同一把尺子。
公开基准给我最大的帮助,是把”怎么测”拆得更清楚:有终态就查终态,有安全边界就单列拒绝题,有随机性就重复运行,有开放文本才引入裁判。业务数据和验收条件仍然要自己准备。
工具怎么分工
评估平台解决的是记录、组织实验、执行判据和查看回归,不会自动替业务定义任务契约。
LangSmith 适合已经在 LangChain 或 LangGraph 上开发的团队。它把 trace、数据集、实验和人工反馈放在一起,接入成本低。Langfuse 更适合希望自托管,或者工具调用、检索和自定义分数都要自己控制的场景。我现在用 Langfuse 记录 trace 和版本,判据本身仍写在业务代码里。
DeepEval 的形态更接近 pytest,适合把离线评估放进 CI。它提供了若干 LLM 指标,也可以写自定义指标。Inspect AI 是专门面向 Agent 多步评测设计的框架,支持沙箱、工具调用和多步任务,社区也比较活跃,评估重构类 Agent 时我会优先考虑它。RAGAS 只解决检索和生成的 RAG 维度,适合做检索组件的离线评测,不能代替 Agent 的终态和权限评估。Arize Phoenix 偏 OpenTelemetry 观测和自托管链路分析。Promptfoo 适合补提示注入、越权和数据泄露等红队 case,它不替代任务成功率评估。
工具选型要看现有栈、数据能不能出网、是否需要自托管、判据是否要进 CI。对我这类系统,最小组合已经够用:一个 trace 平台,一套可重置的评估环境,业务代码里的确定性校验,少量校准过的 LLM Judge,再加人工抽审。先把这些跑起来,比再接一个评估 SaaS 更有价值。
分阶段建设,而不是一步到位
评估体系不是一次性搭完的项目,我现在按四个阶段推进。
第一阶段是快速验证:选一小批已有的真实迁移单元或历史告警,跑通”确定性校验 + 简单裁判”的最小闭环,先确认判据能不能自动跑起来,不追求覆盖率。第二阶段是定制扩展:基于内部仓库和真实业务规则构建专有评测集,把语义保持性、安全性这类专有维度的检查接进去,覆盖到主要任务类型。第三阶段是接入 CI:每次模型、prompt 或工具版本升级,自动跑一遍评测集、生成报告、和历史版本比对,通不过就拦截发布。第四阶段是生产监控:把线上 trace 持续接入观测平台,收集离线集覆盖不到的新失败模式,反哺评估集迭代。
这四个阶段不是严格顺序,很多时候是并行推进的,但如果团队还没有走到第一阶段就想直接上生产监控,通常意味着还没有一份可判断”对不对”的任务契约,监控数据也无从解读。
还没补完的两块
现在改提示词、换模型、改检索或新增工具,都会先跑离线集。转码 Agent 主要看语义保持性、安全性和测试通过率,巡检 Agent 主要看终态和拒绝题,检索组件先看召回再跑端到端任务。通过率之外,还会一起看成本、稳定性和失败分类。
数据集维护仍然很花时间。业务规则和仓库结构会变,三个月前捞的 case 即使分数高,也不代表今天线上没有新问题。我现在每周从日志补题,也淘汰长期不出现的旧题。
巡检 Agent 的漏报更难评。离线集能测一条已有告警进来以后它怎么做,测不到本来应该发现、却没有任何事件进来的问题。现在只能靠日志审计、抽审和主动巡检覆盖一点,这部分还没有省事的办法。

