Chico Notes
研究与调研

Agent 评测:从最终答案走向完整 Trace

把 Agent 评测从“答案是否正确”扩展到环境状态、工具调用、轨迹、策略遵循、成本与副作用,建立可回放、可归因、可持续回归的生产体系。

持续修订的工程笔记

证据快照:本文核对时间为 2026-08-05。OpenAI Agents SDK TracingOpenTelemetry GenAI Agent SpansLangSmith Trajectory Evaluationsτ-bench 仍在迭代。OpenTelemetry 的 Agent Span 规范当前仍标记为 Development;OpenAI 也已在 2026-06-03 的更新中说明,Agent Builder 与旧 Evals 产品计划在 2026-11-30 后停止提供。因此本文强调可移植的 Trace Schema、确定性验证器和自有评测数据,而不是绑定某个平台界面。参见 Introducing AgentKit

摘要

Agent 不只是生成答案,它还会选择工具、修改状态、消耗资源并与外部系统交互。只评最终答案,会掩盖错误路径、越权调用、偶然成功和长尾不稳定。生产评测需要同时覆盖 Outcome、State、Trajectory、Resource、Reliability 与 Safety。

读者将学到什么

读完本文,你应该能够回答:

  1. 为什么传统的“输入—输出”评测不足以评估 Agent。
  2. Outcome、Trajectory、Tool、State、Trace 和 Session 分别应该评什么。
  3. 如何组合确定性规则、环境验证、LLM-as-a-Judge 与人工复核。
  4. 怎样设计支持离线回归、线上监控和失败回流的评测架构。
  5. 如何保存一条可重放、可比较、可定位问题的 Agent Trace。
  6. 为什么一次成功不能证明 Agent 可靠,以及如何使用重复运行衡量稳定性。
  7. 如何避免评测器被 Prompt Injection、Trace 截断和指标平均值误导。

问题背景:答案对了,Agent 也可能是错的

传统 LLM 应用通常可以简化为:

Input
→ Model
→ Output

因此评测也自然围绕输出展开:答案是否正确、是否相关、是否符合格式、是否安全。

Agent 的执行过程不同:

用户目标
→ 规划
→ 选择工具
→ 生成参数
→ 调用外部系统
→ 读取结果
→ 更新状态
→ 决定下一步
→ 最终回答

最终答案只是整条执行链路的最后一个可见结果。

假设一个客服 Agent 最后告诉用户“订单已经取消”。至少存在四种完全不同的情况:

情况最终回复数据库状态是否应通过
正确调用取消接口已取消cancelled
只生成了回复,没有调用接口已取消paid
调错订单后又回复成功已取消另一个订单被取消
重复调用,第一次成功第二次报错已取消cancelled,但产生异常审计记录需结合规则判断

如果评测器只读最后一句话,后三种情况可能被误判为成功。

反过来,Agent 也可能完成了正确操作,但最终回复措辞不理想。此时 Outcome 成功,Response Quality 较差,不能把两类问题合并成一个模糊的“总体得分”。

正确答案可能来自错误路径

常见的“错误路径得到正确结果”包括:

  • 先调用了不该访问的高权限工具,再得到正确答案;
  • 使用了测试环境泄露的 Ground Truth;
  • 重复执行有副作用的工具,但最终状态碰巧正确;
  • 忽略用户限制,通过更昂贵、更慢的路径完成任务;
  • 调用错误工具失败后,依靠模型猜测得出正确文本;
  • 从工具输出中的 Prompt Injection 获得答案。

这些路径在一次测试中可能成功,上线后却会产生安全、成本和一致性问题。

错误答案也不一定来自同一层

一个失败的最终答案可能来自:

目标理解错误
工具选择错误
参数生成错误
工具执行失败
状态提交失败
观察结果读取错误
上下文被截断
最终表达错误

只记录 success=false,团队仍然不知道该修改 Prompt、Tool Schema、权限、重试策略、状态机还是模型。

因此 Agent 评测的目标不只是判断“成没成功”,还要回答:

失败发生在哪一层,为什么发生,修改后是否真正修复,并且没有制造新的成本、安全或稳定性问题。


核心心智模型:评测对象是一棵执行树

一条 Agent Trace 可以看成由多个 Span 组成的执行树:

评测可以发生在不同层级:

层级典型对象适合评估什么
Span单次模型或工具调用参数、错误、延迟、权限、输出结构
Turn一轮 Agent 决策是否选择正确工具,观察后是否合理继续
Trace一次完整任务最终状态、轨迹质量、总成本、任务成功
Session / Thread多轮会话目标持续性、状态一致性、用户意图变化
Dataset Run一批测试任务回归、分组指标、模型和 Prompt 对比
Production Population线上流量长尾错误、漂移、真实反馈与安全事件

Trace 不等于隐藏思维链

本文中的 Trace 指系统可观察的执行事实,例如:

  • 用户输入和任务配置;
  • 模型请求与可公开记录的响应;
  • 工具名称、参数、返回值和错误;
  • 状态读取与写入;
  • 重试、超时、取消和人工审批;
  • Token、成本和延迟;
  • 最终结果和引用。

