<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>AgentOps on Chico's Tech Blog</title><link>https://realtime-ai.chat/tags/agentops/</link><description>Recent content in AgentOps on Chico's Tech Blog</description><image><title>Chico's Tech Blog</title><url>https://github.com/chicogong.png</url><link>https://github.com/chicogong.png</link></image><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 16 May 2026 11:00:00 +0800</lastBuildDate><atom:link href="https://realtime-ai.chat/tags/agentops/index.xml" rel="self" type="application/rss+xml"/><item><title>Agent 上线之后:怎么评估和监控</title><link>https://realtime-ai.chat/posts/agent-evals/</link><pubDate>Sat, 16 May 2026 11:00:00 +0800</pubDate><guid>https://realtime-ai.chat/posts/agent-evals/</guid><description>Agent 难的不是搭出来,是上线后知道它好不好。讲清楚 Agent 该看哪些指标、怎么做离线 eval、在线 trace、人审和 LLM-as-judge 的取舍,以及回归怎么防。</description><content:encoded><![CDATA[<p>用一个下午就能搭出一个像样的 Agent demo。接个大模型、写几个工具、调通 ReAct 循环,跑十条 case,全过。截图发群里,大家鼓掌。</p>
<p>两周后,一个客户在工单里贴出对话记录:你的 Agent 把退款金额算成了原价的三倍,还信誓旦旦地说&quot;已为您处理&quot;。你翻监控面板——CPU 正常、接口 P99 40ms、错误率 0.02%,一片绿。</p>
<p>这就是 Agent 工程里最反直觉的地方:<strong>搭出来是最简单的一步,知道它到底好不好,才是真正的工程</strong>。传统软件你写完测试、跑通 CI,基本就放心了;Agent 不行——它每次的输出都不一样,它&quot;出错&quot;的方式根本不会触发任何异常。这篇讲讲上线之后那部分:看什么指标、怎么评、怎么防回归。</p>
<h2 id="为什么你那套监控不管用">为什么你那套监控不管用</h2>
<p>先说清楚传统监控为什么在这里失灵。</p>
<p>传统软件的故障是<strong>二值</strong>的:要么 200,要么 500;要么返回了,要么超时了。你的告警系统盯着这些信号,出事就响。Agent 的故障是<strong>语义</strong>的:HTTP 200,JSON 合法,字段齐全,延迟正常——内容是错的。Agent 自信地编了一个不存在的退货政策,调了正确的工具但传错了参数,绕了七步才完成一件三步能干完的事。这些在传统监控眼里全是&quot;成功请求&quot;。</p>
<p>更麻烦的是 Agent 是<strong>非确定性</strong>的。同样一句&quot;帮我查下上个月的账单&quot;,今天它走两步给出答案,明天可能走五步还问你要确认。你没法用&quot;输入 X 必然输出 Y&quot;来断言。所以 Agent 的评估,本质上是在做<strong>概率系统的质量管理</strong>——你管的不是单次对错,是一个分布。</p>
<p>还有一层:Agent 是<strong>多步</strong>的。一次任务里,规划器把目标拆成子步骤,工具选择器挑了几个工具,检索器拉了上下文,模型可能还重试了两次,最后才有一个回答。出了问题,你得知道是哪一步坏的。只盯着最终输出,等于只看考试总分不看错题——你知道它考砸了,但不知道为什么。</p>
<pre class="mermaid">flowchart TD
  A[用户请求] --> B[规划<br/>拆解子任务]
  B --> C[工具选择]
  C --> D[工具调用]
  D --> E{结果够了吗}
  E -->|不够| B
  E -->|够了| F[生成回答]
  F --> G[返回用户]
  style B fill:#fde7c2,stroke:#e8b23c
  style C fill:#fde7c2,stroke:#e8b23c
  style D fill:#fde7c2,stroke:#e8b23c
