Agent 不是黑箱,只是少了一台行车记录仪:从 AgentOps 到可诊断智能体

结合 AgentOps、Agent 设计模式、MAST、GRADE 与 AgentDebugX 五项研究,解释为什么 Agent 可观测性不能停在 Token、延迟和调用日志,以及如何把目标、计划、工具、依赖、评估和护栏组织成可诊断、可恢复的证据链。

一个退款 Agent 调错了接口,多退了 500 元。监控面板一片绿色:HTTP 200、延迟 1.8 秒、Token 没超预算、模型也没有报错。那它到底错在哪里?是用户目标被理解错了,计划漏了一步,查到旧订单,还是工具参数用错了?

传统应用出故障,我们习惯先看日志、指标和调用链。但到了 Agent 系统,常见的可观测性仍停在“模型调用了几次、花了多少钱、请求有没有报错”。这就像调查交通事故时,只拿到发动机转速和油耗,却没有行车路线、驾驶决策、路况和刹车记录。

《AgentOps: Enabling Observability of LLM Agents》试图补上这台“行车记录仪”。论文分析了当时 17 个 AgentOps 或 LLM 应用运维工具,提出一套 Agent 工件关系模型和追踪分类学。它最重要的贡献不是又造了一个平台,而是把问题说清楚了:

Agent 的一次运行不是一串 LLM 请求,而是一张由目标、推理、计划、任务、工具、评估和护栏共同构成的执行图。

如果只记录 LLM 输入输出,我们看见的是发动机;如果要解释整辆车为什么开进沟里,就必须记录整张图。

先建立一张地图:Agent 可观测性的四个部分

读后面的细节前,先抓住四个部分:

  1. 执行结构:谁先做了什么,控制权如何从计划流向任务和工具;
  2. 依赖关系:后一步究竟依赖了哪份知识、状态和中间结果;
  3. 质量控制:评估器检查了什么,护栏在何处放行、拦截或升级给人;
  4. 版本证据:当时使用了哪个模型、提示词、工具、配置、评估器和策略版本。

这四部分坐落在一个更大的生产闭环里:设计 → 执行 → 观察 → 评估 → 修复 → 再执行。它们之间的杠杆关系也很直观:

  • 记录更多执行 Span,定位粒度会提高,但存储、延迟和隐私成本也会上升;
  • 只记录父子调用,能回答“谁调用了谁”,却回答不了“谁依赖了谁”;
  • 增加在线评估和护栏,可以更早发现问题,但评估器本身也必须版本化和校准;
  • 版本信息缺一项,历史回放就可能变成“用今天的系统猜昨天发生了什么”。

所以,可观测性不是“日志越多越好”,而是用可接受的成本留下足够的因果候选证据

一次 Agent 运行,到底应该长什么样

假设用户说:“订单 A 重复扣款了,请退回多收的部分。”一个简化的退款 Agent 可能经历下面的过程:

flowchart LR
    U["用户目标:退回重复扣款"] --> A["Agent"]
    A --> R["推理:识别订单与风险"]
    R --> P["计划:查询、核对、退款、通知"]
    P --> W["工作流"]
    W --> T1["任务 1:查询订单"]
    W --> T2["任务 2:核对重复扣款"]
    W --> T3["任务 3:执行退款"]
    T1 --> DB["订单工具"]
    T3 --> PAY["支付工具"]
    E["评估器"] -.检查.-> P
    E -.检查.-> W
    G["护栏"] -.约束.-> T3
    T1 -.订单状态依赖.-> T2
    T2 -.金额依赖.-> T3

AgentOps 论文把一条完整 Trace 拆成嵌套的 Span。每个 Span 都有一组通用字段:名称、开始时间、持续时间、输入输出、错误、指标、事件、父 ID 和跨 Span 链接;不同类型的 Span 再带上自己的业务语义。

把它翻译成工程语言,大致是下面这张表:

Span 类型最值得保留的证据能回答的问题
Agent角色、职责、persona、Agent 版本当时是谁在负责?它被赋予了什么边界?
Reasoning上下文引用、检索知识、决策规则、决策摘要决策依据来自哪里?应用了哪些约束?
Plan目标、约束、计划步骤、历史计划引用目标有没有在规划阶段被改写或漏掉?
Workflow任务列表、任务依赖、运行环境、历史执行工作如何被拆分和编排?
Task任务说明、状态、重试次数、结果哪一步开始偏离,是否发生静默失败?
Tool工具名与版本、配置、请求响应引用、副作用调了什么、用的哪版、改变了什么外部状态?
Evaluation测试用例、指标、评分结果、评估器版本“成功”是谁定义和判定的?
Guardrail策略版本、检查目标、动作、命中原因风险规则是否执行,为什么放行?
LLM模型与版本、参数、Token、延迟哪次模型调用产生了什么成本和候选输出?

这里有一个容易踩的坑:论文把 reasoning outcome 也列为元数据,不代表生产系统就应该默认保存模型的原始思维链。原始思维链可能包含敏感信息、未经验证的猜测,体积也很大。更稳妥的做法是记录结构化决策摘要、引用的证据、采用的规则以及最终动作,并对输入输出做脱敏、哈希或受控引用。可观测性的目标是可审计,不是把所有内部文本永久倒进日志仓库。