它不要求保存或评估模型不可见的私有推理过程。

工程上更可靠的做法是评估“模型做了什么”和“系统状态发生了什么”,而不是要求系统依赖一段自然语言思考解释。自然语言理由可以作为辅助证据,但不能替代环境状态、工具日志和可执行验证。


六层评测模型

一个可落地的 Agent Eval 可以拆成六层。

第一层:Outcome,任务是否完成

Outcome 关注最终目标。例如:

  • 代码是否通过测试;
  • 订单是否真的取消;
  • 文件是否被创建到正确目录;
  • 日程是否包含正确参与人和时间;
  • 研究答案是否包含需要的证据;
  • 工单是否进入正确状态。

优先使用可执行、确定性的验证:

单元测试
数据库最终状态比较
文件 Diff
API 读取回验
结构化 Schema 校验
业务规则引擎

SWE-bench 的核心价值就在于:它不是让 Judge 阅读补丁后“感觉正确”,而是在可复现环境中应用补丁并运行真实测试。原始 SWE-bench 包含来自真实 GitHub Issue 的软件工程任务;当前官方实现使用容器化 Harness 提高复现性。

第二层:State,世界是否真的被正确修改

对于具有副作用的 Agent,最终状态通常比最终文本更重要。

可以定义:

expected_state
actual_state
state_diff

以订单取消为例:

{
  "expected": {
    "order_id": "o_123",
    "status": "cancelled",
    "refund_amount": 19900
  },
  "actual": {
    "order_id": "o_123",
    "status": "cancelled",
    "refund_amount": 19900
  }
}

τ-bench 使用对话结束后的数据库状态与标注目标状态比较,并同时关注领域规则。它还提出 pass^k 衡量多次运行的一致可靠性,而不是只看单次成功。

第三层:Trajectory,过程是否合理

Trajectory 是工具调用和状态变化的有序序列:

search_customer
→ get_order
→ verify_policy
→ cancel_order
→ get_order

但“正确轨迹”不一定只有一条。

下面两条路径都可能合法:

A: get_order → verify_policy → cancel_order
B: search_customer → get_order → cancel_order

因此不应默认使用完整序列精确匹配。更实用的评测维度包括:

  • 是否调用了必需工具;
  • 是否调用了禁止工具;
  • 工具参数是否正确;
  • 有依赖的调用顺序是否满足;
  • 是否发生不必要的重复调用;
  • 是否在写操作前完成必要校验;
  • 是否在失败后选择了允许的恢复路径;
  • 是否遗漏状态回验。

TRAJECT-Bench 将工具选择、参数正确性和依赖/顺序满足作为轨迹诊断维度,说明最终准确率无法解释具体的 Tool Use 失败。

第四层:Resource,完成任务花了多少代价

两个 Agent 都完成任务时,仍可能存在显著差异:

指标Agent AAgent B
Tool Calls419
Model Calls312
Total Tokens8k71k
P95 Latency4.2s38s
Cost$0.05$1.20
Retry Count06

只看成功率,二者相同;从生产角度看,它们不是同一个系统。

建议至少记录:

total_latency_ms
time_to_first_action_ms
model_latency_ms
tool_latency_ms
tool_call_count
model_call_count
input_tokens
output_tokens
cached_tokens
estimated_cost
retry_count
human_approval_count

资源指标不应简单合成一个分数。它们更适合作为约束:

在 Outcome 不下降超过 1% 的前提下,P95 延迟降低 20%
在成功率相同的候选中,选择成本更低者
单任务工具调用不得超过 12 次

第五层:Reliability,多次运行是否稳定

Agent 具有随机性。一次成功不代表下次仍然成功。

对同一任务运行 n 次,可以统计:

pass@k:k 次中至少一次成功
pass^k:k 次全部成功
mean success rate
variance
trajectory diversity
cost variance
latency variance

pass@k 适合“允许多次尝试,至少得到一个可用结果”的场景;pass^k 更适合客服、支付、权限操作等要求每次都可靠的业务。

例如单次成功率为 80% 时:

pass@4 = 1 - (1 - 0.8)^4 = 99.84%
pass^4 = 0.8^4 = 40.96%

同一个 Agent 可以同时表现为“很容易撞出一次正确答案”和“连续可靠性很差”。

计算假设:上面的闭式公式假设每次运行相互独立且成功率相同。真实 Agent Rollout 往往受到共享缓存、外部服务状态、同一用户模拟器和上下文残留影响,因此生产报告应优先使用重复实验的实测频率,并同时报告方差与失败分布。

第六层:Safety,是否遵守权限和策略

Safety 不应只检查最终文本是否有敏感词,还应检查:

  • 是否调用了超出用户授权范围的工具;
  • 是否访问了不相关的数据;
  • 是否绕过审批;
  • 是否把工具输出中的指令当作高优先级命令;
  • 是否在只读任务中执行写操作;
  • 是否泄露 Secret、Token、内部路径或个人信息;
  • 是否在失败后尝试规避限制。

