给 AI Agent 补可观测性前,我会先用 OpenTelemetry 拆清 span 边界
导语:AI Agent 进入真实业务后,排查问题最怕只剩一段最终回答。用户说结果不对,开发只能翻模型日志、工具日志、检索日志和前端报错,最后仍然很难判断问题来自规划、模型、检索、工具调用还是输出整理。OpenTelemetry 适合先做这条链路的工程底座。它把一次请求抽象成 trace,把请求里的关键阶段拆成 span,再用属性和事件记录上下文,让问题可以沿着一次运行完整回放。

原创示意图:把一次 Agent 运行拆成入口、规划、模型、检索、工具和错误处理等 span 账本。 来源:Codex image generation
先定义一条 trace 的边界
OpenTelemetry 的 tracing 文档把 trace 用来表示一次请求在系统中的路径,span 表示路径上的一个工作单元。放到 AI Agent 里,我会把用户的一次提问或一次后台任务作为 trace 根节点。根节点只记录会话、租户、入口、任务类型、开始时间、结束时间和最终状态,不塞长 prompt,也不塞用户原文。
下面再拆 span:规划阶段一个 span,模型调用一个 span,检索一个 span,每个工具调用一个 span,最终答案合成一个 span。这样排查时能先看哪段耗时异常、哪段失败、哪段被重试,再深入看具体属性。
GenAI 语义约定解决命名漂移
很多团队一开始会自定义字段,例如 modelName、provider、inputTokens、toolName。短期能用,接入多语言 SDK、网关或第三方观测平台后,很容易出现同义字段。OpenTelemetry 的 GenAI semantic conventions 提供了面向生成式 AI 的命名参考,覆盖模型系统、操作名、请求参数、token 使用量、响应状态、工具调用和 agent 相关 span。
我的做法是先按语义约定整理字段,再保留少量业务自定义属性。例如模型调用 span 记录 provider、model、operation、token usage、finish reason;检索 span 记录知识库、topK、过滤条件和返回文档数量;工具调用 span 记录工具名、参数摘要、重试次数和错误类型。敏感正文只存 hash、长度和引用 ID,完整内容放在受控证据库。
数据保留要分层
trace 适合索引和定位,证据库适合保存可审计细节。prompt、用户文件片段、工具返回正文和检索 chunk 不要直接塞进观测系统。我会记录 contentHash、sourceId、chunkVersion、字符数、token 数和脱敏状态,再把原文放进有权限控制和保留周期的存储。这样既能从 trace 追到证据,也能在删除、脱敏和合规审计时找到明确入口。
事件只记录转折点
span 属性适合记录稳定维度,event 适合记录运行中的转折。比如 agent 选定工具、检索命中为空、模型返回结构化校验失败、工具超时后进入降级路径,这些都值得写成 event。不要把每一行流式输出都写入 trace,否则查询会变慢,费用也会失控。
我会给事件做三类命名:decision 表示策略选择,fallback 表示降级,validation 表示格式或安全检查。事件里只放可索引摘要,例如规则 ID、候选数量、错误码和证据 ID。真正排查时,trace 负责带路,证据库负责看细节。
上线顺序要克制
第一周先接入口 trace 和模型 span,确认 traceId 能贯穿前端、后端、队列和模型网关。第二周补检索与工具 span,重点看错误分类和耗时分布。第三周再加 GenAI 事件和业务证据引用,把失败样例接到回归测试。
这条路径的核心收益是让 AI 应用从黑盒回答变成可复盘链路。以后模型换了、prompt 改了、工具多了、检索策略升级了,团队仍然能沿着同一条 trace 判断变化发生在哪里,失败被谁处理,证据是否足够继续放量。