<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>LangFuse on AI博士 万戈</title>
        <link>https://www.yesmiracle.net/tags/langfuse/</link>
        <description>AI博士万戈的技术博客，聚焦 Agentic AI、AI Infra 与 Agent Security，分享 AI 基础设施与工程落地实践。</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <managingEditor>admin@yesmiracle.net (万戈)</managingEditor>
        <webMaster>admin@yesmiracle.net (万戈)</webMaster>
        <lastBuildDate>Tue, 22 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.yesmiracle.net/tags/langfuse/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Agent 可观测性：从日志到 Trace 的全链路监控</title>
        <link>https://www.yesmiracle.net/post/20260922-engineering-07-agent-observability/</link>
        <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
        <author>admin@yesmiracle.net (万戈)</author>
        <guid>https://www.yesmiracle.net/post/20260922-engineering-07-agent-observability/</guid>
        <description>&lt;img src="https://www.yesmiracle.net/post/20260922-engineering-07-agent-observability/cover.svg" alt="Featured image of post Agent 可观测性：从日志到 Trace 的全链路监控" /&gt;&lt;p&gt;你上线了一个 Agent。它调用 3 个工具、跟用户聊 5 轮、搜了 2 次知识库——然后突然开始胡言乱语。你翻日志，看到的是 3 行 &lt;code&gt;INFO: tool executed&lt;/code&gt; 和 1 行 &lt;code&gt;ERROR: LLM returned unexpected response&lt;/code&gt;。但你不知道：是哪次调用出了问题？是 LLM 抽风了，还是工具返回了错误数据？用户说了什么触发性的词？下一次它还会这样吗？&lt;/p&gt;