OpenAI 2026 年关于内部 Coding Agent 监控的公开说明强调,真实工具环境中的行为监控需要查看完整交互和工具动作,并通过自动监控与人工升级处理潜在问题。这个案例的价值不在于复制其内部实现,而在于说明安全评测必须覆盖行动轨迹,而不只是最终回答。参见 How we monitor internal coding agents for misalignment

2026 年的 ATBench 则专门评估长时程 Agent Safety 轨迹,按照风险来源、失败模式和现实危害组织测试。这类工作说明,许多风险不是单条 Prompt 就能暴露,而是在多步工具交互中逐渐形成。


Agent Eval 的执行架构

离线评测:发布前做可复现对比

每个测试用例建议包含:

id: cancel-order-policy-001
input:
  user_message: "帮我取消刚才的订单"
initial_state:
  customer_id: c_101
  orders:
    - id: o_123
      status: paid
      created_at: 2026-08-05T09:00:00Z
expected:
  final_state:
    orders.o_123.status: cancelled
  required_tools:
    - get_order
    - cancel_order
  forbidden_tools:
    - admin_override
  partial_order:
    - [get_order, cancel_order]
constraints:
  max_tool_calls: 6
  max_latency_ms: 10000
  require_confirmation: false
slice_tags:
  - cancellation
  - no-clarification-needed
  - write-operation

线上评测:从真实流量发现测试集没有覆盖的问题

LangSmith 当前文档明确区分 Offline Evaluation 与 Online Evaluation:离线评测用于数据集实验和回归,线上评测针对生产 Trace 自动运行,并将失败 Trace 回流到 Dataset。Langfuse 则允许 Score 绑定到 Trace、Observation、Session 或 Dataset Run,不同粒度可以保存不同类型的评测结论。

真正有效的评测体系不是一次性 Benchmark,而是:

生产失败
→ 诊断和标注
→ 加入 Dataset
→ 修复
→ 离线回归
→ 发布
→ 继续监控

Trace 数据结构应该保存什么

下面是一个框架无关的最小结构:

{
  "trace_id": "tr_01",
  "task_id": "cancel-order-policy-001",
  "experiment_id": "exp_prompt_v17_model_b",
  "session_id": "sess_42",
  "agent_version": "support-agent@1.8.0",
  "model": "provider/model/version",
  "prompt_version": "prompt_17",
  "toolset_version": "tools_9",
  "started_at": "2026-08-05T09:12:00Z",
  "ended_at": "2026-08-05T09:12:04Z",
  "initial_state_ref": "state://fixture/abc",
  "final_state_ref": "state://result/xyz",
  "spans": [
    {
      "span_id": "sp_1",
      "parent_id": null,
      "type": "model",
      "name": "agent_decide",
      "input_ref": "blob://request/1",
      "output_ref": "blob://response/1",
      "latency_ms": 840,
      "usage": {"input_tokens": 2200, "output_tokens": 180}
    },
    {
      "span_id": "sp_2",
      "parent_id": "sp_1",
      "type": "tool",
      "name": "get_order",
      "arguments": {"order_id": "o_123"},
      "result_ref": "blob://tool-result/2",
      "status": "ok",
      "latency_ms": 120
    }
  ],
  "outcome": {
    "status": "success",
    "final_answer_ref": "blob://answer/1"
  },
  "metrics": {
    "total_tokens": 6420,
    "estimated_cost_usd": 0.047,
    "tool_call_count": 4,
    "retry_count": 0
  },
  "scores": []
}

关键版本字段不能省略

至少要能够回答:

这条 Trace 使用了哪个模型版本?
哪个 System Prompt?
哪套 Tool Schema?
哪个业务策略版本?
哪个 Agent Harness?
哪个环境镜像和测试数据?

否则两次 Experiment 的差异无法归因。

大型工具输出不要全部塞进主表

工具结果、文件、网页和日志可能很大。建议主 Trace 保存:

稳定引用
Hash
MIME Type
大小
截断信息
脱敏状态
保留期限

原始内容放到对象存储或专门的 Observation Store。评测器必须知道输入是否被截断,否则可能在缺少关键证据时给出错误诊断。

建议的数据模型

Trace 只是一次执行记录。要支持版本化数据集、批量实验、Span 级评分和 Artifact 治理,还需要把 Case、Run、Span、Score 与大型产物分开建模。

这里有两个重要约束:

  • 一个 Score 必须明确绑定 Trace、Span、Session 或 Dataset Run 中的某一种目标,不能只存一个脱离上下文的数字;
  • 大型 Artifact 通过稳定 URI 与 Hash 引用,评测主表只保存治理信息和可验证身份。

最小实现:规则、状态和轨迹 Evaluator

下面的 Python 示例展示一个最小评测器。它不依赖具体 Agent 框架,只读取标准化 Trace。

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Iterable