为什么普通调用链还不够:执行边不等于依赖边

到这里,AgentOps 已经比“只记 LLM 请求”前进了很远。但 2026 年的 GRADE指出了一个更隐蔽的缺口:Trace 通常能告诉你运行顺序,却不一定告诉你每一步依赖了什么。

想象一个订票 Agent:

  1. 查询价格;
  2. 锁定座位;
  3. 确认付款。

三个步骤都按顺序成功执行,调用链毫无异常。但如果第三步依赖的是第一步读到的价格,而价格在第二、第三步之间已经变化,故障发生在“依赖失效”,不在“执行顺序错误”。

GRADE 因此把一次运行表示成共享同一组节点的两层图:

  • 执行边记录控制流,例如先后顺序、Agent 交接和工具调用;
  • 依赖边记录数据与状态依赖,例如读取、写入、复用或基于某个结果做决定。

依赖边还要标明证据强度:它是从 Trace 中直接观察到的,是通过埋点明确声明的,还是在某个假设下推断的。论文在六类 Agent 数据上发现,经过规模归一化的依赖结构能够在跨数据集测试中保持高于随机水平,而单纯的运行规模在部分留出类别上会失效。

这给工程系统一个很实在的提醒:parent_span_id 只能表达嵌套,不能替代数据血缘。至少对高风险动作,应该显式记录:

  • 这一步读取了哪个资源、哪个版本或哪个快照;
  • 使用了哪些上游输出;
  • 写入或改变了哪些外部状态;
  • 依赖是观测到、声明的,还是推断出来的。

调用链回答“它怎么走到这里”,依赖图回答“它凭什么这么做”。 两者缺一不可。

有了 Trace,要找什么:MAST 给失败起了名字

只有记录,没有诊断语言,工程师仍然会在一大坨 Trace 里凭感觉找错。《Why Do Multi-Agent LLM Systems Fail?》提供了另一个拼图:作者从 7 个多 Agent 框架收集了 1,642 条标注 Trace,归纳出 14 种失败模式,分成三大类:

  1. 系统设计问题:角色或任务规范不清、重复执行、上下文丢失、无法识别任务已经完成;
  2. Agent 间失配:带着错误假设继续、任务跑偏、隐瞒或忽略关键信息、推理与动作不一致;
  3. 任务验证失败:没有验证结果、验证不充分,或错误地接受了失败产物。

这套分类不是作者拍脑袋列的清单。MAST 先由专家对 150 条 Trace 反复归纳,最终标注者一致性 Cohen’s κ 达到 0.88;随后用 LLM-as-a-Judge 扩展标注,少样本版本与人工标注达到 94% 准确率、κ 为 0.77。

更值得工程团队注意的是:这些问题不能都甩给“模型不够强”。论文在保持底层模型不变的情况下,仅调整 Agent 角色描述就让 ChatDev 的成功率提高 9.4 个百分点;系统工作流和提示词干预的最大提升达到 15.6 个百分点。一个团队里每个人都很聪明,不代表组织一定能把事做对;多 Agent 系统同样如此。

MAST 与 AgentOps 恰好互补:

  • AgentOps 定义应该留下哪些工件
  • MAST 定义应该在这些工件里寻找哪些失败

比如“上下文丢失”需要关联 Reasoning、Plan 与历史记录;“信息被忽略”需要查看 Agent 交接和依赖边;“缺少验证”则应该直接表现为 Workflow 尾部缺失 Evaluation Span。失败分类一旦能映射到 Span 类型,告警就不再只是“输出分数低”,而是“退款动作依赖的订单快照已过期”或“高风险工作流在结束前没有执行金额一致性评估”。

可观察还不是可诊断:错误出现的位置未必是根因位置

Trace 还有一个经典陷阱:报错的位置,常常不是犯错的位置。

退款接口返回金额超限,表面上是 Tool Span 失败;真正的根因可能是三步之前的计划没有写“只退重复部分”,也可能是订单查询返回了两笔不同币种的交易,而核对任务把它们直接相加。只盯着红色 Span,修复往往会落在错误的层。

AgentDebugX把 Agent 调试组织成一个四步闭环:

flowchart LR
    D["Detect<br/>检测"] --> A["Attribute<br/>归因"]
    A --> R["Recover<br/>生成修复"]
    R --> X["Rerun<br/>重跑验证"]
    X --> D

它的 DeepDebug 不只做一次性总结,而是结合全局轨迹、结构化调查和交叉质询逐步缩小根因。在 Who & When 基准上,使用 Qwen3.5-9B 时,精确到“责任 Agent + 准确步骤”的归因率为 28.8%,强于最佳单轮基线的 21.7%;在 GAIA 实验中,它单次重跑修复了 73 个失败任务中的 13 个,使总体准确率从 55.8% 提高到 63.6%,而三个拆分式自我修正基线各修复 4 到 6 个。

