一、 背景与要解决的问题
Agent(大模型智能体)的执行过程本质是一个黑盒:它每一轮调用了哪些工具、消耗了多少 Token、哪一步出现延迟抖动、在哪里发生报错,通常在运行结束时只能看到最终生成的文本,中间过程无从追溯。
传统软件排查依赖结构化日志,但在 Agent 场景下,核心痛点往往呈现为:
-
Token 消耗不可控:某单轮请求上下文突然急剧膨胀,导致费用激增。
-
并发执行阻塞:并行分发的工具调用中,某一个外部任务挂起或超时,拖慢整轮响应。
-
静默失败(Silent Failure):工具报错后直接返回空结果或兜底信息,未向外部抛出异常,难以察觉。
为解决上述问题,本方案将可观测性领域的成熟理论------三支柱(Three Pillars)框架引入个人 Agent 运行时:
-
Logs(日志):记录"发生了什么",提供不可变的事实流水。
-
Traces(追踪):记录调用链路拓扑与分段耗时,分析因果关系与执行时序。
-
Metrics(指标):聚合后的量化统计,用于宏观把控成本、延迟与稳定性。
目标是打开 Agent 运行黑盒,使每一轮执行过程做到可追溯、可度量、可可视化。
二、 核心设计思路
系统的易用性、侵入度与可靠性取决于以下三项底层设计决策:
1. 复用宿主已有事件流做采集,不平行 hook
Agent 每一步执行(工具调用、模型响应、轮次起止、错误)天然存在于宿主引擎的权威事件流中。
-
设计抉择 :不另起监听去"平行"抓取事件,而是直接接入宿主现有的捕获引擎作为存储后端。在 DeepSeek Harness(dsh)体系下,具体复用官方
session-telemetry的协调器。 -
收益:事件到记录的映射、数据脱敏、分级过滤以及生命周期标记完全复用;与官方远程上报后端唯一的区别是本方案落盘至本地文件。平行 hook 容易引发事件重复、时序乱序,并带来双重维护负担,复用原生事件流是保证观测数据不失真的唯一途径。
2. 热路径非阻塞,投影用纯函数
-
热路径契约 :采集器的
emit挂接在 Agent 主循环的同步路径上,其操作仅允许做轻量入队与内存缓冲,严禁执行同步 I/O 或await异步阻塞,确保可观测性逻辑不会反客为主成为系统的性能瓶颈。 -
纯函数投影:Traces 和 Metrics 均为对内存事件缓冲区的零副作用纯函数投影,外部副作用严格收敛在最终的文件写入层。这使得链路分析与指标聚合逻辑可独立进行单元测试,并且随时支持从历史原始日志中离线重算。
3. 本地自包含,零外部后端
-
本地落盘:产物(NDJSON 日志 / Chrome Trace 追踪 / 聚合指标 JSON)全部存储在本地,采用工业通用格式,不依赖任何第三方 APM 平台或云端服务,支持离线用通用工具直接查看。
-
静默降级:采集端设立严格的异常隔离,观测逻辑自身出现任何故障均静默降级,确保可观测性工具绝不阻断被观测 Agent 的核心业务执行。
三、 三支柱具体实现规范
┌─────────────────────────────────────────────────────────────────┐
│ Agent Event Stream (dsh) │
└────────────────────────────────┬────────────────────────────────┘
│ non-blocking buffer
▼
┌───────────────────────────┐
│ Raw Event Log (NDJSON) │ ◄── 唯一原始事实源
└───────┬───────────┬───────┘
│ │
pure function projection pure function projection
▼ ▼
┌────────────────────────────┐ ┌────────────────────────────┐
│ Trace Events (Chrome JSON) │ │ Metrics Aggregate JSON │
│ (callId-paired nested span)│ │ (Token/Latency/Errors) │
└────────────────────────────┘ └────────────────────────────┘
1. Logs(日志)
-
存储格式 :单事件单行的结构化 NDJSON(
logs.ndjson)。 -
写入机制 :在
emit触发时流式追加写入。作为三支柱中唯一的权威原始事实源,Traces 与 Metrics 均从其派生。即使进程遭到强制中断,日志也会完整保留至最后一次落盘的状态。
2. Traces(追踪)
-
拓扑结构 :构建
turn → step → tool的三层嵌套 Span,导出为标准的 Chrome Trace Event Format(trace.json)。 -
关键技术修复(callId 配对机制):
-
问题:Agent 在同一个 Step 中常并行下发多个工具调用,受网络与处理时延影响,各工具结果呈乱序返回。如果依赖传统的先进先出(FIFO)队列闭合 Span,会导致工具调用与耗时错位,排查数据彻底失真。
-
方案 :废除 FIFO 模式,所有
toolSpan 的开始与结束事件必须通过唯一的callId进行显式关联与精确闭合。
-
3. Metrics(指标)
-
统计分桶 :按 Session 隔离分桶统计(
metrics.json)。 -
核心指标项:
-
Token 消耗:Input Tokens、Output Tokens、Cache Read Tokens、Reasoning Tokens。
-
调用频次:Turn 轮次数、Step 内部步数、各 Tool 独立调用计数。
-
耗时分布:Turn / Step / Tool 各层级的 P50、P95、Max 分位值。
-
故障统计:Turn 错误率、Tool 错误总数。
-
4. 采集生命周期优化
-
早期隐患 :初版实现仅在进程触发
exit时落盘 Trace 和 Metrics。在命令行 Headless 运行下一视同仁,但在 Web 常驻服务模式下,后台服务进程常驻不退出,导致调试时无法实时获取 Trace 与 Metrics。 -
改进方案 :在每个 Turn 执行完毕的边界补充
flush检查点,并引入coalesce(合并防抖)锁机制,防止高频并发刷新破坏文件数据。在常驻服务中无需重启即可查验运行状态,任务意外中断也能完整保留上一轮的链路指标。
四、 实战运行审计案例:dsh-observe 分析
以下基于 DeepSeek Harness 在真实复杂会话(查询天气与车票、规划旅游景点)下的观测数据(runId: 2026-09-09T10-33-49-304Z,全周期耗时 168.7s,共 2 轮 Turn、9 个 Step)进行实证解读。
1. Metrics 视图(成本、效能与异常看板)
JSON
{
"tokens": { "input": 185126, "output": 4539, "cacheRead": 235520 },
"counts": { "turns": 2, "steps": 9, "toolCalls": { "web_fetch": 9, "web_search": 3 } },
"latencyMs": {
"turn": { "p50": 42585, "p95": 45109, "max": 45109 },
"step": { "p50": 7772, "p95": 22277, "max": 22277 },
"tool": { "p50": 501, "p95": 9716, "max": 9716 }
},
"errors": { "turnErrors": 0, "toolErrors": 2, "turnErrorRate": 0.0 }
}
-
Token 成本与 Prompt Caching 效益:
-
输入 Token(185,126)与输出 Token(4,539)比例接近 40:1,符合复杂 Agent 体系因持续注入工作区规范和环境信息导致的输入偏重特征。
-
缓存读取量达到 235,520 tokens,占处理量主要份额,证明系统前缀约束与 Skill 声明稳定命中了底层的 Prompt Cache,有效降低了 API 计费与首字延迟。
-
-
任务效能与容错:
-
Turn 错误率为 0.0%(2 轮全部成功完成交付)。
-
记录 Tool 错误 2 次,源于爬虫遭遇跨域重定向拦截,错误被限制在工具层,由 Agent 在后续步骤自主换源修复,未导致上层崩溃。
-
-
时延特征:
-
Turn 维度 P50 为 42.6 秒,Max 为 45.1 秒。
-
Tool 维度 P50 仅 501ms,但 P95/Max 飙升至 9.7 秒(共 12 次调用),暴露出外网爬取与搜索接口存在较为显著的长尾延迟。
-
2. Trace 视图(任务执行甘特图与瓶颈定位)
Plaintext
Turn 1 (42.6s) ──► Step 1 (13.9s: 2*Search 并发) ──► Step 2-4 (Fetch 串并发) ──► Step 5 (19.5s: 最终文本输出)
│
[空闲挂起 ~80s:等待用户查看并键入第二轮交互需求]
│
Turn 2 (45.1s) ──► Step 1 (9.9s: 1*Search) ──► Step 2-3 (Fetch) ──► Step 4 (22.3s: 最终文本输出)
-
并发调度可视性:在 Step 1 和 Step 2 下方,Trace 显示多块工具 Span 呈现垂直重叠排列,直观印证了运行时具备多任务并行派发与乱序归集能力。
-
时延瓶颈二八分布:
-
起始步骤(Step 1):Turn 1 耗时 13.9s,Turn 2 耗时 9.9s,耗时集中在多源网络检索。
-
收尾步骤(Final Step):Turn 1 Step 5 耗时 19.5s,Turn 2 Step 4 耗时 22.3s。此时下方无工具 Span,时间完全被大模型流式生成高密度 Markdown 表格和长文本策略所占据。
-
-
生命周期停顿:两轮大色块之间存在约 80 秒的平直空白,准确反映出 Agent 在完成首轮后进入 Idle 挂起状态,等待用户阅读并键入下一条指令。
3. Logs 视图(状态机事件与上下文注入审计)
底层的不可变事件账本完整记录了微秒级的状态流转:
-
消息收发队列管理(Inbox Splicing):
-
seq: 4(18:34:45.596):通过agent/inbox/spliced写入用户查询指令"帮我查询一下上海到西安的天气和火车票"。 -
seq: 5:触发状态机迁移turn/start。 -
seq: 6:再次通过agent/inbox/spliced将消息从消费队列移出并装载进模型执行上下文,杜绝丢消息或重复消费。
-
-
单次执行上下文(Prompt)拼装透视 : 在
seq: 7到seq: 12的 9 毫秒时间窗口内(18:34:45.729~45.738),完整呈现了输入装配序列:-
seq: 8 (system/message):装载模型身份、运行目录与工具协议。 -
seq: 9 (user/message):装载用户业务 Prompt。 -
seq: 10 (user/message):装载工作区规则(AGENTS.md规范约束)。 -
seq: 11 (user/message):装载沙箱隔离与审批策略(sandbox:policy,approval:policy)。 -
seq: 12 (user/message):挂载当前环境可用的全部 20+ 个外部 Skill 清单(available_skills)。
-
任何针对模型"为何幻觉"、"为何未遵守操作规范"的质疑,均可通过检索该日志段落进行现场还原。
4. 三图联动核心结论与优化方向
| 观测维度 | 真实观测表现 | 针对性优化 / 业务建议 |
|---|---|---|
| 网络与工具 | 12 次工具调用,P50 为 501ms,但 P95 达到 9.7s;发生 2 次重定向阻断后自愈 | 针对 weather.com.cn 等已知站点,在工具底层直接追加 URL 预规整逻辑(自动转换 https),消除重定向引发的额外轮次开销。 |
| 推理与生成 | 最终输出步耗时(19~22s)占全轮用时近 50%,模型生成大量结构化排版 | 追求交互响应体感的场景下,前端应严格消费 Server-Sent Events(SSE)打字机流,平抑长达 20 秒的等待焦虑。 |
| 成本与缓存 | 总计消耗 42.5 万 token,Prompt Cache 命中超过 23.5 万 | 得益于工程规则、目录规范与工具 Schema 保持静态前缀,缓存效益显著,后续迭代应坚守系统提示词的前缀稳定性。 |
五、 应用场景与工程沉淀
1. 落地应用场景
-
框架无关的快速埋点:为各类轻量化个人 Agent 快速提供工业级可观测能力,免除搭建复杂云端 OTLP/APM 收集链路的运维成本。
-
链路级瓶颈定位与调试:快速排查复杂工作流中"某轮响应缓慢"、"Token 异常激增"、"并行工具 hang 死"及"内部静默报错"等故障。
-
离线复盘与轨迹溯源:在无外网依赖的安全受限环境中,提供完整、高保真的任务执行轨迹复盘。
2. 交付物与沉淀资产
-
可视化交互 :生成的
trace.json可直接拖入 Perfetto UI 或chrome://tracing中,展开清晰的耗时火焰泳道图。 -
三合一离线面板 :提供轻量自包含的
dashboard.html,无需联网,拖入包含三产物的runId文件夹即可在单一页面内联动展示 Metrics、Trace 与 Logs。 -
高效命令行分析 :日志结构遵循严格的 NDJSON 契约,支持使用
jq编写一行命令快速完成错误抽取与耗时过滤。 -
规范沉淀 :基于
dsh-observe插件完成真实端到端验证后,解耦出框架中立的通用规范------production-agent-observabilitySkill,将产物数据契约、采集生命周期契约、基于callId的乱序配对算法及反模式规避清单固化为工程资产,供后续各 Agent 项目直接复用。