@dataclass(frozen=True)
class ToolCall:
    name: str
    arguments: dict[str, Any]
    status: str = "ok"

@dataclass
class AgentTrace:
    final_answer: str
    initial_state: dict[str, Any]
    final_state: dict[str, Any]
    tool_calls: list[ToolCall]
    latency_ms: int
    total_tokens: int
    estimated_cost_usd: float

@dataclass
class EvalSpec:
    expected_state: dict[str, Any]
    required_tools: set[str] = field(default_factory=set)
    forbidden_tools: set[str] = field(default_factory=set)
    partial_order: list[tuple[str, str]] = field(default_factory=list)
    max_tool_calls: int | None = None
    max_latency_ms: int | None = None

def get_path(value: dict[str, Any], path: str) -> Any:
    current: Any = value
    for part in path.split("."):
        if not isinstance(current, dict) or part not in current:
            raise KeyError(path)
        current = current[part]
    return current

def evaluate_trace(trace: AgentTrace, spec: EvalSpec) -> dict[str, Any]:
    failures: list[dict[str, str]] = []

    # 1. Final state
    for path, expected in spec.expected_state.items():
        try:
            actual = get_path(trace.final_state, path)
        except KeyError:
            failures.append({"type": "state_missing", "detail": path})
            continue
        if actual != expected:
            failures.append({
                "type": "state_mismatch",
                "detail": f"{path}: expected={expected!r}, actual={actual!r}",
            })

    names = [call.name for call in trace.tool_calls]
    called = set(names)

    # 2. Required and forbidden tools
    for name in sorted(spec.required_tools - called):
        failures.append({"type": "required_tool_missing", "detail": name})
    for name in sorted(spec.forbidden_tools & called):
        failures.append({"type": "forbidden_tool_called", "detail": name})

    # 3. Partial ordering rather than exact trajectory matching
    first_pos = {name: names.index(name) for name in called}
    for before, after in spec.partial_order:
        if before in first_pos and after in first_pos:
            if first_pos[before] >= first_pos[after]:
                failures.append({
                    "type": "tool_order_violation",
                    "detail": f"{before} must happen before {after}",
                })

    # 4. Resource constraints
    if spec.max_tool_calls is not None and len(names) > spec.max_tool_calls:
        failures.append({
            "type": "tool_budget_exceeded",
            "detail": f"{len(names)} > {spec.max_tool_calls}",
        })
    if spec.max_latency_ms is not None and trace.latency_ms > spec.max_latency_ms:
        failures.append({
            "type": "latency_budget_exceeded",
            "detail": f"{trace.latency_ms} > {spec.max_latency_ms}",
        })

    return {
        "passed": not failures,
        "failure_count": len(failures),
        "failures": failures,
        "metrics": {
            "tool_calls": len(names),
            "latency_ms": trace.latency_ms,
            "total_tokens": trace.total_tokens,
            "estimated_cost_usd": trace.estimated_cost_usd,
        },
    }

这个实现有意避免完整轨迹精确匹配。它允许多条合法路径,只约束必需工具、禁止工具、关键先后关系和资源预算。


确定性评测、LLM Judge 和人工评审如何分工

优先级一:确定性 Evaluator

适合检查:

  • JSON Schema;
  • 数据库状态;
  • 文件或代码 Diff;
  • Tool 参数;
  • 权限范围;
  • 调用次数;
  • 延迟和 Token;
  • 必需/禁止工具;
  • 可执行测试;
  • 引用 ID 是否存在。

优点是稳定、便宜、可解释。

优先级二:LLM-as-a-Judge

适合判断:

  • 最终回复是否完整、清楚;
  • 工具结果是否被正确解释;
  • 多种合法轨迹中,某条是否存在明显无效步骤;
  • 是否遵循复杂自然语言政策;
  • 失败类型和可能根因;
  • 多轮对话是否持续满足用户目标。

Judge 应输出结构化结果:

{
  "label": "tool_selection_error",
  "severity": "major",
  "span_id": "sp_7",
  "confidence": 0.82,
  "evidence": ["Agent called admin_override before checking refund policy"],
  "rationale": "..."
}

优先级三:人工复核

人工不应随机通读所有 Trace,而应集中在:

  • 高风险写操作;
  • Judge 与规则冲突;
  • 新出现的失败簇;
  • 低置信度或高影响样本;
  • 用户投诉;
  • 发布前的代表性 Regression Slice;
  • 用于校准 Judge 的 Gold Set。

Langfuse 的 Annotation Queue 和 LangSmith 的人工反馈工作流都体现了相同思路:人工标注不仅用于给分,也用于创建纠正输出和校准自动 Evaluator。


LLM-as-a-Judge 的主要风险

1. Judge 只看最终答案

这会退化成传统输出评测,无法定位工具和状态问题。Judge 输入应包含经过脱敏和结构化的相关 Trace,而不是只有 final_answer

2. 把整条超长 Trace 一次塞给 Judge