&lt;p&gt;传统监控告诉你「出事了」，但 Agent 监控需要告诉你&lt;strong&gt;为什么出事、在哪出事、还会不会出事&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这篇文章是 &lt;strong&gt;AI Agent 工程实战系列&lt;/strong&gt;的第七篇，前面六篇分别讲了 &lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260910-engineering-01-rag-retrieval-precision/&#34; &gt;RAG 检索精度提升&lt;/a&gt;、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260912-engineering-02-agent-memory-system/&#34; &gt;Agent 记忆系统设计&lt;/a&gt;、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260914-engineering-03-tool-calling-reliability/&#34; &gt;Tool Calling 可靠性与容错&lt;/a&gt;、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260916-engineering-04-agent-inference-latency/&#34; &gt;推理延迟优化&lt;/a&gt;、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260918-engineering-05-agent-state-persistence/&#34; &gt;状态管理与持久化&lt;/a&gt;、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260920-engineering-06-multi-agent-orchestration/&#34; &gt;多 Agent 编排模式&lt;/a&gt;。这一篇讲 Agent 可观测性——把 APM 那一套完整迁移到 Agent 场景。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;📌 本系列：一、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260910-engineering-01-rag-retrieval-precision/&#34; &gt;RAG 检索精度提升实战&lt;/a&gt; → 二、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260912-engineering-02-agent-memory-system/&#34; &gt;Agent 记忆系统设计&lt;/a&gt; → 三、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260914-engineering-03-tool-calling-reliability/&#34; &gt;Tool Calling 可靠性与容错&lt;/a&gt; → 四、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260916-engineering-04-agent-inference-latency/&#34; &gt;推理延迟优化&lt;/a&gt; → 五、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260918-engineering-05-agent-state-persistence/&#34; &gt;状态管理与持久化&lt;/a&gt; → 六、&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20260920-engineering-06-multi-agent-orchestration/&#34; &gt;多 Agent 编排模式&lt;/a&gt; → &lt;strong&gt;七、Agent 可观测性（本篇）&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一agent-可观测性为什么不是往日志里多写几行&#34;&gt;一、Agent 可观测性为什么不是「往日志里多写几行」&lt;/h2&gt;
&lt;p&gt;先看一个真实例子。你的 Agent 运行这样一个流程：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;用户提问 → LLM 决定调 API_A → API_A 返回 → LLM 分析结果 → 决定调 API_B → 调知识库 → 生成最终回答
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;传统做法：每个环节记一行日志。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[10:00:01] 用户输入: &amp;#34;查一下 Q3 销售数据和竞争对手动态&amp;#34;
[10:00:05] 调用 API_A: sales_api
[10:00:08] 返回: {data: [...]}
[10:00:10] 调用 API_B: competitor_api
[10:00:14] 返回: {data: [...]}
[10:00:16] 调用知识库: retriever
[10:00:18] 返回: chunks * 3
[10:00:22] 生成回答（200 tokens）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这堆日志回答不了四个关键问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;因果关系&lt;/strong&gt;：LLM 为什么决定调 API_A 而不是 API_C？日志里没有 LLM 的推理链。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;延迟归属&lt;/strong&gt;：总耗时 21 秒，知识库调用占了 4 秒——但这是网络延迟还是 LLM 响应慢？日志只有开始结束，没有内部阶段。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上下文传递&lt;/strong&gt;：API_B 的参数是 LLM 根据 API_A 的结果动态决定的——如果错了，是 API_A 的数据质量有问题，还是 LLM 推理错了？日志里的独立条目看不出依赖链。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;非确定性路径&lt;/strong&gt;：同一输入运行两次，可能一次走了 3 个工具、一次走了 5 个。日志的行数变了，但你不知道哪条路径是「异常」的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Agent 可观测性的核心差异&lt;/strong&gt;就在这里：传统 APM 监控的是&lt;strong&gt;已知路径上的性能&lt;/strong&gt;，Agent 监控的是&lt;strong&gt;未知路径上的行为&lt;/strong&gt;。你不知道 Agent 下一步会调用什么工具，所以你不能预先埋好监控点——你需要在运行时动态捕获每一跳（hop）。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二opentelemetry--genai-semantic-conventions打-trace-的正确姿势&#34;&gt;二、OpenTelemetry + GenAI Semantic Conventions：打 Trace 的正确姿势&lt;/h2&gt;
&lt;p&gt;要解决上述问题，你需要把 Agent 的每一次决策、每一个工具调用、每一次 LLM 请求都建模为 &lt;strong&gt;Span（跨度）&lt;/strong&gt;——带 Parent-Child 关系、带属性、带时间线的一组结构化事件。&lt;/p&gt;
&lt;h3 id=&#34;21-span-设计agent-就是你的-application&#34;&gt;2.1 Span 设计：Agent 就是你的 Application&lt;/h3&gt;
&lt;p&gt;把 Agent 看作一个分布式系统，每次用户请求就是一个 &lt;strong&gt;Trace&lt;/strong&gt;。Trace 内部的 Span 按层级组织：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Trace: user-session-abc123
├── Span: agent.run                         # Root Span — 整个请求生命周期
│   ├── Span: llm.invoke                    # LLM 调用（第一次：决定用什么工具）
│   │   ├── Span: gen_ai.choice             # LLM 决定调用 tool_A
│   │   └── Span: gen_ai.response           # LLM 原始输出
│   ├── Span: tool.invoke                   # 工具调用
│   │   ├── Span: tool_A.execute            # 实际执行
│   │   │   ├── Span: http.request          # HTTP 请求细节
│   │   │   └── Span: tool_A.parse          # 结果解析
│   │   └── Span: tool_A.result_analysis    # LLM 分析工具返回结果
│   ├── Span: llm.invoke                    # LLM 调用（第二次：根据结果决定下一步）
│   │   └── Span: gen_ai.choice             # 决定调 tool_B
│   ├── Span: tool.invoke
│   │   └── Span: tool_B.execute
│   ├── Span: retriever.invoke              # 知识库检索
│   │   └── Span: vector_search.query
│   ├── Span: llm.invoke                    # LLM 调用（第三次：生成最终回复）
│   │   └── Span: gen_ai.response
│   └── Span: agent.output                  # 输出给用户
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这个 Span 树回答了所有问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;谁调了谁？&lt;/strong&gt; — Parent-Child 关系天然表达&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;哪里慢了？&lt;/strong&gt; — 每个 Span 有开始/结束时间&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;为什么选这个工具？&lt;/strong&gt; — &lt;code&gt;gen_ai.choice&lt;/code&gt; Span 记录了 LLM 的 raw_output&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上下文怎么传的？&lt;/strong&gt; — 通过 Span 的 &lt;code&gt;attributes&lt;/code&gt; 标注输入输出&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;22-opentelemetry-genai-属性标准化&#34;&gt;2.2 OpenTelemetry GenAI 属性标准化&lt;/h3&gt;
&lt;p&gt;2026 年 5 月，OpenTelemetry 在 v1.37+ 中正式推出了 &lt;strong&gt;GenAI Semantic Conventions&lt;/strong&gt;（目前已接近稳定）。这套标准定义了 Agent/LLM 场景的关键属性：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; opentelemetry &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; trace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; opentelemetry.semconv.ai &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; GenAiAttributes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tracer &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; trace&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get_tracer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent-runtime&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; tracer&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start_as_current_span(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;llm.invoke&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; span:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.request.model&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gpt-5.6&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.request.max_tokens&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.response.token_count&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;847&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.response.completion_tokens&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;612&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.tool.name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sales_api&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.tool.type&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;function&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.agent.id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;assistant-v3&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.agent.turn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关键属性包括：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;属性名&lt;/th&gt;
          &lt;th&gt;类型&lt;/th&gt;
          &lt;th&gt;用途&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.request.model&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;模型名称&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.request.max_tokens&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;int&lt;/td&gt;
          &lt;td&gt;最大 token 限制&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.response.token_count&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;int&lt;/td&gt;
          &lt;td&gt;总 token 用量&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.response.completion_tokens&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;int&lt;/td&gt;
          &lt;td&gt;输出 token 数&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.tool.name&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;工具名称&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.tool.type&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;工具类型（function/mcp/retriever）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.agent.id&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;Agent 标识&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.agent.turn&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;int&lt;/td&gt;
          &lt;td&gt;对话轮次&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.choice.id&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;LLM 选择的 tool call ID&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.choice.reasoning&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;LLM 的推理过程（可选）&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;23-三种-trace-方案对比&#34;&gt;2.3 三种 Trace 方案对比&lt;/h3&gt;
&lt;p&gt;目前主流的 Agent Trace 方案有三类：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;维度&lt;/th&gt;
          &lt;th&gt;LangFuse&lt;/th&gt;
          &lt;th&gt;Arize Phoenix&lt;/th&gt;
          &lt;th&gt;traceAI (Future AGI)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;协议&lt;/td&gt;
          &lt;td&gt;MIT&lt;/td&gt;
          &lt;td&gt;开源&lt;/td&gt;
          &lt;td&gt;Apache 2.0&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;GitHub ⭐&lt;/td&gt;
          &lt;td&gt;19K+&lt;/td&gt;
          &lt;td&gt;10K+&lt;/td&gt;
          &lt;td&gt;~800&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;核心架构&lt;/td&gt;
          &lt;td&gt;Observation 中心（V4）&lt;/td&gt;
          &lt;td&gt;OTel 原生（OpenInference）&lt;/td&gt;
          &lt;td&gt;轻量 instrumentation 库&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Trace 存储&lt;/td&gt;
          &lt;td&gt;内置（PostgreSQL）&lt;/td&gt;
          &lt;td&gt;内置（可挂接外部 backend）&lt;/td&gt;
          &lt;td&gt;不自带存储，推 OTel Collector&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;查询速度&lt;/td&gt;
          &lt;td&gt;V4 提升 10x（cursor 分页）&lt;/td&gt;
          &lt;td&gt;中等&lt;/td&gt;
          &lt;td&gt;依赖 backend&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;跨 Agent Trace&lt;/td&gt;
          &lt;td&gt;间接支持（Session）&lt;/td&gt;
          &lt;td&gt;通过 OTel Context&lt;/td&gt;
          &lt;td&gt;原生支持（跨边界 span）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;离线审计&lt;/td&gt;
          &lt;td&gt;支持（Export）&lt;/td&gt;
          &lt;td&gt;支持（Parquet）&lt;/td&gt;
          &lt;td&gt;支持（OTel 原生）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;自建可行&lt;/td&gt;
          &lt;td&gt;✅ 中等（PostgreSQL）&lt;/td&gt;
          &lt;td&gt;✅ 简单（复用 OTel infra）&lt;/td&gt;
          &lt;td&gt;✅ 灵活（只关心中间格式）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;学习曲线&lt;/td&gt;
          &lt;td&gt;低&lt;/td&gt;
          &lt;td&gt;中（需 OTel 基础）&lt;/td&gt;
          &lt;td&gt;中（纯 instrumentation）&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;选型建议&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;已有 OTel 基础设施 → &lt;strong&gt;Arize Phoenix&lt;/strong&gt;（最干净的集成路径）&lt;/li&gt;
&lt;li&gt;多 Agent 跨边界追踪 → &lt;strong&gt;traceAI&lt;/strong&gt;（原生跨 Agent span）&lt;/li&gt;
&lt;li&gt;想要独立可视化 + 查询 → &lt;strong&gt;LangFuse&lt;/strong&gt;（最成熟的开源 UI）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三tool-calling-trace-实战一个完整例子&#34;&gt;三、Tool Calling Trace 实战：一个完整例子&lt;/h2&gt;
&lt;p&gt;纸上谈兵够了，让我们看一个真实的 Trace 设计。假设你的 Agent 执行以下工作流：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;用户: &amp;#34;查一下我们最大的三个客户是谁，然后看看他们最近一周的订单状态&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Agent 收到请求后，需要：调用 CRM 接口获取客户排名 → 调用订单系统获取订单状态 → 调用知识库了解合同条款 → 汇总成报告。&lt;/p&gt;
&lt;h3 id=&#34;31-代码实现&#34;&gt;3.1 代码实现&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; opentelemetry &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; trace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; opentelemetry.propagate &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; inject
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; json&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; time
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tracer &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; trace&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get_tracer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent-runtime&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tracer_provider &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; trace&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get_tracer_provider()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handle_user_request&lt;/span&gt;(user_input: str, session_id: str):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Agent 入口：处理用户请求&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; tracer&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start_as_current_span(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent.run&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        attributes&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;session.id&amp;#34;&lt;/span&gt;: session_id,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent.name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;customer-support-agent&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent.version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;3.2.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; root_span:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 第一步：LLM 分析用户意图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools_to_call &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; llm_analyze_intent(user_input)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; tool_name, params &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; tools_to_call:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;# 每个工具调用是一个子 Span&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; tracer&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start_as_current_span(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool.invoke.&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;tool_name&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                attributes&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.tool.name&amp;#34;&lt;/span&gt;: tool_name,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.tool.type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;function&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool.params&amp;#34;&lt;/span&gt;: json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;dumps(params)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; tool_span:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; tool_name &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;crm_top_customers&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; crm_top_customers(params)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    tool_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool.result.count&amp;#34;&lt;/span&gt;, len(result))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#75715e&#34;&gt;# 工具的 HTTP 调用作为孙 Span&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; tracer&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start_as_current_span(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http.request&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; http_span:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        http_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http.method&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        http_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http.url&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://crm.internal/api/top-customers&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        http_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http.status_code&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;elif&lt;/span&gt; tool_name &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;order_status&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; order_status(params)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    tool_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool.result.orders&amp;#34;&lt;/span&gt;, len(result))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;elif&lt;/span&gt; tool_name &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;contract_search&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; tracer&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start_as_current_span(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vector_search.query&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; query_span:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        query_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;retriever.top_k&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        query_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;retriever.score_threshold&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0.7&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; vector_search(params)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 最终 LLM 生成回答&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; tracer&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start_as_current_span(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;llm.final_response&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; final_span:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; llm_generate(tools_to_call, result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            final_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.response.token_count&amp;#34;&lt;/span&gt;, response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;token_count)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            final_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gen_ai.response.finish_reason&amp;#34;&lt;/span&gt;, response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;finish_reason)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        root_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent.total_tools&amp;#34;&lt;/span&gt;, len(tools_to_call))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        root_span&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_attribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent.total_latency_ms&amp;#34;&lt;/span&gt;, int(time&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;time() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; start_ms))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;32-span-属性最佳实践&#34;&gt;3.2 Span 属性最佳实践&lt;/h3&gt;
&lt;p&gt;每个 Span 应该记录以下四类属性：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;类别&lt;/th&gt;
          &lt;th&gt;属性&lt;/th&gt;
          &lt;th&gt;示例&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;身份&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;gen_ai.agent.id&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;customer-support-v3&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;session.id&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;sess_abc123&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;trace.id&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;OTel 自动生成&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;环境&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;deployment.environment&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;production&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;service.version&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;3.2.0&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;host.id&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;pod-7a8b&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;输入/输出&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;tool.params&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;{&amp;quot;limit&amp;quot;: 5}&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;tool.result.count&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;llm.response.content&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;摘要（或 hash）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;性能&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;tool.latency_ms&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;1204&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;llm.tokens.input&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;1523&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;llm.tokens.output&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;612&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;llm.ttft_ms&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;420&lt;/code&gt;（首个 token 延迟）&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;33-存储开销-benchmark&#34;&gt;3.3 存储开销 Benchmark&lt;/h3&gt;
&lt;p&gt;Trace 数据量是个现实问题。我们做了个压力测试：一个 Agent 处理一次用户请求平均产生 15-25 个 Span。如果每天 10,000 次请求：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;场景&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;Span/请求&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;每日 Span 数&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;存储（未压缩）&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;存储（压缩 5:1）&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;简单 QA（1-2 工具）&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;8-12&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~100K&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~800 MB&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~160 MB&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;复杂推理（3-5 工具）&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;15-25&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~200K&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~1.6 GB&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~320 MB&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;多 Agent 协作&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;30-60&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~500K&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~4 GB&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;~800 MB&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;关键发现&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单日 1 万请求在高复杂度场景下产生 4 GB 原始 Trace 数据——&lt;strong&gt;这比传统 API 网关的日志量少一个数量级&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gen_ai.choice.reasoning&lt;/code&gt;（LLM 推理过程）是最大的存储贡献者——一个 reasoning 字段可达 500-2000 token&lt;/li&gt;
&lt;li&gt;建议生产环境对 reasoning 做 &lt;strong&gt;采样存储&lt;/strong&gt;（如 1:10 采样率），或存储 hash + 全量存冷存储&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四llm-调用监控langfuse--langsmith-集成&#34;&gt;四、LLM 调用监控：LangFuse / LangSmith 集成&lt;/h2&gt;
&lt;p&gt;Trace 解决了「发生了什么」，但 Agent 场景还有另一个维度——&lt;strong&gt;LLM 调用质量和 token 消耗&lt;/strong&gt;。这是 LangFuse / LangSmith 这类平台擅长的事。&lt;/p&gt;
&lt;h3 id=&#34;41-langfuse-集成&#34;&gt;4.1 LangFuse 集成&lt;/h3&gt;
&lt;p&gt;LangFuse V4（2026 年 3 月发布）引入了 Observation 中心架构，让集成更灵活：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; langfuse &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; Langfuse
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; langfuse.decorators &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; observe, langfuse_context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;langfuse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Langfuse(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public_key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pk-...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    secret_key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sk-...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    host&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://cloud.langfuse.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@observe&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;agent_process&lt;/span&gt;(user_input: str):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# LangFuse 自动捕获 LLM 调用、token、延迟&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    langfuse_context&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;update_current_observation(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        input&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;user_input,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        session_id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sess_abc123&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        metadata&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;agent_version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;3.2.0&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# LLM 调用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; openai&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chat&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;completions&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;create(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        model&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gpt-5.6&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        messages&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# 手动标记 token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    langfuse_context&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;score_current_observation(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;response_quality&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;,  &lt;span style=&#34;color:#75715e&#34;&gt;# 人工评分或自动评分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        comment&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;正确回答了客户问题&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查询 token 消耗&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;traces &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; langfuse&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fetch_traces(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    session_id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sess_abc123&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; traces:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Total tokens: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;t&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;total_tokens&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Cost: $&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;t&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;total_cost&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.4f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键能力&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;自动捕获&lt;/strong&gt;：&lt;code&gt;@observe()&lt;/code&gt; 装饰器自动拦截 LLM 请求和响应&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session 回放&lt;/strong&gt;：按 session_id 聚合所有 trace，回放完整对话&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Token 消耗追踪&lt;/strong&gt;：按模型、按 session、按时间聚合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工/自动评分&lt;/strong&gt;：给每条 trace 打质量分，用于后续分析和模型调优&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;42-langsmith-集成侧重评估&#34;&gt;4.2 LangSmith 集成（侧重评估）&lt;/h3&gt;
&lt;p&gt;LangSmith 与 LangFuse 定位不同——它更侧重&lt;strong&gt;评估和回归测试&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; langsmith &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; Client, traceable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;client &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Client()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@traceable&lt;/span&gt;(run_type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chain&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;agent_chain&lt;/span&gt;(user_input: str):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# LangSmith 的 trace 自动记录每一步&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    intent &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; analyze_intent(user_input)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; execute_tools(intent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 运行评估&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; client&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;evaluate(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dataset_id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;customer-support-dataset&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[agent_chain],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    evaluators&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[response_correctness, hallucination_check]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;LangFuse vs LangSmith 选型&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;维度&lt;/th&gt;
          &lt;th&gt;LangFuse&lt;/th&gt;
          &lt;th&gt;LangSmith&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;核心场景&lt;/td&gt;
          &lt;td&gt;生产监控 + Token 追踪&lt;/td&gt;
          &lt;td&gt;评估 + 回归测试&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;自建成本&lt;/td&gt;
          &lt;td&gt;中等（开源版自托管）&lt;/td&gt;
          &lt;td&gt;高（主要 SaaS）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;离线审计&lt;/td&gt;
          &lt;td&gt;支持导出&lt;/td&gt;
          &lt;td&gt;有限&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;集成复杂度&lt;/td&gt;
          &lt;td&gt;低（装饰器模式）&lt;/td&gt;
          &lt;td&gt;中（需 LangChain 生态）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;谁用&lt;/td&gt;
          &lt;td&gt;SRE / 运维&lt;/td&gt;
          &lt;td&gt;ML 工程师&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;我的建议&lt;/strong&gt;：两个都用。LangFuse 跑生产监控，LangSmith 跑上线前的回归评估。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五agent-行为基线建模&#34;&gt;五、Agent 行为基线建模&lt;/h2&gt;
&lt;p&gt;这是 Agent 可观测性最被忽视的部分。你有了 Trace、有了 LLM 监控——但你怎么知道「今天这个 Agent 的表现是正常的」？&lt;/p&gt;
&lt;p&gt;答案：&lt;strong&gt;基线建模&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;51-什么是-agent-行为基线&#34;&gt;5.1 什么是 Agent 行为基线&lt;/h3&gt;
&lt;p&gt;基线是一套统计学指标，描述 Agent 在「正常」状态下的行为模式。一旦偏离基线，就是告警信号。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心指标&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;指标&lt;/th&gt;
          &lt;th&gt;定义&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;正常范围（示例）&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;异常信号&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Tool 调用频率&lt;/td&gt;
          &lt;td&gt;每次请求调用的工具数&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;2-4 次&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;8 次（绕圈子）或 0 次（LLM 拒绝调用）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Tool 调用延迟 P50&lt;/td&gt;
          &lt;td&gt;单工具响应的中位数延迟&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;lt;500ms&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;2s（服务降级）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Tool 调用延迟 P99&lt;/td&gt;
          &lt;td&gt;单工具响应的 99 分位延迟&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;lt;3s&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;10s（超时临界）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;LLM 首个 token 延迟&lt;/td&gt;
          &lt;td&gt;TTFT&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;lt;800ms&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;3s（模型拥塞）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;错误率&lt;/td&gt;
          &lt;td&gt;工具调用失败占比&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;lt;2%&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;10%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Choice 切换率&lt;/td&gt;
          &lt;td&gt;LLM 改变主意的频率&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;0-1 次/请求&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;3 次（不确定性过高）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;回答长度&lt;/td&gt;
          &lt;td&gt;最终回复 token 数&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;200-800&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;2000（啰嗦）或 &amp;lt;20（拒绝回答）&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Tool 调用链深度&lt;/td&gt;
          &lt;td&gt;Agent 调用栈深度&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;1-3 层&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&amp;gt;5 层（循环/级联）&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;52-建立基线的工程方法&#34;&gt;5.2 建立基线的工程方法&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;第一阶段：积累期（前 1000 次请求）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;只记录不告警。用滑动窗口计算每日均值：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; statistics
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; collections &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; deque
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AgentBaseline&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; __init__(self, window_size: int &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;window_size &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; window_size
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tool_count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; deque(maxlen&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;window_size)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;latency_p50 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; deque(maxlen&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;window_size)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;error_rate &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; deque(maxlen&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;window_size)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chain_depth &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; deque(maxlen&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;window_size)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;record&lt;/span&gt;(self, trace_data: dict):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tool_count&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(trace_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_count&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;latency_p50&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(trace_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latency_ms&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;error_rate&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(trace_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;has_error&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chain_depth&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(trace_data&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chain_depth&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;get_baseline&lt;/span&gt;(self) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; dict:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_count_avg&amp;#34;&lt;/span&gt;: statistics&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;mean(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tool_count),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_count_std&amp;#34;&lt;/span&gt;: statistics&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;stdev(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tool_count),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latency_p50&amp;#34;&lt;/span&gt;: statistics&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;median(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;latency_p50),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;error_rate&amp;#34;&lt;/span&gt;: sum(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;error_rate) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; len(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;error_rate),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chain_depth_p95&amp;#34;&lt;/span&gt;: sorted(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chain_depth)[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                int(len(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;chain_depth) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.95&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;is_anomalous&lt;/span&gt;(self, trace: dict) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; bool:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bl &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get_baseline()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; trace[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_count&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; bl[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_count_avg&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; bl[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_count_std&amp;#34;&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 工具调用数远超正常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; trace[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;error_rate&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; bl[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;error_rate&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; bl[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;error_rate&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.01&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 错误率突增 3 倍&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;第二阶段：稳定期（1000+ 次请求后）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;引入时间序列异常检测。用移动平均 + 标准差控制图（SPC — Statistical Process Control）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; numpy &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; np
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; scipy &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; stats
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SPCAnomalyDetector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; __init__(self, window_hours: int &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;window &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; window_hours
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {}  &lt;span style=&#34;color:#75715e&#34;&gt;# {hour: [tool_call_counts]}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;update&lt;/span&gt;(self, hour: str, tool_calls: int, latency: float):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; hour &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics[hour] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics[hour]&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_calls&amp;#34;&lt;/span&gt;: tool_calls,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latency&amp;#34;&lt;/span&gt;: latency
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;detect&lt;/span&gt;(self, current_hour: str) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; list:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;返回当前小时的所有异常信号&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        alerts &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        recent_hours &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; list(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;keys())[&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt;:]  &lt;span style=&#34;color:#75715e&#34;&gt;# 最近 24h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        all_tool_calls &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        all_latency &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; h &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; recent_hours:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; m &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics[h]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                all_tool_calls&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(m[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_calls&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                all_latency&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(m[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latency&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(all_tool_calls) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; []  &lt;span style=&#34;color:#75715e&#34;&gt;# 数据不足&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# Z-score 异常检测&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        current_data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;hourly_metrics&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(current_hour, [])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; m &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; current_data:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            z_tool &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (m[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tool_calls&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; np&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;mean(all_tool_calls)) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; np&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;std(all_tool_calls)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            z_latency &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (m[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latency&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; np&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;mean(all_latency)) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; np&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;std(all_latency)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; abs(z_tool) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                alerts&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;工具调用数异常（z=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;z_tool&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.1f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;）: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;m[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tool_calls&amp;#39;&lt;/span&gt;]&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; abs(z_latency) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                alerts&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;延迟异常（z=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;z_latency&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.1f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;）: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;m[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;latency&amp;#39;&lt;/span&gt;]&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;ms&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; alerts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;53-行为漂移检测&#34;&gt;5.3 行为漂移检测&lt;/h3&gt;
&lt;p&gt;基线需要定期刷新——因为模型升级、Prompt 变更、工具接口更新都会改变「正常」的定义。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐策略&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;日级基线&lt;/strong&gt;：滚动 7 天窗口，每日凌晨计算&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;版本标记&lt;/strong&gt;：每次 Agent 版本更新后重建基线，旧版本基线保留作为对比&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;漂移触发&lt;/strong&gt;：当连续 3 天的新基线均值偏离旧基线 2σ 以上，标记为行为漂移事件&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六运行时监控-vs-离线审计两个层面&#34;&gt;六、运行时监控 vs 离线审计：两个层面&lt;/h2&gt;
&lt;p&gt;Agent 可观测性有两个截然不同的消费场景，需要不同的工具链。&lt;/p&gt;
&lt;h3 id=&#34;61-运行时监控实时层&#34;&gt;6.1 运行时监控（实时层）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：秒级发现异常、自动恢复、阻断故障扩散&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;典型场景&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLM 返回格式错误 → 自动重试&lt;/li&gt;
&lt;li&gt;工具调用超时 → 降级到缓存&lt;/li&gt;
&lt;li&gt;错误率飙升 → 切换到备用模型&lt;/li&gt;
&lt;li&gt;Token 消耗异常 → 触发预算告警&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;工具链&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus + Alertmanager（指标聚合 + 告警）&lt;/li&gt;
&lt;li&gt;Grafana（实时仪表盘）&lt;/li&gt;
&lt;li&gt;OTel Collector（Span 接收 + 采样）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;关键指标&lt;/strong&gt;（Prometheus 格式）：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-prometheus&#34; data-lang=&#34;prometheus&#34;&gt;# Agent 请求总数
agent_requests_total{agent=&amp;#34;customer-support&amp;#34;, version=&amp;#34;3.2.0&amp;#34;}
# Tool 调用延迟分布
agent_tool_latency_seconds_bucket{tool=&amp;#34;crm_api&amp;#34;, le=&amp;#34;0.1&amp;#34;}
agent_tool_latency_seconds_bucket{tool=&amp;#34;crm_api&amp;#34;, le=&amp;#34;0.5&amp;#34;}
agent_tool_latency_seconds_bucket{tool=&amp;#34;crm_api&amp;#34;, le=&amp;#34;1.0&amp;#34;}
agent_tool_latency_seconds_bucket{tool=&amp;#34;crm_api&amp;#34;, le=&amp;#34;+Inf&amp;#34;}
# LLM token 消耗
agent_llm_tokens_total{model=&amp;#34;gpt-5.6&amp;#34;, type=&amp;#34;input&amp;#34;}
agent_llm_tokens_total{model=&amp;#34;gpt-5.6&amp;#34;, type=&amp;#34;output&amp;#34;}
# Agent 错误率
agent_error_ratio{agent=&amp;#34;customer-support&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;62-离线审计分析层&#34;&gt;6.2 离线审计（分析层）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：回顾性分析、模式发现、合规审计、模型调优&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;典型场景&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;复盘昨天哪些 Agent 请求出了问题&lt;/li&gt;
&lt;li&gt;发现 Tool 调用链的常见模式（最常见的是哪 3 条路径？）&lt;/li&gt;
&lt;li&gt;审计特定用户的所有 Agent 交互记录&lt;/li&gt;
&lt;li&gt;用历史 Trace 生成回归测试集&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;工具链&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ClickHouse（列式存储，适合 Trace 查询）&lt;/li&gt;
&lt;li&gt;Parquet + S3（长期归档）&lt;/li&gt;
&lt;li&gt;Jupyter Notebook + Pandas（分析）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;典型查询&lt;/strong&gt;（ClickHouse）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 找出今天所有「绕圈子」的 Agent 请求
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; session_id, tool_count, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       arrayStringConcat(tool_names, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; -&amp;gt; &amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; tool_chain
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; agent_traces
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; toDate(&lt;span style=&#34;color:#66d9ef&#34;&gt;timestamp&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; today()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; tool_count &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; tool_names[tool_count] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tool_names[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;]  &lt;span style=&#34;color:#75715e&#34;&gt;-- 最后调用的工具和第一个相同
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; tool_count &lt;span style=&#34;color:#66d9ef&#34;&gt;DESC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;63-两级数据流架构&#34;&gt;6.3 两级数据流架构&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;实时层（秒级）  ←  ←  OTel Collector (采样 100%)  ←  ←  Agent Runtime
                    ↓  采样 10% (reasoning 字段)
                    ↓
离线层（小时级） →  →  ClickHouse / S3 Parquet  →  →  Notebook 分析
                    ↓
                    ↓  →  LangFuse / LangSmith（LLM 质量分析）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;关键设计原则&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;采样策略差异化&lt;/strong&gt;：性能指标全量采集，LLM reasoning 字段采样存储&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;热/冷数据分离&lt;/strong&gt;：7 天内热数据（PostgreSQL/ClickHouse），7 天后冷数据（S3 Parquet）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace 与 Metrics 双通道&lt;/strong&gt;：Metrics 给自动化（告警），Trace 给人（Debug）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七告警策略设计从出事了到这里有问题&#34;&gt;七、告警策略设计：从「出事了」到「这里有问题」&lt;/h2&gt;
&lt;p&gt;Agent 告警与普通 APM 告警的最大区别：&lt;strong&gt;很多「异常」不是故障，只是 Agent 走了不同的路径&lt;/strong&gt;。一个 Agent 多调了 2 个工具可能是绕路了，也可能是它发现需要额外的上下文。&lt;/p&gt;
&lt;h3 id=&#34;71-四级告警体系&#34;&gt;7.1 四级告警体系&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;P0 — 完全不可用&lt;/strong&gt;（立即电话/Slack 轮值）&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;条件&lt;/th&gt;
          &lt;th&gt;示例&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;所有请求的 Tool 调用成功率 &amp;lt; 50%&lt;/td&gt;
          &lt;td&gt;依赖 API 全部超时&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;连续 5 分钟无任何成功响应&lt;/td&gt;
          &lt;td&gt;LLM 端点 503&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Agent 输出包含敏感数据泄露特征&lt;/td&gt;
          &lt;td&gt;PII 正则匹配命中&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;工具调用出现非预期的 side effect&lt;/td&gt;
          &lt;td&gt;删除了生产数据&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;P1 — 功能降级&lt;/strong&gt;（5 分钟内响应）&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;条件&lt;/th&gt;
          &lt;th&gt;示例&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;错误率 &amp;gt; 10%（基线 &amp;lt; 2%）&lt;/td&gt;
          &lt;td&gt;工具降级&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;P99 延迟 &amp;gt; 基线 3x&lt;/td&gt;
          &lt;td&gt;模型拥塞&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Tool 调用链深度 &amp;gt; 5&lt;/td&gt;
          &lt;td&gt;Agent 在绕圈子&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Token 消耗 &amp;gt; 日预算的 150%&lt;/td&gt;
          &lt;td&gt;Prompt 膨胀&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;P2 — 行为异常&lt;/strong&gt;（工作时间内响应）&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;条件&lt;/th&gt;
          &lt;th&gt;示例&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Z-score &amp;gt; 3 的单个指标&lt;/td&gt;
          &lt;td&gt;某个用户的行为基线漂移&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Tool 调用频率日环比变化 &amp;gt; 50%&lt;/td&gt;
          &lt;td&gt;Prompt 变更导致行为变化&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;LLM 拒绝率上升 &amp;gt; 5%&lt;/td&gt;
          &lt;td&gt;偏好冲突或护栏误判&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;P3 — 信息性&lt;/strong&gt;（记录，不告警）&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;条件&lt;/th&gt;
          &lt;th&gt;示例&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;模型版本自动切换&lt;/td&gt;
          &lt;td&gt;灰度发布&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;新工具调用模式出现&lt;/td&gt;
          &lt;td&gt;长期行为漂移信号&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Agent 配置变更&lt;/td&gt;
          &lt;td&gt;日志审计&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;72-减少误报的关键设计&#34;&gt;7.2 减少误报的关键设计&lt;/h3&gt;
&lt;p&gt;Agent 告警最怕误报——因为 Agent 本来就「不确定」，天天告警会被忽略。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三个过滤器&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;滑动窗口聚合&lt;/strong&gt;：不基于单次请求告警，而是基于 5 分钟滑动窗口的聚合指标。一个请求走岔了不算异常，连续 10 个请求都岔了才算。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;基线自适应&lt;/strong&gt;：告警阈值不应是固定数字，而是基于基线的动态阈值。如果基线今天变了（如模型升级后 Tool 调用数从 3 增加到 5），告警阈值自动调整。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;行为 vs 性能分离&lt;/strong&gt;：性能告警（延迟、错误率）用固定阈值，行为告警（Tool 选择、链深度）用统计阈值。不要混在一起。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;73-告警响应-runbook&#34;&gt;7.3 告警响应 Runbook&lt;/h3&gt;
&lt;p&gt;每个 P0 告警应附带一个 Trace 链接和预分析：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[P0 ALERT] Agent customer-support 错误率 68%（基线 1.2%）
Session: sess_abc123
Trace: https://traces.internal/trace/abc123def456
预分析:
- 最近 10 个请求全部调用 order_api 失败（HTTP 503）
- 其他 3 个 Agent（billing-support, data-analyst）同样受影响
- 根因推测: 订单服务后端故障
建议动作:
1. 将 Agent 的订单模块降级到缓存模式（命令: ./degrade order_cache）
2. 联系订单服务团队
3. 降级后密切监控错误率（预计 &amp;lt; 3%）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这个 Runbook 应该由告警系统&lt;strong&gt;自动生成&lt;/strong&gt;——从 Trace 数据中提取关键信息填入模板。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;写在最后&#34;&gt;写在最后&lt;/h2&gt;
&lt;p&gt;Agent 可观测性本质上是把分布式系统那一套经验迁移到&lt;strong&gt;非确定性执行&lt;/strong&gt;的场景。Span 是分布式 Trace 那一套，Metrics 是 Prometheus 那一套，基线建模是 SPC 控制图那一套——但 Agent 场景让每一层都有了自己的「Agent 味道」。&lt;/p&gt;
&lt;p&gt;我踩过的三个坑：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;不要等出事了再打 Trace&lt;/strong&gt;。Trace 基础设施应该在 Agent 上线第一天就部署好，因为「上线前的测试」和「生产中的非确定性路径」是两回事。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存了 reasoning 但没人看&lt;/strong&gt;。除非你有专门的 LLM 调试团队，否则在生产环境对 reasoning 做采样存储就够了——全量存只会烧存储，不会提升排查效率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;告警阈值设太死&lt;/strong&gt;。Agent 行为会随着模型升级、Prompt 迭代、工具变更而变化。固定阈值在一周内就会失效，基线必须自动刷新。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这篇暂停在工程层面。说到 Agent 运行时观测，我在做 &lt;a class=&#34;link&#34; href=&#34;https://github.com/eyelessly/clawguard&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ClawGuard&lt;/a&gt; 时最深的体会是：&lt;strong&gt;eBPF 层的无侵入观测和用户态的 Trace 观测应该是互补关系，不是替代关系&lt;/strong&gt;。eBPF 告诉你「网络包长什么样」，Trace 告诉你「Agent 为什么发了这个包」。两者合在一起，才是真正的手中有图、心中不慌。&lt;/p&gt;
&lt;p&gt;下一期：Agent 安全——从 Prompt 注入到供应链攻击的实战防御。这是这个系列的暗线，也该正式展开了。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本系列第七篇。全系列计划约 10 篇覆盖 Agent 工程实战的核心话题。&lt;/em&gt;&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