</pre><p>橙色那三块——规划、选工具、调工具——是 Agent 区别于&quot;一次 LLM 调用&quot;的地方,也是大多数故障的发生地。你的可观测性必须能看进这三块,而不只是看进出。</p>
<h2 id="agent-该盯哪几个指标">Agent 该盯哪几个指标</h2>
<p>把指标分成两类:<strong>业务结果</strong>和<strong>过程健康</strong>。前者回答&quot;它有没有把事办成&quot;,后者回答&quot;它办事的姿势对不对&quot;。</p>
<table>
  <thead>
      <tr>
          <th>指标</th>
          <th>它在说什么</th>
          <th>不正常时意味着</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>任务成功率</td>
          <td>用户的目标到底达成了没</td>
          <td>这是北极星,其他指标都为它服务</td>
      </tr>
      <tr>
          <td>步数 / 轮次</td>
          <td>完成一个任务走了几步</td>
          <td>步数飙升 = 规划在打转或工具在失败重试</td>
      </tr>
      <tr>
          <td>工具调用错误率</td>
          <td>工具调用里失败的比例</td>
          <td>区分&quot;参数错&quot;和&quot;工具本身挂了&quot;</td>
      </tr>
      <tr>
          <td>Token 消耗</td>
          <td>单次任务烧掉多少 token</td>
          <td>直接对应成本,也是绕路的信号</td>
      </tr>
      <tr>
          <td>端到端延迟</td>
          <td>用户从发问到拿到结果等了多久</td>
          <td>多步 Agent 的延迟是各步之和,会累</td>
      </tr>
      <tr>
          <td>工具选择准确率</td>
          <td>该用 A 工具时它是不是用了 A</td>
          <td>选错工具,后面全错</td>
      </tr>
  </tbody>
</table>
<p>几个容易踩的点。</p>
<p><strong>任务成功率不能自己定义。</strong> &ldquo;成功&quot;必须从用户视角定:用户想退款,Agent 走完全流程、退款到账才算成功;它礼貌地回了一大段话但没退成,是失败。很多团队把&quot;流程跑完没报错&quot;当成功,这是自欺。</p>
<p><strong>步数和 token 是一对孪生信号。</strong> 它俩一起涨,通常是 Agent 陷进了&quot;调工具—结果不满意—再调&quot;的循环。我习惯给每个任务设一个步数上限(比如 15 步)做硬熔断,然后把&quot;步数分布&quot;画成直方图——你要看的不是平均值,是那条长尾。平均 4 步很健康,但如果有 5% 的任务走到 20 步,那 5% 就是你的成本黑洞和体验灾难。</p>
<p><strong>工具调用错误率要拆开看。</strong> &ldquo;模型给工具传了非法参数&quot;和&quot;工具后端 500 了&quot;是两种完全不同的病:前者是模型的问题,要改 prompt 或工具描述;后者是依赖的问题,要改基础设施。混在一个数字里,你永远不知道该修哪。OpenTelemetry 的 GenAI 语义约定(2026 年仍是 experimental,但已经是事实标准)专门为 <code>execute_tool</code> span 和 <code>error.type</code> 留了字段,就是为了让你能这样拆。</p>
<h2 id="离线评估上线前的单元测试">离线评估:上线前的&quot;单元测试&rdquo;</h2>
<p>离线评估,就是给 Agent 写单元测试。核心是一个 <strong>eval 集</strong>:一批输入,配上你认可的&quot;理想行为&rdquo;。每次改了 prompt、换了模型、调了工具描述,先拿这批 case 跑一遍,看分数有没有掉。</p>
<p>eval 集怎么来,决定了它有没有用。<strong>别凭空想象 case,要从真实流量里捞。</strong> 一个我反复验证的做法:每周翻线上 trace,把失败的、用户追问的、绕路的对话挑出来,清洗成 eval case。你的 eval 集应该是你<strong>踩过的坑的合集</strong>,而不是产品经理拍脑袋写的&quot;理想用户故事&quot;。理想故事永远通过,真实的坑才暴露问题。</p>
<p>Agent 的离线评估比纯 LLM 难,难在要评<strong>轨迹(trajectory)</strong>,不只是评最终答案。Google 的 ADK 把这件事说得很直白:一个 golden case 要同时记两样东西——<strong>理想的工具调用序列</strong>和<strong>理想的最终回答</strong>。于是你能分别打两类分:</p>
<ul>
<li><strong>轨迹分</strong>:它选的工具对不对、顺序合不合理、有没有多余的步骤。轨迹可以严格比对(必须和 golden 完全一致),也可以宽松比对(关键工具调到就行)。</li>
<li><strong>结果分</strong>:最终回答对不对、全不全。</li>
</ul>
<p>为什么要分开?因为一个 Agent 可能&quot;答对了但过程很糟&quot;——瞎试了八个工具碰巧蒙对。这种 case 结果分满分,轨迹分很低。你要是只看结果分,就会把一个脆弱的、纯靠运气的 Agent 当成好 Agent 放上线。</p>
<p>一条实用纪律:<strong>如果你的 eval 集通过率是 100%,那不是你的 Agent 完美,是你的 eval 太简单了。</strong> 健康的 eval 集应该一直留着几条过不了的 case,逼着你持续改进。通过率到顶的那天,就是该往里加硬 case 的那天。</p>
<h2 id="在线观测用-trace-还原现场">在线观测:用 trace 还原现场</h2>
<p>离线评估管&quot;上线前&quot;,在线观测管&quot;上线后&quot;。核心工具是 <strong>trace</strong>——把一次完整任务里的每一步都记下来:每次 LLM 调用的输入输出和 token,每次工具调用的参数和返回,每一步的耗时。出了问题,你能像看录像回放一样把现场还原出来。</p>
<p>观测的粒度分三层,这个分层很关键:</p>
<ul>
<li><strong>Span 级</strong>:单个步骤。定位&quot;哪一步坏了&quot;——是第三次工具调用传错了参数。</li>
<li><strong>Trace 级</strong>:一次完整任务。判断&quot;整件事办成了没&quot;。</li>
<li><strong>Session 级</strong>:跨多轮对话的一整个会话。评估&quot;这个用户这一次来,体验到底如何&quot;。</li>
</ul>
<p>值得提醒的一点:早期那批 observability 工具(Langfuse、LangSmith、Braintrust、W&amp;B Weave)最初都是为&quot;监控 LLM 调用&quot;设计的,后来才扩展去支持 Agent——而它们处理 Agent 的方式,常常是把 Agent 当成&quot;一串 LLM 调用&quot;,而不是当成&quot;一个有目标、有结果的会话&quot;。这个出身决定了你用它们时要多留个心眼:<strong>别让工具默认的视角把你带偏到只看单次调用,你真正要回答的是 trace 级和 session 级的问题。</strong></p>
<p>2026 年这个领域的工具已经分化得比较清楚,选型可以这么看:</p>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>适合谁</th>
          <th>特点</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Langfuse</td>
          <td>想自托管、要开源、在意数据主权</td>
          <td>开源标杆,无按席位收费;2026 年 1 月被 ClickHouse 收购</td>
      </tr>
      <tr>
          <td>LangSmith</td>
          <td>技术栈是 LangChain / LangGraph</td>
          <td>和自家框架咬合最紧,接入几乎零开销</td>
      </tr>
      <tr>
          <td>Braintrust</td>
          <td>重视 eval 工程、要把 eval 卡进 CI</td>
          <td>免费额度大方,CI 门禁工作流最成熟</td>
      </tr>
      <tr>
          <td>Arize Phoenix</td>
          <td>想要开源 + 偏 ML 团队习惯</td>
          <td>基于 OpenTelemetry,可观测性血统正</td>
      </tr>
      <tr>
          <td>AgentOps</td>
          <td>多框架混用、重在调试多 Agent</td>
          <td>多框架 Agent 调试能力强</td>
      </tr>
  </tbody>
