AI Agent 工程实践(17):Agent 为什么需要可观测性(Observability)?
发布时间:2026-07-12
标签:AI Agent|LLM|Observability|可观测性|工程实践
系列导航
上一篇:AI Agent 工程实践(16):Agent 为什么需要状态(State)?
下一篇: AI Agent 工程实践(18):Agent 如何做 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:版本号(模板改了不知道,排查就是噩梦)、参数填充结果
- LLM:input/output tokens、模型名、temperature、完整的 prompt + response
- Tool:工具名、入参、出参、耗时、是否成功
- Latency:每步耗时(LLM 推理时间 / Tool 响应时间 / 端到端总时间)
- Trace:Trace 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_type="llm_call") async def llm_invoke(prompt, model): # 自动记录:input/output tokens、latency、model return await model.generate(prompt) @trace(span_type="tool_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 = f"trace_{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 到 Benchmark
def 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 工程实践(16):Agent 为什么需要状态(State)?
下一篇: AI Agent 工程实践(18):Agent 如何做 Benchmark?
本文是 [AI Agent 工程实践] 系列的第 17 篇(第二季 · 工程实现)。
