第 25 章 · 可观测性

Harness 锚点|判别清单第 7 项「可观察性」——基于会话格式的追踪、成本与调试。

那笔说不清的账单

那个卖家的选品 Agent 上线一周后,他收到 API 账单——比预估高了三倍。他想弄明白钱花哪了:是哪个卖家用得凶?哪类调研最烧 token?还是某个 Agent 卡在死循环里空转了一夜?他打开系统一看——什么记录都没有。他不知道 Agent 当时想了什么、调了哪些工具、每步花了多少 token、在哪一步出的错。这笔账,查无可查。

Agent 天生比传统程序更难观测:它的行为是非确定的(non-deterministic)(同样输入可能不同输出)、多步的(multi-step)(一次任务几十步)、烧钱的(costly)(每步都是 API 调用)。传统程序你还能靠“复现 bug”来排查,Agent 很多问题只发生一次、无法复现。没有可观测性,生产 Agent 就是个定时炸弹。

可观测性的三支柱:日志、追踪、指标

可观测性(Observability) 的核心,是让系统的内部状态从外部可见。业界把它拆成经典的“三支柱(three pillars)”,对 Agent 一样适用:

  • 日志(Logs):记录“发生了什么”。每条消息、每次工具调用、每个错误,都是一条带时间戳的离散事件。日志回答的是“这一刻具体发生了什么”。
  • 追踪(Traces):记录“一次任务的完整链路”。从用户请求到最终答案,中间每一步的顺序、耗时、输入输出——像一棵调用树(每个节点是一次模型调用或工具调用)。追踪回答的是“这次任务到底走了哪条路径”。
  • 指标(Metrics):量化的数字。token 用量、成本、延迟、成功率、工具调用次数——可聚合、可画曲线、可设告警。指标回答的是“整体趋势和健康度如何”。

三者互补:指标告诉你“出问题了”(成本曲线突然抬头),追踪告诉你“哪一次任务出的问题、走到哪断的”,日志告诉你“那一步具体错在哪”。

为什么追踪对 Agent 尤其重要

三支柱里,追踪(trace) 对 Agent 是重中之重。

传统 Web 请求往往是“一进一出”——收到请求、查个库、返回结果,链路很短。而一次 Agent 任务是多步的,甚至是多 Agent 的:它可能想了五步、调了三个工具、其中一个工具又触发了子 Agent……这条链路又长又分叉。出了问题,你需要看到的不是某一条孤立日志,而是“这次任务完整地走了哪条路径、每步花了多久、输入输出是什么、在哪个节点断的”。

这就是 trace 的价值:它把散落的日志按一次任务的因果顺序串成一棵树,让你能顺着链路一步步回放。对 Agent 来说,一条完整的 trace,基本等于“把它当时的思考和行动全程录像”。

用 pi 实现:会话格式就是天然的追踪

这里 pi 有个巧妙之处:它的会话格式(session format)(第 12 章)本身就是一份结构化的完整记录。

回顾一下,pi 的会话持久化在 ~/.pi/agent/sessions/,每条消息都带元数据——角色、内容、工具调用、token 数、时间戳。这意味着:一次 Agent 任务的完整轨迹,已经天然地存在会话文件里了。你不需要额外埋点(instrumentation),会话本身就是一条 trace。

基于这个基础,可观测性可以这样做:

// 会话本身即追踪:读取一个会话,就能还原完整执行链路
const session = await pi.loadSession(sessionId);

for (const msg of session.messages) {
  console.log({
    role: msg.role,              // user / assistant / tool
    tool: msg.toolCall?.name,    // 调用了哪个工具
    tokens: msg.usage?.total,    // 花了多少 token
    at: msg.timestamp,           // 什么时候
  });
}

// 汇总成指标
const totalCost = session.messages.reduce((s, m) => s + (m.cost ?? 0), 0);

再加上 pi 的 SDK(docs/sdk.md),你可以把这些数据导出到专业的可观测平台——比如遵循 OpenTelemetry 标准接到 Logfire、Langfuse、Grafana 等。而 pi-ai 层(第 23 章)在模型调用处统一记录 token 和定价,让成本追踪(cost attribution) 变得准确——这直接连到下一章的预算控制。

技术可观测不等于经营可评估

日志能告诉你工具有没有报错,Trace 能告诉你 Agent 走了哪条路径,但它们不能自动回答“这项能力是否改善了经营结果”。要回答后一个问题,必须让一次 Agent 运行与业务对象、流程状态和最终结果关联起来。