</table>
<p>不用纠结选哪个&quot;最好&quot;。务实的选法:<strong>先确认它原生支持 OpenTelemetry GenAI 语义约定</strong>,这样你不会被锁死,以后换工具数据能带走。然后看它的出身和你的技术栈合不合。能自托管、数据敏感就 Langfuse;深度用 LangChain 就 LangSmith;eval 是核心工作流就 Braintrust。</p>
<h2 id="谁来打分人审还是-llm-as-judge">谁来打分:人审还是 LLM-as-judge</h2>
<p>trace 有了,你还得给每条 trace 打分,才知道质量是涨是跌。打分有三种人:规则、人、和另一个大模型。</p>
<p><strong>能用规则就用规则。</strong> 凡是确定性的检查——延迟有没有超标、JSON schema 合不合法、token 有没有爆预算、有没有调到那个必须调的工具——全用代码硬判。规则评估快、不要钱、结果稳定,能用规则的地方绝不要上模型。这是省钱省心的第一原则。</p>
<p><strong>剩下的&quot;质量&quot;问题,人审最准但最贵。</strong> 回答的语气专不专业、有没有答非所问、逻辑通不通——这些目前只有人能可靠地判断。人审是你所有评估的<strong>真相来源(ground truth)</strong>,但你不可能让人审每天几十万条对话。所以人审的正确用法是<strong>抽样</strong>:每天抽一两百条,尤其抽那些自动评估打了低分或者落在边界上的。</p>
<p><strong>规模化只能靠 LLM-as-judge</strong>——用一个大模型当裁判,按 rubric 给另一个 Agent 的输出打分。但这东西用不好就是自我安慰,几条铁律:</p>
<ol>
<li><strong>先校准,再信任。</strong> 上线一个 judge 前,拿它跑那批人审过的 golden case,看它和人的判断一致率。业界经验是要做到 <strong>75%–90% 一致</strong>才能用。没校准过的 judge,它给的分只是&quot;看起来很科学的噪声&quot;。</li>
<li><strong>rubric 要具体到能打钩。</strong> 别问 judge&quot;这个回答好不好&quot;,要给明确标准:&ldquo;是否引用了知识库里的真实政策?是否直接回答了用户的问题?有没有编造金额?&ldquo;评判标准越像一张检查清单,judge 越稳。</li>
<li><strong>judge 喂的输入要对。</strong> 评轨迹就把完整 trace 给它,评回答质量就只给它问题和回答。喂错了上下文,分数就废了。</li>
<li><strong>警惕 judge 被骗。</strong> 2026 年初已经有研究(arXiv 上《Gaming the Judge》)指出:Agent 可以生成一段&quot;看起来很有道理但其实不忠实&quot;的推理,把 LLM judge 哄过去。所以高风险场景下,judge 的结论仍然要被人审抽查兜底。</li>
</ol>
<p>我的分工建议很简单:<strong>规则做体检(确定性指标),LLM-as-judge 做日常巡检(规模化、覆盖全量),人审做权威诊断(抽样、校准 judge、定真相)。</strong> 三层各管各的,谁也别越位。</p>
<h2 id="回归别让今天的修复变成明天的故障">回归:别让今天的修复变成明天的故障</h2>
<p>Agent 最阴险的回归是这样发生的:用户报了个 bug,你改了 prompt 把它修好了,上线。三周后另一类对话开始出问题——你那次改 prompt,顺手把另一种场景搞坏了。Prompt 是全局生效的,改一个字,影响面没人说得清。</p>
<p>防回归的办法,是把 eval 集变成 Agent 的<strong>回归测试套件,并且卡进 CI</strong>。</p>
<p>具体做法:每次提交改动(改 prompt、换模型、调工具),CI 自动跑全套 eval 集,把分数和主干基线逐条对比。Braintrust 的 GitHub Action、Promptfoo 这类工具已经把这条路铺好了——它会在 PR 里直接贴一张表,哪个 case 的哪个评分项涨了(🟢)、哪个跌了(🔴),一目了然。</p>
<p>关键是<strong>门禁(quality gate)</strong>:设一条线,核心 case 的成功率掉破阈值,这个 PR 就不许合。这一步把&quot;上线后被用户发现回归&quot;前移成了&quot;提 PR 时就被 CI 拦下&rdquo;。从一次线上事故,变成一次代码评审里的红叉——成本差着好几个数量级。</p>
<pre class="mermaid">flowchart LR
  A[改 prompt/模型/工具] --> B[提交 PR]
  B --> C[CI 跑全套 eval]
  C --> D{核心成功率<br/>过线了吗}
  D -->|过线| E[允许合并]
  D -->|没过| F[阻断 + PR 里标红]
  F --> A
  E --> G[上线]
  G -.线上失败 case.-> H[回灌进 eval 集]
  H --> C
  style D fill:#fde7c2,stroke:#e8b23c
  style H fill:#fde7c2,stroke:#e8b23c