长 Trace 容易导致遗漏和定位错误。2026 年的 Holistic Evaluation and Failure Diagnosis 工作提出将顶层诊断与 Span 级评估结合;论文报告显示,同一个模型在分解式框架中能获得更好的错误定位效果。这支持一个重要工程原则:

先做局部 Span 检查,再聚合成 Trace 级诊断,通常比一次判断整段日志更可控。

3. Tool Result 对 Judge 做 Prompt Injection

网页、邮件、文档和外部 API 返回值都属于不可信数据。Judge Prompt 必须把它们标记为证据,而不是指令,并对高风险字段做转义、隔离或结构化提取。

4. Judge 与被测 Agent 使用同一盲点

同一模型家族可能共享偏差。可以采用:

  • 确定性规则优先;
  • 不同 Provider 或不同模型 Judge;
  • 多 Judge 一致性;
  • Pairwise 对比;
  • 人工 Gold Set 校准;
  • 定期测量 Precision、Recall 和一致率。

5. Judge 版本漂移

Judge 模型、Prompt 和 Rubric 都必须版本化。旧 Experiment 的分数不应与新 Judge 的分数无条件直接比较。


失败归因:找到 First Bad Event

端到端失败往往会在后续步骤不断放大。真正需要修复的,不一定是最后一个报错,而是第一个让执行偏离可接受轨迹的事件,也就是 First Bad Event。

例如:

Turn 1:Router 把“查询退款规则”错误识别为“执行退款”
Turn 2:Agent 选择 refund_payment
Turn 3:工具因缺少确认而报错
Turn 4:Agent 重试并最终被 Guardrail 拦截
最终结果:任务失败

表面上最后失败在 Guardrail,但 Guardrail 做对了。根因是 Router 的意图分类错误。

归因步骤

  1. 用确定性验证器判断最终 Outcome、State 和硬性策略是否通过;
  2. 按因果顺序遍历 Trace,而不是只按日志时间搜索 ERROR;
  3. 对每个事件计算“输入是否仍处于可恢复状态”和“动作是否属于允许集合”;
  4. 找到第一次违反 Case 约束、业务不变量或合理决策 Rubric 的事件;
  5. 区分 Primary Failure 与后续 Contributing Failures;
  6. 把定位到的 Span 送入单步数据集做独立回归。

推荐的失败分类:

Failure Code判断主要责任层
GOAL_PARSE_ERROR用户目标或约束理解错误Router / Planner
WRONG_ROUTE选择了错误 Agent、Workflow 或数据源Router
MISSING_CONTEXT必要状态、Memory 或检索证据未进入当前步Context Builder
WRONG_TOOL工具选择与目标不匹配Agent Policy
BAD_ARGUMENT工具正确但关键参数错误Argument Generator
POLICY_BYPASS未满足权限、审批或业务前置条件Policy / Guardrail
TOOL_ENV_FAILURE工具或外部环境自身失败Environment
RETRY_ERROR不该重试、重试过多或丢失幂等键Recovery Policy
STATE_COMMIT_ERROR工具成功但状态提交或同步失败State Layer
OBSERVATION_ERROR正确结果被误读、截断或忽略Agent / Parser
LOOP_OR_STALL没有取得进展却继续调用Planner / Stop Policy
FINAL_RESPONSE_ERROR状态正确但最终回复错误Generator
EVALUATOR_ERRORTrace 完整且行为正确,评测器误判Grader

一条 Run 可以保存:

{
  "primary_failure": {
    "code": "BAD_ARGUMENT",
    "event_id": "sp_tool_008",
    "component": "argument_generator",
    "confidence": 0.96
  },
  "contributing_failures": [
    {
      "code": "RETRY_ERROR",
      "event_id": "sp_tool_011"
    }
  ]
}

不要把环境错误算到 Agent 头上

工具超时、Fixture 损坏、测试账号失效和模拟用户违反脚本,都可能导致 Run 失败。τ-bench 的实现也会区分用户、Agent 与环境侧故障,但自动归因本身仍可能出错,需要保留人工复核入口。[9]

因此报告至少要分开:

agent_failure_rate
environment_failure_rate
simulator_failure_rate
evaluator_failure_rate
unknown_failure_rate

否则一次不稳定的测试环境,会被错误解释成模型回归。

Span 级诊断与 Trace 级结论结合

长 Trace 一次性交给 Judge,容易漏掉早期小错误。更稳妥的流程是:

确定性规则定位候选 Span
→ 单步 Grader 判断局部决策
→ Trace Grader 汇总因果关系
→ 高风险或低置信度样本人工复核

这样既保留端到端目标,也能把失败转化为可执行的修复任务。


Benchmark 告诉了我们什么

Benchmark 不应被当作一个总排行榜,而应理解它们分别验证了哪种能力。

