资讯中心

AI Agent 工程实践(17):Agent 为什么需要可观测性(Observability)?

📅 2026/7/24 8:04:35
AI Agent 工程实践(17):Agent 为什么需要可观测性(Observability)?
发布时间2026-07-12标签AI AgentLLMObservability可观测性工程实践系列导航上一篇AI Agent 工程实践16Agent 为什么需要状态State下一篇 AI Agent 工程实践18Agent 如何做 Benchmark本文是 [AI Agent 工程实践] 系列的第 17 篇第二季 · 工程实现。Agent 上线第二周用户投诉答案不对。我去查日志发现 Agent 调了三个 Tool、做了五次 LLM 推理、中间还重试了两回——但没有任何记录告诉我到底是哪个环节出了错。是 Prompt 写偏了是 LLM 幻觉了是 Tool 返回了脏数据是重试时状态乱了完全不知道。像一个病人说我不舒服但没有体温计、没有血常规、没有 CT——你只知道他病了不知道病在哪。那一刻我意识到Agent 缺了最后一道防线Observability。没有它Agent 就是一个黑箱——你只知道它做错了不知道它为什么做错。这一篇把黑箱切开。本文你将学到✓ 为什么 Agent 的 Observability 和传统后端完全不同——不是日志就够了✓ 四个被忽视的核心概念Trail留痕/ Audit审计/ Trace追踪/ Benchmark评测✓ 完整观测链路Prompt → LLM → Tool → Latency → Trace → Metrics✓ 一个可落地的 Agent 观测数据模型——直接套用到项目里适合阅读✓ Agent 上线后发现出了错不知道谁的责任的人✓ 用 LangSmith / LangFuse / Arize 但不确定该记什么的开发者✓ 意识到Agent 不只是调 LLM——它是多步推理 多工具调用的复杂系统的人问题背景Agent 的调试比传统后端难一个数量级。传统后端出问题时你查一条 SQL、看一个函数的出入参基本能定位。Agent 出错时你的排查链路可能是到底是哪一步错了Agent 跑了五步——Planning → Tool A 调用 → LLM 推理 → Tool B 调用 → Review。最后答案不对但每一步单独看都没大毛病。问题出在步骤之间的组合效应单步日志看不出来。是 LLM 的问题还是 Tool 的问题LLM 返回了正确的函数调用但 Tool 返回了过期数据导致推理偏差——责任在 Tool但表象是 LLM胡说了。没有 Trace 串起来你会调错方向。为什么同样的输入这次对了上次错了不是灵异事件——是中间某个 Tool 的返回变了一点点导致了蝴蝶效应。没有 Benchmark 做回归对比你永远发现不了。用户的数据隐私有没有被泄漏给 LLM审计合规问题——你的 Agent 把用户的 PII 传给了一个第三方 Tool。没有 Audit Trail你连有没有泄漏都不知道。一句话Agent 不是单步函数调用是多步推理 多工具调用的复杂系统。你不能只观测最后结果对不对——你要观测每一步、每个环节、每条决策链路。错误尝试第一次只记最终输出上线后只记录了用户问了什么、Agent 回了什么。觉得中间过程不重要。结果出错时完全不知道怎么排查——只知道答案错了不知道为什么错。观测最终输出 只看了电影的最后一帧却想搞清楚整个剧情。第二次把 Agent 当普通 Web 服务打日志照搬后端那套——每个 Tool 调用前后打一条INFO日志每条 LLM 请求记一次。结果日志很快爆炸——一次复杂任务可能产生 50 条日志。没有 Trace 把它们串起来时50 条分散的日志比 0 条日志更难用。日志量 ≠ 可观测性。没有结构化、没有关联,日志就是噪音。两次尝试指向同一个教训Agent 的可观测性不能靠最终结果太粗也不能靠打散日志太细没关联。需要一个中间层——把每一步串成一条完整的 Trace再在 Trace 上做 Audit 和 Benchmark。关键观察我把Agent 排错的时间和有没有可观测做了对比排错场景无可观测有可观测LLM 幻觉导致错误靠感觉怀疑可能是 LLM 的问题Trace 显示该步 LLM 输出偏离预期Tool 返回脏数据不知道反复调 LLM 试Trace 显示 Tool 返回了过期数据性能瓶颈在哪猜可能是 Tool A 慢Latency Trace 精确到每步耗时新版本比旧版本差在哪靠用户反馈感知Benchmark 回归对比没有可观测性的 Agent 是黑箱——你只知道它做错了不知道它为什么做错。60% 的排错时间耗在定位不是修复。Observability 把定位从小时级降到分钟级。四个概念的精确区别这四个是本文最核心的概念辨析概念回答什么问题数据粒度典型产出Trail留痕谁做了什么事件级审计日志Audit审计为什么做出这个决策决策级决策追溯链Trace追踪经过哪些环节、每步耗时多少请求级调用链 火焰图Benchmark评测这次的质量和以前比怎么样任务级质量分数 回归报告四者不是平行关系是递进关系Trail 是原始数据事件记录→ Audit 在 Trail 上做决策追溯 → Trace 在 Trail 上做性能分析 → Benchmark 在 Trace 和 Trail 上做质量量化。先有 Trail才有后面的一切。最终方案Agent Observability 四件套观测链路Prompt → LLM → Tool → Latency → Trace → Metrics你给的六步链路——每步观测什么清楚每一步观测什么Prompt版本号模板改了不知道排查就是噩梦、参数填充结果LLMinput/output tokens、模型名、temperature、完整的 prompt responseTool工具名、入参、出参、耗时、是否成功Latency每步耗时LLM 推理时间 / Tool 响应时间 / 端到端总时间TraceTrace ID Span ——把上面所有步串成一条完整的调用链Metrics成功率、平均延迟、token 消耗、用户反馈分数Trail Audit决策可追溯# 一个完整的 Trace 数据结构 trace_id: trace_20260712_001 user_id: user_42 task: 查询订单状态并生成报告 spans: - id: span_1 type: llm_call model: claude-sonnet-4-20250514 input_tokens: 1200 output_tokens: 340 latency_ms: 1200 prompt_version: v2.3 - id: span_2 type: tool_call tool: db_query input: { sql: SELECT status FROM orders WHERE id? } output: { status: shipped } latency_ms: 45 - id: span_3 type: llm_call input_tokens: 800 output_tokens: 520 latency_ms: 900 decision_chain: # Audit为什么得出这个结论 - span_1: LLM 决定需要查询订单 - span_2: 查询返回 shipped - span_3: LLM 基于 shipped 生成报告 final_output: 您的订单已于 7 月 10 日发货... benchmark_score: 4.2 # Benchmark这次的质量分数Audit 不是独立系统——它是 Trace 上的一条决策链视图。你不需要额外存审计数据只要 Trace 存得好Audit 是 Trace 的一种查询方式。Trace调用链串联Trace 是 Agent Observability 的骨架——没有 Trace ID所有 Span 是孤岛trace(span_typellm_call) async def llm_invoke(prompt, model): # 自动记录input/output tokens、latency、model return await model.generate(prompt) trace(span_typetool_call) async def tool_execute(tool_name, args): # 自动记录tool_name、args、result、latency result await tools[tool_name](**args) return result所有 Span 在同一个 Trace ID 下自动串起来。出问题时不是翻 50 条分散日志——是查一条 Trace看到完整链路。Benchmark质量可量化Benchmark 回答最核心的问题这次运行的质量和上次比是变好还是变差不是感觉变差了——是上次平均分 4.2、这次 3.8下降了 0.4。Benchmark 不需要复杂——用户反馈评分/、人工抽检分数、自动评测RAGAS 等都可以。架构图 / 流程图Agent Observability 的完整架构关键点Trace Store 是唯一数据源——Audit / Metrics / Benchmark 都是 Trace 的不同查询视图。不额外维护数据只维护一种数据Trace多种用途。代码或配置示例最小可落地的 Trace 记录class AgentTrace: def __init__(self, task_id: str): self.trace_id ftrace_{task_id} self.spans [] self.start_time now() def span(self, span_type: str, **kwargs): 记录一个 Span——自动计时 start now() yield self.spans.append({ type: span_type, latency_ms: (now() - start).ms, **kwargs, }) def to_audit_trail(self) - list: 从 Trace 生成审计链哪些决策导致了最终结果 return [ f{s[type]}: {s.get(summary, )} for s in self.spans if s[type] in (llm_call, tool_call) ]从 Trace 到 Benchmarkdef benchmark_score(trace: AgentTrace, user_rating: int) - float: 综合质量分用户反馈 系统指标 total_latency sum(s[latency_ms] for s in trace.spans) latency_penalty 1.0 if total_latency 5000 else 0.7 # 5s 内不加罚 return user_rating * latency_penalty # 简单加权代码不长但最小可行——有 Trace ID 串联、有 Latency 记录、能从 Trace 生成 Audit Trail、能算出 Benchmark 分数。Observability 不需要一开始就上全套平台——先把这些数据记下来后面怎么用都好说。设计权衡候选方案优点缺点为什么不选只记最终输出零成本无法排查只看最后一帧全量打散日志信息多无关联、噪音大、存储爆炸50条无关联日志比0条更差上全套平台LangSmith等功能全初期重、集成成本高先记数据平台可以后上结构化 Trace 四视图轻量、可演进需设计 Span 结构选择理由先记对数据工具可迭代不一定要上全套观测平台。第一版结构化 Trace → 存数据库 → SQL 查 Audit → Grafana 看 Metrics → 手动 Benchmark。平台可以迭代但 Trace 数据结构一旦设计错了改的代价极高。先想清楚记什么再想用什么记。总结✅ 没有 Observability 的 Agent 是黑箱——你知道错了不知道错在哪。✅ 四个概念递进Trail留痕·原始数据→ Audit审计·决策追溯→ Trace追踪·性能链路→ Benchmark评测·质量量化。✅ 完整观测链路Prompt → LLM → Tool → Latency → Trace → Metrics每步观测什么从第一天就该明确。✅ Trace Store 是唯一数据源——Audit / Metrics / Benchmark 都是 Trace 的不同查询视图。✅ 先记对数据再选工具——Trace 数据结构设计错了后面的一切都是错的。参考资料LangSmith / LangFuse 文档→ Agent 追踪与审计的工程实现参考OpenTelemetry→ 分布式追踪标准Agent Trace 的概念参照第 16 篇Agent State→ State 的 history 是可观测性的第一步第 04 篇Review 复盘机制→ Review 需要数据Observability 提供数据第 15 篇RAG 知识治理→ Evaluate 闭环依赖 Benchmark 数据系列导航上一篇AI Agent 工程实践16Agent 为什么需要状态State下一篇 AI Agent 工程实践18Agent 如何做 Benchmark本文是 [AI Agent 工程实践] 系列的第 17 篇第二季 · 工程实现。