</pre><p>注意图里那条虚线:<strong>线上抓到的新失败,要回灌进 eval 集。</strong> 这是整个闭环里最容易被偷懒省掉、但最值钱的一步。每修一个线上 bug,顺手把它变成一条 eval case——这样同一个坑,你这辈子只会踩一次。eval 集不是写一次就完的资产,它是跟着你的线上事故一起长大的。</p>
<h2 id="最后评估投入排个序">最后:评估投入排个序</h2>
<p>如果你正在做 Agent,评估和监控这块的投入,我建议这个顺序:</p>
<ol>
<li><strong>先上 trace。</strong> 一个看不见内部的 Agent,你连它怎么坏的都不知道,谈何优化。这是地基,而且接入成本很低。</li>
<li><strong>再攒 eval 集。</strong> 从线上 trace 里捞真实失败 case,哪怕只有 30 条也比没有强。它会马上开始帮你。</li>
<li><strong>然后卡进 CI。</strong> 把 eval 集变成回归门禁,从此改 prompt 不再是闭眼下注。</li>
<li><strong>最后才上 LLM-as-judge,而且必须先用人审校准。</strong> 校准跳不得。</li>
</ol>
<p>很多团队的顺序是反的——demo 一通就急着上线,出了事再回头补监控。但 Agent 这东西,<strong>你对它的可观测性有多深,你能把它做多好就有多高的上限</strong>。先让自己看得见,再谈让它变得更好。</p>
]]></content:encoded></item></channel></rss>