指标层级要回答的问题指标示例
经营结果这项能力最终创造或保护了什么价值?转化率、履约时效、缺货率、解决率、退款损失
流程结果目标流程是否更快、更稳、更少返工?处理时长、一次通过率、转人工率、异常积压
AI 质量判断、检索和执行是否正确?任务成功率、引用正确率、工具参数正确率
风险治理是否越权、误执行或违反业务规则?策略拦截率、错误审批、敏感数据访问、事故数
成本与采用单位结果是否划算,团队是否真正使用?单任务成本、人工复核成本、活跃使用率、放弃率

把业务关联标识带进 Trace

sessionIduserIdtenantId 外,生产 Trace 还应携带 capabilityId(哪项 AI 能力)、businessObjectId(哪笔订单/线索/工单)、workflowState(执行前后状态)、outcomeOwner(结果负责人)和 experimentVersion(模型、Prompt、策略组合)。最终业务结果可能几小时或几天后才出现,因此还需要一个回写机制,把结果异步关联到原始 Trace。

没有业务关联标识,可观测性只能帮助工程团队解释“系统发生了什么”;有了结果回写,它才能帮助业务团队判断“这项能力值不值得继续投入”。

可观测性的三个实际用途

有了三支柱的数据,它们在生产里主要派三个用场:

  1. 调试(debugging):Agent 行为异常时,翻出那次会话(trace),一步步看它当时想了什么、调了什么、哪步的输出不对劲——问题往往一目了然。这也是为什么“会话即追踪”这么值钱:异常本来难复现,但轨迹已经录下来了。
  2. 成本归因(cost attribution):哪个用户、哪类任务、哪个工具最烧钱?卖家那笔翻三倍的账单,有了按会话/用户聚合的指标就能定位到元凶,才谈得上优化。
  3. 质量评估(quality evaluation):成功率、平均步数、常见失败模式——这些聚合指标是持续改进 Agent 的依据,也是判断“改了提示到底有没有变好”的标尺。

从观测到评测:把真实会话变成回归集

可观测性还有一个经常被低估的价值:它是评测数据的来源

很多团队一开始做 Agent 评测,会凭空编一批问题。但最有价值的样本,其实来自真实会话:

线上失败会话 → 抽取输入、工具轨迹、错误点 → 写成 golden case → 每次发布前回放

pi 的会话格式天然适合这件事,因为你能从 trace 里看到:

  • 用户原始问题是什么。
  • Agent 调了哪些工具、参数是什么。
  • RAG 命中了哪些来源。
  • 哪一步 token / 成本异常。
  • 最终回答是否引用了正确依据。

把这些会话沉淀进附录 D 那种任务集,你就有了一套不断长大的回归测试。以后改 prompt、换模型、重建 RAG 索引,不再靠“我感觉更好了”,而是跑一遍真实样本,看关键行为有没有退化。

从第一天就记录

可观测性最容易犯的错,是“等出了问题再想加”。但前面说过,Agent 很多问题只发生一次、无法复现——如果当时没记录,就永远查不到了。你没法对着一个已经消失的现象打断点。

所以有一条铁律:从第一天起就持久化会话、记录 token 和成本。这不是等系统“成熟了”才做的锦上添花,而是地基。pi 默认就在做前者(会话持久化),你要做的是别关掉它、并把关键指标接出来。埋点这件事,晚一天,就可能永久丢掉一批本可查清的问题。

真实案例:pi-app 让长会话“不再是黑箱”

可观测性不只是给工程师看的后台指标,也能直接做进用户界面。pi 的 Web 界面 pi-app 就把 Agent 的内部状态摆到了最显眼的位置——它在顶部实时显示:

  • 上下文占用:当前用了多少窗口,离压缩还有多远(第 9 章)。
  • 花费:这个会话到目前花了多少钱(靠 pi-ai 的准确定价)。
  • 压缩结果:什么时候压缩过、压掉了什么。
  • 系统提示:当前生效的系统提示是什么。

pi-app 团队对这个功能的描述一针见血——“长会话不再像黑箱”。这正是本章的核心:可观测性就是让系统的内部状态从外部可见。它还印证了“会话即追踪”的思路——因为一次会话的完整轨迹已经结构化地存在文件里,pi-app 只是把它读出来、展示给人看,不需要额外埋点。