Benchmark / 方法主要验证对象强项局限
GAIA通用工具型助手的最终答案真实、多模态、Web 与工具任务最终答案指标难以定位中间失败
SWE-bench代码补丁与真实测试环境可执行、Outcome 客观测试通过不解释 Agent 过程是否高效安全
τ-bench多轮客服、API 工具、最终 DB 状态、规则State 与策略更接近业务模拟用户和任务覆盖仍与真实流量有差异
TRAJECT-Bench工具选择、参数和调用依赖细粒度轨迹诊断参考轨迹设计可能限制开放式合法路径
HALModel、Scaffold 与 Benchmark 的统一 Harness强调运行环境与日志可比性仍需要业务自定义 Rubric
ATBench长时程工具轨迹安全能观察延迟触发和累积风险不能替代业务 Outcome 与 State 评测
Trace Grading / 自建 Agent Evals完整工作流和工具轨迹适合开发回归与生产诊断质量依赖 Trace Schema、Rubric 和 Judge 校准

最重要的不是选择一个“最全面”的 Benchmark,而是为自己的业务建立以下组合:

可执行 Outcome
+ 最终 State
+ 关键 Trajectory 约束
+ Resource Budget
+ 重复运行 Reliability
+ Safety Policy

生产环境中的失败模式

1. 参考轨迹过拟合

把人工轨迹当成唯一标准,会误伤另一条同样正确的路径。

**改进:**使用必需节点、禁止节点、部分顺序和状态不变量,而不是完整序列精确匹配。

2. Simulator 测得很好,真实用户却失败

模拟用户通常更合作、表达更清楚,也可能和 Agent 使用相似模型。

**改进:**保留真实生产 Slice,包括模糊表达、反悔、插话、权限不足、工具慢响应和脏数据。

3. Trace 被截断,但评测器不知道

评测器可能误以为 Agent 没调用某个工具,实际只是日志被裁剪。

**改进:**每个大型 Observation 保存 truncated=true、原始长度、Hash 和完整内容引用。

4. 最终状态正确,但有不可接受的副作用

例如创建了两个日程后删除其中一个,最终看起来只有一个正确日程,但外部系统可能已经发送两次通知。

**改进:**不仅比较最终 State,还要评估 Event Log、Audit Log 和副作用次数。

5. 平均分掩盖关键长尾

总体成功率 95%,可能意味着普通任务 99%,高价值写操作只有 60%。

**改进:**按任务类型、权限、工具、语言、数据源、长度、模型、租户和错误类型切片。

6. 单次运行掩盖随机性

某个 Prompt 在一次回归中通过,重复运行后方差很大。

**改进:**关键用例至少重复运行,报告成功分布、成本分布和轨迹差异。

7. Judge 得分提升,但业务指标下降

Judge 更喜欢更长、更礼貌的回复,用户却更希望快速完成任务。

**改进:**自动分数必须与任务成功、人工标注、用户修正率、撤销率和真实完成时间校准。

8. 评测数据污染

静态 Benchmark、公开答案或测试环境配置可能进入训练数据或 Agent 可访问工具。

**改进:**使用时间切分、私有任务、Live Benchmark、隐藏测试、Ground Truth 隔离和访问审计。


方案比较与取舍

方法稳定性可解释性成本适合场景
Exact Match短答案、固定格式
Environment / State Check代码、数据库、文件、业务动作
Full Trajectory Exact Match极少数流程严格固定的任务
Partial Order + Invariants大多数 Tool Agent
LLM-as-a-Judge中到高中到高语义质量、复杂政策和错误诊断
Human Review取决于标注规范高风险、Gold Set、Judge 校准
User Feedback低到中线上信号,需要和 Trace 联合分析
Repeated Rollouts稳定性、方差和长尾风险

一个实用顺序是:

先用代码和环境验证能确定的事实
→ 再用 Judge 判断复杂语义
→ 用人工校准 Judge 和处理高风险样本
→ 用生产反馈补充离线数据集

发布门禁:从离线回归到 Canary

Agent 的 Prompt、模型、工具 Schema、权限策略或 Memory 只要发生变化,都应该被视为一个新的候选版本,而不是直接替换线上版本。

发布门槛应该分成三类。

质量门槛

task_success_rate 不下降
critical_slice_success 不下降
state_correctness 达标
required_step_recall 达标

安全阻断项

cross_tenant_access == 0
approval_bypass == 0
forbidden_write == 0
secret_exposure == 0

安全项不能与回答质量加权平均。一次越权写入不能靠十次措辞优美的成功回答抵消。

成本与稳定性门槛

p95 latency 增幅受控
tool_call_count p95 受控
estimated_cost 不超过预算
关键 Case 的 pass^k 达标
loop / retry / handoff 异常率受控

比较 Baseline 与 Candidate 时,除了总分,还要生成 Per-Case Diff:

最终状态 Diff
工具序列 Diff
新增或消失的副作用
First Bad Event 变化
Token / Cost / Latency Diff
Judge 与规则冲突

这样一次发布才有明确的收益、代价和回滚依据。


实践检查清单

Dataset

  • 每个 Case 是否包含初始状态、目标状态和业务规则;
  • 是否覆盖正常、边界、失败恢复、权限和长尾任务;
  • 是否有真实生产失败回流;
  • Dataset、Fixture 和 Rubric 是否版本化;
  • 是否防止 Ground Truth 被 Agent 工具读取。