这些数字一方面证明闭环调试比“看一眼 Trace 后重试”更有希望,另一方面也提醒我们保持清醒:28.8% 的精确归因率远未达到可以无人值守的程度。 当前更合理的定位,是让诊断器生成带证据的根因候选和可回滚修复,再由测试、策略门或人工完成最终放行。

从论文落到系统:一份最小可观测契约

如果现在要给一个 Agent 平台设计第一版观测协议,我会从下面五层开始,而不是先采购一个漂亮 Dashboard。

第一层:统一身份与时间线

每次用户目标分配稳定的 trace_id;每个步骤有 span_idparent_span_id、类型、开始与结束时间、状态、错误和事件。跨 Trace 的异步任务、消息交接和恢复运行使用显式 links,不要伪装成父子关系。

第二层:记录“版本化的决定条件”

模型名还不够。提示词模板、Agent 定义、工具 schema、知识库快照、护栏策略、评估器、关键运行参数都要有可回溯版本。否则同一输入今天复现不出昨天的行为,你无法判断变化来自模型、数据还是编排。

第三层:把副作用当一等公民

对支付、发信、删库、部署等动作,Tool Span 至少要记录幂等键、权限主体、目标资源、请求摘要、响应摘要、前后状态引用和补偿动作。普通观测系统常把工具调用当一次 HTTP 请求;AgentOps 系统必须知道它是否改变了世界,以及能否撤销。

第四层:分开执行边与依赖边

执行边可以从编排器自动获得;关键依赖边要由工具适配器和状态层显式埋点。先覆盖高风险路径,不必第一天就推断所有隐式依赖。每条依赖边标注 observeddeclaredinferred,让后续诊断知道证据有多硬。

第五层:让评估与护栏进入同一条 Trace

不要把评估结果放在另一个找不到运行上下文的表里。Evaluation Span 应连接被评估的 Agent、计划、任务或输出,并带上测试用例、评分规则、评估器版本和结果;Guardrail Span 应记录检查目标、策略版本、命中理由以及最终动作:放行、阻断、过滤、降级还是转人工。

这与《什么才是好的 Harness》里的原则相呼应:提示词中的规则只是恳求,运行时护栏才是物理边界。而评测证据页取证强调的模型、评分器、提示配置和数据内容版本,也正是可回放 Agent Trace 的最小复现封条。

三个不能被“全量日志”解决的问题

1. 可观察不等于因果可识别

Trace 能缩小怀疑范围,却不会自动证明根因。两个步骤相关,不代表前者导致后者失败;重试成功,也不一定证明修改正确。根因假设仍要通过对照实验、状态回放、故障注入或最小化复现来验证。

2. 观测本身会产生风险

用户输入、检索文档、工具响应和模型中间文本可能包含个人信息、密钥或商业数据。生产设计必须在采集前确定字段级脱敏、访问控制、保留期限和删除机制。高风险环境宁可记录哈希、类型和受控对象引用,也不要把原始内容复制到新的数据湖。

3. 2024 年的分类学不是行业终稿

AgentOps 原论文的 17 个工具来自 GitHub 与 Google 检索,并把大规模 GitHub 查询限制在相关性排序的前三页;作者也承认工具选择和数据属性可能不完整。更关键的是,这项工作主要提出关系模型与分类模板,尚未通过大规模真实案例验证。后续的 MAST、GRADE 和 AgentDebugX 正是在补它没有回答的问题:失败如何分类、依赖如何表达、根因如何定位、修复如何验证。

因此,最好的用法不是照抄论文中的每个字段,而是把它当作一份架构检查表,再用你的风险模型、业务动作和真实故障持续修订。

收束:上线前问自己八个问题

  1. 一次用户目标能否关联到完整 Trace,而不是散落的 LLM 请求?
  2. 计划、任务、工具、评估和护栏是否有明确的 Span 类型?
  3. 除了“谁调用谁”,是否记录了关键数据和状态依赖?
  4. 模型、提示词、工具、知识、评估器和策略能否回溯到具体版本?
  5. 对外部世界产生副作用的动作,能否审计、幂等、补偿或回滚?
  6. 失败分类能否映射到具体 Span 与依赖边,而不是只给一个总分?
  7. 根因候选是否带证据,并经过重跑或测试验证?
  8. 日志是否遵守最小采集、脱敏、授权和保留期限?

如果其中大半答不上来,你拥有的可能只是“LLM API 监控”,还不是 Agent 可观测性。

Agent 不是天然不可理解。真正的问题是,我们用观察一个函数调用的方式,去观察一个会规划、会使用工具、会改变外部状态、还会与其他 Agent 协作的运行系统。AgentOps 的价值,是把观察单位从“模型请求”提升成“目标驱动的执行图”;MAST 告诉我们该在图里寻找什么失败,GRADE 补上依赖盲区,AgentDebugX 再把证据送入检测、归因、恢复与重跑的闭环。

模型越自主,系统越不能只看最终答案。你不必知道 Agent 的每一个内部念头,但必须知道它依据什么、做了什么、改变了什么,以及谁验证过。


论文索引