Skip to content

可观测性

1. 从一个具体翻车场景开始

你收到一条用户反馈:"上周三生成的技术文档,数据来源对不上,而且格式也和我们项目模板不一致。"

你打开系统,找到那份产物。它看起来是完整的:标题正确、段落通顺、引用格式也没问题。但当你顺着任务链路往回查,问题才一件件浮现:

  • 检索阶段召回的是一篇两年前的官方文档。
  • 执行阶段虽然接到了资料卡片,却没有真正使用里面的版本号。
  • 审稿节点通过了格式检查,却漏掉了引用与正文不一致的问题。
  • 交付检查只校验了输出长度,没有核对元数据和模板字段。

这不是一次简单的"模型出错"。任务没有抛异常,每个节点都执行过,但最终产物却不可信。你最大的困难是:中间证据在哪里?

Agent 项目的可观测性要回答的正是这个问题。

2. 为什么 Agent 系统更难排障

传统 Web 应用出错通常有明确症状:接口 500、数据库超时、页面报错。排查可以从错误日志、调用栈和依赖状态开始。

Agent 项目的问题却很少以异常形式出现:

  • 产物生成成功,但资料来源不可靠。
  • 语句通顺,但多个来源被生硬拼接。
  • 审稿通过,但关键事实没有引用。
  • 工具调用成功,但检索结果没有进入结构。
  • Prompt 版本更新后,产物风格开始波动。
  • 交付检查通过,但元数据、内链或结构化数据没有跟产物内容对齐。

这类问题很难靠"重新跑一次"复现。模型输出有随机性,外部资料会更新,任务状态也可能已经从执行推进到交付检查。系统需要在问题发生时记录现场,把每个 Agent 看到的输入、做出的判断、调用过的工具和产出的中间结果留住。

在 Agent 项目里,可观测性要回答的核心问题通常有三类:

  1. 这个产物为什么生成现在这样?
  2. 最近一批产物的质量、延迟或返工率是否发生变化?
  3. 哪些降级路径正在被频繁触发?

3. 三类观测数据

OpenTelemetry 把常见遥测信号分成 Traces、Metrics 和 Logs。套到 Agent 项目里,这三类数据的分工要贴近任务链路。

3.1 Trace:复盘一次任务

Trace 记录一次任务的完整链路。一次任务可以拆成多个 Span:

txt
Trace: agent_task_123
  Span: intake
  Span: research
  Span: source_filter
  Span: plan
  Span: execute
  Span: technical_review
  Span: style_review
  Span: rewrite
  Span: delivery_check

Trace 适合回答:"这个产物为什么变成这样?"

例如一个产物被反馈"引用不可靠",排查时只看最终产物会缺少中间证据。更有价值的是顺着 Trace 看:

  1. research 是否召回了官方资料、论文或项目源码。
  2. source_filter 是否把低可信来源标成了可引用资料。
  3. plan 是否把资料 ID 分配到了对应部分。
  4. execute 是否使用了这些资料,还是只根据通用知识生成产物。
  5. technical_review 是否检查了事实、引用和版本时效性。

Trace 的价值在于把一次任务拆成可检查的节点,让排障从"读最终产物猜原因"变成"沿着任务链路看证据"。

3.2 Metrics:观察整体趋势

Metrics 不保存完整现场,而是抽取数值或比例。Agent 项目里可以优先关注这些指标:

  • 资料召回命中率。
  • 官方来源占比。
  • 每个产物平均引用数。
  • 审稿阻塞率。
  • 每个产物平均改写次数。
  • 交付检查失败率。
  • degraded Span 占比。
  • 从需求提交到交付检查完成的耗时。

Metrics 适合回答:"最近系统整体是否变差?"

单个产物的问题要看 Trace;一批产物的趋势要看 Metrics。比如官方来源占比连续下降,可能意味着检索查询词退化、来源筛选规则过松,或外部搜索工具返回质量变差。

3.3 Logs:记录离散事件

Logs 适合记录不一定属于主链路、但后续需要排查的事件。例如:

  • 某个外部搜索服务返回异常。
  • 某次人工确认被跳过。
  • 某个 Prompt 版本被回滚。
  • 某条资料被管理员标记为不可信。
  • 某个产物被交付后返修。

Logs 是补充信号,可以帮助定位异常事件。只堆日志会带来两个问题:节点之间缺少关联,单个任务的上下文也容易散落在多处。

4. Span 应该记录什么

每个 Span 不能只记录耗时,还要记录足够的业务上下文。Agent 任务里的 Span 至少要能回答四个问题:

  1. 这个节点收到什么输入?
  2. 它做了什么判断?
  3. 它调用了哪些工具或模型?
  4. 它把什么结果交给下一个节点?