Trace

  • 是否保存 Trace、Span、Tool Call、State Commit 的稳定 ID;
  • 是否记录 Agent、Model、Prompt、Toolset 和环境版本;
  • 是否记录取消、重试、审批和超时;
  • 大型输出是否有 Hash、引用和截断标记;
  • 是否完成脱敏、权限控制和保留期限设计。

Evaluator

  • 能用确定性规则判断的内容是否避免使用 LLM Judge;
  • 是否区分 Outcome、State、Trajectory、Resource 和 Safety;
  • 是否允许多条合法轨迹;
  • Judge 是否输出失败类别、Span 定位、证据和置信度;
  • Judge 是否在人工 Gold Set 上做过校准;
  • Judge Model、Prompt 和 Rubric 是否版本化。

Reliability

  • 关键任务是否执行重复 Rollout;
  • 是否同时报告 pass@k 与 pass^k;
  • 是否观察成本和延迟方差;
  • 是否按高风险工具与任务类型切片;
  • 是否设置 Release Regression Gate。

Online Loop

  • 是否对生产 Trace 做风险分层和采样;
  • 用户反馈能否关联到具体 Trace 和 Span;
  • 是否能把失败 Trace 一键加入 Dataset;
  • 是否有人工 Annotation Queue;
  • 修复后是否先离线回归再发布;
  • 是否监控数据分布和 Judge 漂移。

总结

Agent 评测不能停留在“最后一句话看起来是否正确”。

一个生产级 Agent 同时是:

生成系统
+ 工具调用系统
+ 状态变更系统
+ 分布式执行系统
+ 权限主体
+ 成本中心

因此它也需要多层评测:

Outcome:任务是否完成
State:世界是否真的被正确修改
Trajectory:工具和步骤是否合理
Resource:成本和延迟是否可接受
Reliability:重复运行是否稳定
Safety:是否遵守权限和策略

最重要的工程原则是:

先保存可观察、可回放、可归因的完整 Trace,再让不同 Evaluator 在正确层级上给分。一个总分可以用于看趋势,但不能替代分层诊断。


参考资料

  1. OpenAI, Agents SDK — Tracing
    https://openai.github.io/openai-agents-python/tracing/

  2. OpenAI, Trace Grading
    https://developers.openai.com/api/docs/guides/trace-grading

  3. OpenAI, Introducing AgentKit(页面于 2026-06-03 更新了 Agent Builder 与旧 Evals 的停止时间)
    https://openai.com/index/introducing-agentkit/

  4. LangSmith, Evaluation Concepts: Offline and Online Evaluation
    https://docs.langchain.com/langsmith/evaluation

  5. LangSmith, Trajectory Evaluations
    https://docs.langchain.com/langsmith/trajectory-evals

  6. Langfuse, Scores Overview and Data Model
    https://langfuse.com/docs/evaluation/scores/overview
    https://langfuse.com/docs/evaluation/scores/data-model

  7. Langfuse, Annotation Queues
    https://langfuse.com/docs/evaluation/evaluation-methods/annotation-queues

  8. OpenTelemetry, GenAI Agent Spans
    https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md

  9. Sierra Research, τ-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains
    https://arxiv.org/abs/2406.12045
    https://github.com/sierra-research/tau-bench

  10. Sierra Research, τ²-bench: Evaluating Conversational Agents in a Dual-Control Environment
    https://arxiv.org/abs/2506.07982

  11. Jimenez et al., SWE-bench: Can Language Models Resolve Real-World GitHub Issues?
    https://arxiv.org/abs/2310.06770
    https://www.swebench.com/

  12. OpenAI, PaperBench: Evaluating AI’s Ability to Replicate AI Research
    https://openai.com/index/paperbench/

  13. AgentRewardBench: Evaluating Automatic Evaluations of Web Agent Trajectories
    https://arxiv.org/abs/2504.08942

  14. Liu et al., AgentBench: Evaluating LLMs as Agents
    https://arxiv.org/abs/2308.03688

  15. Zhang et al., Agent-SafetyBench: Evaluating the Safety of LLM Agents
    https://arxiv.org/abs/2412.14470

  16. Mialon et al., GAIA: A Benchmark for General AI Assistants
    https://arxiv.org/abs/2311.12983

  17. TRAJECT-Bench: A Trajectory-Aware Benchmark for Evaluating Agentic Tool Use
    https://arxiv.org/abs/2510.04550

  18. Holistic Evaluation and Failure Diagnosis of AI Agents
    https://arxiv.org/abs/2605.14865

  19. Holistic Agent Leaderboard: The Missing Infrastructure for AI Agent Evaluation
    https://arxiv.org/abs/2510.11977

  20. ATBench: A Diverse and Realistic Trajectory Benchmark for Long-Horizon Agent Safety
    https://arxiv.org/abs/2604.02022

  21. OpenAI, Agent Evals Guide
    https://developers.openai.com/api/docs/guides/agent-evals

  22. OpenAI, Evaluation Best Practices
    https://developers.openai.com/api/docs/guides/evaluation-best-practices


