【智能体测评-10】生产环境的Agent可观测性与持续测评
这是“智能体测评”系列的第 10 篇,也是收官篇。第 9 篇讲了不同场景的测评方案差异,那些主要发生在发布之前。但 Agent 真正的考验从上线那一刻才开始——用户不会按你的测评集提问,环境会变化,模型会更新。这一篇我们讲四层框架的最后一层 L4:Agent 上线之后,怎么持续知道它好不好,以及怎么让生产环境反哺你的测评体系。
测评不止于发布
一个常见的误解:测评是发布前的质检流程。跑一轮黄金集,分数达标,上线,结束。
如果 Agent 是传统软件,这个思维勉强成立——代码不变,行为基本不变,上线前测完就可以高枕无忧。但 Agent 有三个特性让“发布即终点”的假设彻底失效:
第一,Agent 的行为依赖模型,而模型在你看不见的地方变化。
你用 gpt-4o 开发并测过的 Agent,三个月后底层模型可能已经静默更新了好几次。同一个 prompt、同一份代码,行为可能完全不同。你不会收到任何 changelog。
第二,Agent 的环境是活的。
它依赖的 API 会改版、网页会重构、数据会过期。测评时全部通过的 Agent,可能因为某个工具的返回格式变了,在生产中突然全线失败。
第三,用户的使用方式永远超出你的预期。
测评集中的任务是你能想到的,生产中的请求是你想不到的。用户会用你的 Agent 做你设计时完全没预料到的事,其中一些会暴露你从未测试过的能力边界。
这意味着测评必须是一个持续的闭环,而不是一次性的关卡。生产环境不是测评的终点,而是测评最重要的数据来源。
L4 生产观测层:看什么
L4 的观测体系可以分成四个层次,从技术指标到业务指标逐层递进。
第一层:技术健康度
这是最基础、最容易采集、也最先报警的信号。
| 指标 | 说明 | 告警建议 |
|---|---|---|
| 错误率 | 工具调用失败、API 超时、代码异常的比例 | >5% 告警 |
| P95 时延 | 从用户发消息到 Agent 最终响应的时间 | >30s 告警 |
| Token 消耗 | 每次任务的平均/最大 token 消耗 | 突增 2 倍告警 |
| 中断率 | 任务未正常完成(超时/崩溃/用户取消)的比例 | >10% 告警 |
| 工具可用性 | 各外部工具的成功率(分工具统计) | 单个工具 <90% 告警 |
这些指标不告诉你“Agent 做得好不好”,但能第一时间告诉你“Agent 是不是挂了”。
实现上,在 Agent 的每一步执行中埋点:
import time
import logging
logger = logging.getLogger("agent.trace")
async def run_agent(user_message: str, session_id: str):
trace_id = generate_id()
start = time.time()
state = AgentState()
async for event in agent.astream_events(user_message):
if event["type"] == "tool_call":
tool_start = time.time()
try:
result = await execute_tool(event["tool"], event["args"])
logger.info("tool_call", extra={
"trace_id": trace_id,
"session_id": session_id,
"tool": event["tool"],
"args": sanitize(event["args"]), # 脱敏!
"status": "success",
"latency_ms": int((time.time() - tool_start) * 1000),
"tokens": result.usage,
})
except Exception as e:
logger.error("tool_error", extra={
"trace_id": trace_id,
"tool": event["tool"],
"error": str(e),
"latency_ms": int((time.time() - tool_start) * 1000),
})
logger.info("task_complete", extra={
"trace_id": trace_id,
"total_latency_ms": int((time.time() - start) * 1000),
"total_tokens": state.total_tokens,
"step_count": state.step_count,
"status": state.status,
})这些日志建议直接打造成 OpenTelemetry 格式,可以无缝接入 Langfuse、LangSmith、或自建的 trace 系统。
第二层:行为质量指标
技术指标正常,不代表 Agent 表现好。第二层看的是 Agent 的行为质量信号:
任务完成信号(自动采集)
- 任务是否以 Agent 给出最终回答结束(而非异常中断)
- Agent 是否主动声明“我无法完成”(这个信号很重要——它区分了“诚实失败”和“硬撑着失败”)
- 用户是否在同一任务上重复发起(通常意味着不满意)
用户显式反馈
- 点赞/点踩按钮
- 对话后的评分(1-5 星)
- 文字反馈(“这个回答帮到我了吗?”)
注意:显式反馈有严重的选择偏差——极度满意和极度不满的用户才会点,中间大多数人不反馈。不要把点赞率直接等同于满意度。
用户隐式信号
这些比显式反馈量大得多,也更真实:
- 用户是否复制了 Agent 的输出
- 用户是否继续追问(追问的性质:补充信息 vs 表达不满 vs 换个方式问同一个问题)
- 用户是否在 Agent 回复后直接离开(可能是满意,也可能是放弃)
- 用户是否走人工通道/转接客服(对 Agent 的“不信任投票”)
隐式信号需要结合场景建模,不能直接当作满意度,但它的趋势变化(某版本后转接率上升 50%)是非常灵敏的告警。
第三层:轨迹抽样审计
全量人工审计不现实,全量自动审计深度不够。折中方案是分层抽样:
| 抽样策略 | 比例 | 目的 |
|---|---|---|
| 全部点踩/投诉 | 100% 审 | 发现严重问题 |
| 高风险动作后 | 100% 审 | 退款、删除、发送等不可逆操作 |
| 异常轨迹(步数超长/错误重试/死循环) | 100% 审 | 发现系统性故障 |
| 随机抽样 | 2-5% 审 | 基线质量监控 |
| 新模型/Prompt 版本上线后 48 小时 | 20% 审 | 快速发现新版本问题 |
审计方式:人工看轨迹时间线(第 6 篇讲的格式),标注成功/失败/部分成功 + 失败类型(用第 2 篇的失败分类学)+ 严重度。
这些审计结果有两个用途:一是计算真实成功率(区别于 Agent 自称的完成率),二是为测评集提供回采素材(后面详说)。
第四层:业务影响
最上层是 Agent 对业务的实际影响:
- Coding Agent:PR 接受率、bug 修复周期变化、代码回滚率
- 客服 Agent:人工话务量变化、平均处理时间、客诉率、复购率
- 深度研究 Agent:报告采纳率、决策引用率、用户使用频率
业务指标是最终裁判——如果 Agent 技术指标全绿但用户不用它,它就是失败的。但业务指标延迟最长、受干扰因素最多(季节性、市场活动、其他产品变化),不适合作为快速反馈信号,适合作为月度/季度的方向校准。
持续测评:从 L4 到 L1-L3 的回流
L4 不只是“监控”,它和 L1-L3 之间有一条关键的数据回路。这是整个测评体系形成闭环的核心。
生产流量(L4)
│
├── 失败 case ──▶ 分类标注 ──▶ 回归集(L3)
│ │
├── 异常轨迹 ──▶ 模式分析 ──▶ 组件测试(L1)
│ │
└── 新场景 ───▶ 专家审核 ──▶ 探索集 ──▶ 黄金集(晋升)
│
新版本门禁 ◀┘
│
发布回生产 ──▶ L4失败回采:把生产事故变成测评资产
每一条生产失败都是免费的测试用例。关键是建立自动捕获 + 人工 triage 的流程:
自动捕获信号:
- 显式点踩
- 检测到死循环(步数超阈值)
- Agent 输出“无法完成”且用户重复追问
- 用户转接人工
- 工具调用连续失败 3 次以上
- 任务时长超过 P99
Triage 流程:
- 去重:同一根因的失败自动聚类(用 embedding 相似度 + 失败类型标签),避免 100 条本质相同的 case 涌入
- 脱敏:移除 PII、密钥、商业敏感数据
- 标注:人工标注失败类型(第 2 篇的六维分类)、根因、严重度
- 转化:转化为可复现的测评任务——构造输入 + 定义期望行为(不是要求 Agent 必须成功,而是定义“在这种情况下应该怎样”,比如“应该诚实告知无法完成而非编造答案”)
- 入库:进入回归集,确保后续版本不再犯同样的错
这个流程跑起来后,你的回归集会随生产时间自然增长,而且增长的都是真实遇到过的问题——比任何想象出来的测试用例都有价值。
新场景发现:Agent 在做你没设计过的事
用户会把 Agent 用在意料之外的场景。定期(建议每周)从生产流量中聚类出“新任务类型”:
- 对最近一周的用户请求做 embedding 聚类
- 找出不属于现有测评集标签的新聚类
- 评估:是应该支持的新场景,还是应该拒绝的越界使用?
- 该支持的 → 编写测评任务进入探索集;该拒绝的 → 编写“安全拒绝”测试(Agent 应该识别边界并妥善拒绝)
环境变化检测:工具和数据源的“无声故障”
Agent 依赖的外部环境变化往往不会触发任何技术告警(API 还在返回 200),但内容已经变了。检测方法:
- 工具返回一致性检查:定期对一组固定输入调用各工具,对比返回结构是否和预期一致(schema drift 检测)
- 成功率突降告警:某个工具在 Agent 轨迹中的成功率从 95% 突降到 60%,即使技术层面没有报错(可能是返回了错误页面但 HTTP 状态码正常)
- 黄金集定期重跑:每周用当前生产版本重跑黄金集——如果分数下降但代码没动,说明环境或模型变了
金丝雀发布:把测评嵌入发布流程
新版本(模型升级、prompt 调整、工具链改动)上线时,不要全量发布。金丝雀流程:
阶段一:影子流量(Shadow)
新版本不直接服务用户,而是复制一份生产流量在后台运行,结果不返回给用户。对比新旧版本在相同输入下的输出差异:
- 结果分歧率:多少比例的请求两个版本给出了不同结果
- 分歧分类:新版本是“修正了旧版本的错误”还是“引入了新错误”
- 轨迹差异:步数、工具选择、成本的变化
影子流量安全、零风险,可以跑几百到几千条真实流量。
阶段二:小流量金丝雀(5%)
新版本对 5% 的用户生效。重点观测:
- 技术指标(错误率、时延)是否异常
- 隐式信号(转接率、重复追问率)是否恶化
- 全量审计这 5% 的高风险动作
- 持续 24-48 小时
阶段三:灰度扩大(20% → 50% → 100%)
每一步观察 24 小时,关键指标无回退再扩大。
回滚标准(提前定义,不要临场判断):
- 任何严重安全事件(数据泄露、错误退款等 P0 事故)→ 立即回滚
- 任务完成率相比旧版本下降超过 3% → 回滚
- 错误率上升超过 50% → 回滚
- 成本/时延上升超过 30% 且无质量提升 → 回滚
成本与质量的平衡曲线
生产观测带来一个在 L1-L3 不太需要面对的问题:每个月花在 Agent 运行上的钱是真金白银。 你需要持续回答一个问题:当前的质量水平是否值当前的成本?
方法是画出成本-质量曲线:
质量(成功率)
100% ┤
│ ╱
80% ┤ ╱───── ← 当前位置?
│ ╱─────
60% ┤ ╱─────
│ ╱─────
40% ┤╱
└──────────────────────────── 成本($/任务)
$0.05 $0.10 $0.20 $0.50你可以通过调参跑出这条曲线上的点:
- 用小模型(haiku/mini)做简单任务 → 成本低但质量可能下降
- 用大模型(opus/旗舰)做所有任务 → 质量高但成本 5-10 倍
- 限制最大步数/token → 降成本但复杂任务可能完不成
- 加缓存(相同问题复用结果)→ 降本但覆盖面有限
做法:在回归集上用不同配置跑,记录每档配置的成功率和平均成本,画出帕累托前沿。然后做一个清醒的商业决策:
- 成功率 85%、成本 0.45/任务
- 如果你的场景是“错了无所谓,量大管饱”(如灵感生成),选前者
- 如果你的场景是“错了代价巨大”(如医疗、金融),选后者
不要追求“尽可能高的质量”,要追求“在当前业务约束下的最优质量成本比”。这个最优解会随业务阶段变化,所以每季度应该重新评估一次。
工具选型:从自建到平台
实现 L4 观测有两种路径,取决于团队规模:
轻量方案(日活 <1000 次任务,早期团队):
- 日志:结构化 JSON 日志 → SQLite/PostgreSQL
- 可视化:Metabase(开源)配几块看板
- 告警:日志监控脚本 + 企业微信/飞书 webhook
- 轨迹抽样:每周导出随机 50 条,人工在表格里标注
- 成本:几乎为零,开发量 2-3 天
标准方案(日活 1000-100000,成长期团队):
- Trace 采集:OpenTelemetry SDK 埋点
- 观测平台:Langfuse(开源自部署)或 LangSmith(SaaS)
- 日志基础设施:标准 ELK/Loki + Grafana 看板
- 用户反馈:产品内嵌入反馈组件
- 审计队列:抽样轨迹自动推送到标注工具(Label Studio / Argilla)
- 金丝雀:通过 API 网关做流量分发
- 成本:Langfuse 自部署约一台 4C8G 服务器;SaaS 版按 trace 量计费
规模化方案(日活 >100000):
- 全链路 OpenTelemetry → 自有数据湖(ClickHouse / Spark)
- 实时流式指标计算(Flink / Kafka Streams)
- 自动化根因分析(异常轨迹聚类、自动归因)
- 自研标注和测评管理平台
- 成本:需要专职团队维护
建议从轻量方案起步,但日志格式从第一天就按 OpenTelemetry 语义写,这样迁移到平台时不需要重构埋点。
警惕三个生产观测的误区
误区一:仪表盘幻觉
做了 20 个 Grafana 面板,每天看数字,以为自己在“观测”。但面板上的数字如果不驱动任何行动,就是电子装饰品。
检验标准:你能不能说出上周 Agent 的一个具体问题,以及它是怎么通过观测发现、怎么修复的?如果不能,说明你只是在看数字,没有在用数字。
误区二:平均成功率崇拜
“整体成功率 92%”这个数字可能同时掩盖了:P0 场景成功率 98%(很好)和某类边缘场景成功率 40%(灾难)。平均值是最容易让人麻痹的指标。
对策:永远切片看——按场景、按用户群、按工具、按难度。一个整体 92% 的 Agent 可能藏着某个 30% 成功率的子场景,那就是你下一个要修的地方。
误区三:观测团队和开发团队割裂
监控/QA 团队看数据、报问题,开发团队收工单、修问题——这种模式下观测数据的利用效率极低。开发者自己应该能方便地查看任意一条 trace,在自己的开发环境中复现生产问题。
最好的组织设计是:每个 Agent 开发者都对自己功能的线上指标负责,观测工具对开发者完全开放,而不是只有“运营人员”能看到。
回到起点:这个系列讲了什么
写到这里,11 篇文章(00-10)的系列可以收束了。让我们回到总纲提出的框架,看看每一篇回答了体系中的什么问题:
| 层次/模块 | 文章 | 核心回答 |
|---|---|---|
| 世界观 | 00 总纲 | 我们如何看待 Agent 测评:任务导向、过程结果并重、持续闭环 |
| 认知基础 | 01 范式断裂 | 为什么不能用模型跑分的思路测 Agent;能力六维模型 |
| 语言体系 | 02 失败分类学 | Agent 失败的 26 种模式,让“出问题了”变成可定位的语言 |
| 层次框架 | 03 四个层次 | L1 组件 / L2 轨迹 / L3 任务 / L4 生产,各测什么 |
| 外部参照 | 04 Benchmark 拆解 | GAIA/SWE-bench/WebArena/τ-bench/BrowseComp 各测什么、盲区在哪 |
| 评分机制 | 05 LLM-as-Judge | 模型当裁判的偏见、校准方法、rubric 设计 |
| 过程测评 | 06 轨迹测评 | 六个过程指标、轨迹对比方法、恢复行为分级 |
| 测评集建设 | 07 测评集方法论 | 黄金集/回归集/探索集三层架构、任务来源、防污染 |
| 工具落地 | 08 测评流水线 | 一套可跑的开源 Python 流水线 |
| 场景适配 | 09 三类场景 | Coding/客服/深度研究的测评方案差异 |
| 生产闭环 | 10(本篇) | 可观测性、失败回采、金丝雀发布、成本质量平衡 |
如果要用一句话概括整个系列的主张:
Agent 测评不是发布前的一场考试,而是贯穿开发到生产的质量基础设施。它的价值不是产出一个分数,而是让你在改 prompt、换模型、加工具的每一个决策点上,都能回答“这到底是变好还是变坏了”。
这个领域还在非常早期。我们在这个系列里写的方法论,很多会在未来两年被推翻或重写——就像今天看 2023 年的 Agent 测评实践会觉得原始一样。但有几件事我们相当确定会长期成立:
- 只看成功率是不够的,过程和结果必须同时被衡量。
- 公开 benchmark 会持续失真,自建测评能力是团队的核心资产。
- 生产环境是最好的测评集来源,建立从线上到测评集的回流通道比什么都重要。
- 测评的目的不是证明 Agent 行,而是找到它哪里不行——然后修好它。
如果你从这个系列只带走一个实践,我们希望是:今天就给你的 Agent 记全量轨迹日志,哪怕还没有任何分析工具。 三个月后你会感谢自己——因为那时候你拥有的数据,是任何临时测评都无法替代的。
系列到这里结束。但测评这件事,对每一个做 Agent 的团队来说,才刚刚开始。