Span必要字段
intake用户需求、对象、场景、任务范围、澄清问题、约束条件
research查询词、工具、来源列表、来源类型、失败工具
source_filter可信度、时效性、是否官方来源、排除原因
plan部分标题、每部分问题、引用资料 ID、待验证事实
executePrompt 版本、模型、输入资料 ID、输出长度、低置信度标记
technical_review问题数量、严重级别、事实错误、缺失引用、检查清单版本
style_review风格规则版本、违禁句式、术语不一致、可读性问题
rewrite已处理审稿项、保留的未解决项、改写范围
delivery_check元数据、链接、格式、结构化数据、交付状态

这些字段能让排障从猜测变成定位。用户反馈"这个产物像拼接"时,可以先看 plan.sourceIdsexecute.inputSourceIdsrewrite.resolvedIssues。如果结构引用了多个来源,但产物没有记录部分和资料之间的关系,问题可能出在执行节点;如果审稿已经标出部分衔接问题,但改写节点没有处理,对应问题就落在改写流程。

Span 的 metadata 也要记录版本信息,例如 Prompt 版本、模型名、工具版本、检查清单版本和知识库快照。产物质量的回归经常来自版本切换;没有版本字段,后续只能用发布时间去推断。

5. degraded 状态

Agent 系统里有一类情况没有失败,但质量已经下降:

  • 搜索工具超时,系统只用了历史资料。
  • 官方来源不足,系统使用了二手资料。
  • 论文或官方文档打不开,系统改用摘要页。
  • 审稿工具失败,系统只做了格式检查。
  • 资料冲突没有人工确认,系统生成了保守版本。
  • 主模型超时,系统切到更便宜或上下文更短的模型。

这些情况应该记录为 degraded。它没有中断任务,但需要进入 Trace 和 Metrics。

typescript
type SpanStatus = "ok" | "error" | "degraded";

type TraceSpan = {
  name: string;
  status: SpanStatus;
  durationMs: number;
  degradedReason?: string;
  metadata: Record<string, unknown>;
};

没有 degraded,系统会把"勉强交付"误判为"正常交付"。短期看,任务完成率没有下降;长期看,产物可信度、引用完整性和审稿拦截率会被慢慢拉低。

Agent 项目可以把降级原因拆成更稳定的枚举:

typescript
type DegradedReason =
  | "search_timeout"
  | "insufficient_official_sources"
  | "source_conflict_unresolved"
  | "review_tool_failed"
  | "model_fallback"
  | "token_budget_truncated"
  | "manual_confirmation_skipped";

这样做有两个好处。第一,Metrics 能按原因聚合,定位最常见的质量损耗来源。第二,交付检查可以基于降级原因设置门槛,例如含有 source_conflict_unresolved 的任务必须进入人工确认。

6. 隐私、成本和保留策略

Agent 系统的 Trace 可能包含用户需求、内部资料、Prompt、产物、审稿意见和交付计划。全量明文保存会带来隐私、合规和成本压力。

更稳妥的策略是分层保存:

  • 对产物、资料和审稿意见做摘要化存储。
  • 对敏感字段做脱敏、哈希或权限隔离。
  • 对高频成功任务只保存关键字段和采样完整 Trace。
  • 对失败、降级、人工确认、交付返修任务保留更完整现场。
  • 给 Trace、原始工具结果和产物快照设置不同保留周期。
  • 在 Span metadata 中记录数据保留策略版本,便于后续审计。

可观测性服务于排障、评估和审计,字段设计要避免把系统变成无限保存内容副本的仓库。设计字段时要先区分"排障必须"和"以后可能有用"。后者可以采样或延迟写入,前者要进入主 Trace。

7. 落地检查

给 Agent 项目接入可观测性时,可以先从一条最短链路开始:

  1. 为每个任务生成稳定的 traceId
  2. 为 intake、research、plan、execute、review、rewrite、delivery_check 建立 Span。
  3. 在每个 Span 中记录输入摘要、输出摘要、关键 ID、模型和 Prompt 版本。
  4. 为资料不足、工具失败、模型 fallback、人工确认跳过等情况记录 degradedReason
  5. 把官方来源占比、审稿阻塞率、交付检查失败率和 degraded 占比接入 Metrics。
  6. 为外部工具异常、Prompt 回滚、交付后返修记录 Logs。

这条链路不需要一次覆盖所有细节。先把"产物为什么生成这样"记录下来,再逐步补充指标、日志和保留策略。

8. 小结

Agent 项目的可观测性,核心是把"为什么生成这样"记录下来。

Trace 负责复盘单次任务,Metrics 负责发现整体异常,Logs 负责补充离散事件。每个 Span 都要保留足够的业务上下文:资料、Prompt 版本、任务状态、审稿问题、改写范围和降级原因。线上出现"产物不可信""风格漂移""引用缺失"时,系统才有排查入口。

一句话总结

可观测性不是给 Agent 系统加监控,而是把任务从"黑盒生成"变成"可检查、可复盘、可治理"的过程记录。

基于 MIT 协议开源