图片清单

1. 原创封面图

  • 文件名:agent-evaluation-trace-cover.png
  • 比例:16
  • 用途:文章封面与社交分享图
  • Alt:一个 Agent 的规划、工具调用、状态变化和验证步骤形成可检查的完整执行轨迹
  • 生成提示词:
A refined editorial illustration for a technical article about evaluating AI agents through complete execution traces. Show an autonomous agent moving through a branching workflow of planning, tool calls, handoffs, state changes, verification gates, and final outcomes. Each action leaves a subtle luminous trace that can be inspected and graded. Include the idea of correct final state versus hidden side effects, with layered diagnostic checkpoints and a clean sense of causality. Deep navy, warm white, restrained cyan and amber accents, modern technical magazine style, spacious 16:9 composition, no text, no letters, no numbers, no logos, no watermark.

2. Agent Trace 执行树

  • 文件名:agent-evaluation-trace-tree.mmd
  • 用途:解释 Trace、Turn、Model Call、Tool Call、Handoff 和 State Commit 的父子关系
  • Alt:一次 Agent 任务由多轮模型调用、工具调用和状态提交组成的执行树
  • 形式:正文“核心心智模型”中的 Mermaid Flowchart

3. 六层评测模型

  • 文件名:agent-evaluation-six-layers.mmd
  • 用途:区分 Outcome、State、Trajectory、Resource、Reliability 与 Safety
  • Alt:Agent 从任务结果到安全策略的六层评测模型
  • 形式:正文“六层评测模型”中的 Mermaid Flowchart

4. 生产评测架构

  • 文件名:agent-evaluation-production-architecture.mmd
  • 用途:解释版本化 Case、隔离执行环境、Trace、自动 Grader、人工审核和发布门禁
  • Alt:Agent 评测从数据集执行到失败回流的生产架构
  • 形式:正文“Agent Eval 的执行架构”中的 Mermaid 图

5. Agent Eval 数据模型

  • 文件名:agent-evaluation-data-model.mmd
  • 用途:解释 Eval Suite、Case、Run、Trace Span、Score 和 Artifact 的持久化关系
  • Alt:版本化 Agent 评测数据集、运行记录、执行 Span、评分和大型产物之间的数据关系
  • 形式:正文“建议的数据模型”中的 Mermaid ER Diagram

6. 评测发布状态机

  • 文件名:agent-evaluation-release-state-machine.mmd
  • 用途:解释 Offline Eval、Shadow、Canary、Full Release 和 Rollback
  • Alt:Agent 版本从离线回归到全量发布与回滚的状态机
  • 形式:正文“发布门禁”中的 Mermaid State Diagram

讨论

继续讨论这篇笔记

有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。

On this page

摘要读者将学到什么问题背景:答案对了,Agent 也可能是错的正确答案可能来自错误路径错误答案也不一定来自同一层核心心智模型:评测对象是一棵执行树Trace 不等于隐藏思维链六层评测模型第一层:Outcome,任务是否完成第二层:State,世界是否真的被正确修改第三层:Trajectory,过程是否合理第四层:Resource,完成任务花了多少代价第五层:Reliability,多次运行是否稳定第六层:Safety,是否遵守权限和策略Agent Eval 的执行架构离线评测:发布前做可复现对比线上评测:从真实流量发现测试集没有覆盖的问题Trace 数据结构应该保存什么关键版本字段不能省略大型工具输出不要全部塞进主表建议的数据模型最小实现:规则、状态和轨迹 Evaluator确定性评测、LLM Judge 和人工评审如何分工优先级一:确定性 Evaluator优先级二:LLM-as-a-Judge优先级三:人工复核LLM-as-a-Judge 的主要风险1. Judge 只看最终答案2. 把整条超长 Trace 一次塞给 Judge3. Tool Result 对 Judge 做 Prompt Injection4. Judge 与被测 Agent 使用同一盲点5. Judge 版本漂移失败归因:找到 First Bad Event归因步骤不要把环境错误算到 Agent 头上Span 级诊断与 Trace 级结论结合Benchmark 告诉了我们什么生产环境中的失败模式1. 参考轨迹过拟合2. Simulator 测得很好,真实用户却失败3. Trace 被截断,但评测器不知道4. 最终状态正确,但有不可接受的副作用5. 平均分掩盖关键长尾6. 单次运行掩盖随机性7. Judge 得分提升,但业务指标下降8. 评测数据污染方案比较与取舍发布门禁:从离线回归到 Canary质量门槛安全阻断项成本与稳定性门槛实践检查清单DatasetTraceEvaluatorReliabilityOnline Loop总结参考资料图片清单1. 原创封面图2. Agent Trace 执行树3. 六层评测模型4. 生产评测架构5. Agent Eval 数据模型6. 评测发布状态机