一个启发:面向用户的 Agent 产品,值得把成本、上下文、压缩这些“内部状态”也变成 UI 的一部分——用户对一个能看到自己“想什么、花多少”的 Agent,信任度会高得多。

动手看看

随便跑一个多步任务,然后直接去 ~/.pi/agent/sessions/ 打开对应的会话文件——你会看到每条消息的角色、工具调用、token、时间戳全在里面。对照本章说的“三支柱”,想想这一份文件里其实同时藏着日志(每条消息)、追踪(整条链路)和指标(把 token 一加就是)。

再写个十行的小脚本,遍历一个会话把每步的 tooltokens 打出来、末尾累加出总成本。跑一遍你就体会到“会话即追踪”不是口号——不埋一个点,你已经能还原整次任务并算清这笔账。

实战中的几个坑

坑一:等出了问题才想起加可观测。

  • 现象:线上冒出个诡异行为,想查却发现什么都没记,而它再也不复现了。
  • 原因:把可观测当成“后期优化”,没从第一天做。
  • 对策:第一天就持久化会话、记 token 和成本;pi 默认记会话,别手贱关掉。

坑二:日志记了,但串不成一次任务。

  • 现象:满屏离散日志,却看不出“这条错误属于哪次任务、前后发生了什么”。
  • 原因:只有日志、没有追踪,缺少把事件串成链路的 trace/会话 ID。
  • 对策:给每次任务一个会话/trace ID,让所有事件挂到同一条 trace 上(pi 的会话天然就是这条 trace)。

坑三:成本算不准,归不到人。

  • 现象:总账单知道,但说不清哪个用户/任务/工具烧的。
  • 原因:token 和定价没在统一的一层记录,或没按维度打标签。
  • 对策:在模型层(pi-ai)统一记 token 与定价,给每次调用打上用户/任务标签,才能聚合归因。

坑四:埋点太重,拖慢 Agent 或撑爆存储。

  • 现象:为了“全都记”,把每条巨大的工具输出原样落盘,存储和延迟双双失控。
  • 原因:没区分“该记摘要”和“该记全量”。
  • 对策:关键元数据(角色、工具名、token、耗时)全记,巨大内容做截断/摘要;按需采样,别无脑全量。

对比:其他框架

可观测性各家投入差别很大,都围绕“追踪每一步 + 记录 token 与成本”展开。

框架可观测性怎么做特点
LangGraph一等平台 LangSmith:追踪、评估、成本一站式,图的每个节点/每次调用都能可视化四家里可观测最成熟
CrewAI不带专门追踪平台,靠回调/日志或接第三方(OpenTelemetry、外部追踪服务)需自行接入
PydanticAILogfire 深度集成(基于 OpenTelemetry),直接追踪运行、工具调用、结构化输出观测体验是它的亮点
AgnoAgentOS 内建监控面板,直接看运行、token 与成本开箱即用
pi会话格式本身就是结构化追踪,无需埋点;pi-ai 统一记 token 与成本,可经 SDK 导出到 OpenTelemetry 等追踪几乎免费,导出靠标准协议

一句话点破:各家差别只在“平台现不现成、埋点重不重”——但共性是一致的:围绕 trace 把一次任务串起来,并在模型层统一记 token 与成本。理解这个共性,接哪家的可观测平台你都知道该导出什么。

小结

  1. Agent 非确定、多步、烧钱,很多问题只发生一次,没有可观测性就是定时炸弹。
  2. 三支柱:日志(发生了什么)、追踪(完整链路)、指标(量化数字)——对 Agent,追踪(trace) 尤其关键,它把散落事件按因果串成一棵可回放的树。
  3. pi 的会话格式本身就是天然的追踪,无需额外埋点;pi-ai 层在模型调用处统一记录 token 与成本,可经 SDK 导出到 OpenTelemetry 等外部平台。
  4. 三大用途:调试(回放异常会话)、成本归因(定位烧钱的人/任务/工具)、质量评估(成功率、步数、失败模式)。
  5. 真实会话可以沉淀成附录 D 的回归测试集,让 prompt、模型、RAG 和工具变更都有客观对照。
  6. 从第一天就记录——很多问题当时没记就永远查不到;pi-app “长会话不再是黑箱”正是把内部状态变成 UI 的示范。

可观测性让我们“看得见”成本。下一部分 Part 8,我们进入企业级特性,第一件事就是“管得住”成本——Token 预算控制