新人 免费注册,送 10 次调用,最高 $1,无需绑卡。

LLM 智能体可观测性:追踪与会话,复现 10 个问题

目录
  1. LLM 智能体中的追踪、跨度和会话是什么?
  2. 不同问题该看哪个视图?
  3. LLM 智能体为什么慢?
  4. LLM 智能体为什么贵?
  5. 如何根据用户反馈调试 LLM 智能体?
  6. 不是自己写的编程智能体,也能追踪吗?
  7. 能让模型帮你分析追踪吗?
  8. 每个智能体都应该记录什么?
  9. 网关侧追踪覆盖不到什么?
  10. 常见问题
  11. 什么是 LLM 智能体可观测性?
  12. 延伸阅读

LLM 智能体的可观测性,首先要把模型调用按两个层次归组:追踪(trace)将智能体的一次运行画成时间线,会话(session)则汇总一次对话及其总费用。每次调用带上三个请求头,LLM 网关就能根据请求日志生成这两种视图,不需要接入追踪 SDK。网关是位于业务代码和模型提供商之间的代理,会记录每个请求。我们用这套配置测试了一个小型客服智能体和 Claude Code,复现了十个常见问题:三个导致响应慢,四个导致费用高,三个导致功能异常。

TL;DR

  • 三个请求头(X-Trace-Id、X-Span-Id、X-Session-Id)就能让 Synthorai 网关把请求日志组织成追踪和会话,无需追踪 SDK。
  • 将三个互不依赖的子智能体检查并发执行后,耗时中位数从 3.7 s 降至 1.8 s,费用不变。
  • 在 GPT-6 Luna 上,将时间戳从提示词首行移走后,从空缓存开始测试,缓存命中率从 0% 升至 73%。
  • Claude Code 的一次运行花费 $0.1728,其中三个智能体各自的首次调用合计占 72%。

本文是一个七篇指南系列的总览。下面每节概述一篇指南,列出实测数据,并提供链接,方便查看代码和截图。所有测试均在 2026 年 10 月 10 日和 11 日进行。延迟数据取五次运行的中位数,其余数据均来自单次运行。代码位于 github.com/synthorai-io/use-cases。

LLM 智能体中的追踪、跨度和会话是什么?

追踪记录智能体处理一条用户消息或一项任务的全过程,跨度(span)是追踪中的一个步骤,会话则是包含多条追踪的完整对话。在我们的客服智能体中,一次两轮的客户对话对应一个会话,包含两条追踪,每条追踪中有五到六次模型调用。其中一些调用来自子智能体:主智能体将部分任务交给另一个智能体执行,后者使用自己的提示词,通常也会使用更便宜的模型。

概念覆盖范围请求头哪些调用使用相同的值
追踪智能体的一次运行X-Trace-Id本次运行的所有调用
跨度本次运行中的一次模型调用X-Span-Id仅该次调用
会话一次对话X-Session-Id本次对话的所有调用
智能体发起调用的子智能体X-Agent-Id该子智能体的所有调用
标签用户、功能、发布版本X-Synthorai-Metadata需要归组或筛选的任意调用

这些 ID 由你自行指定,每个最多包含 128 个可打印 ASCII 字符。标签是一个扁平的 JSON 对象,值均为字符串;每个请求最多带 10 个标签,每个值最多 128 字节。网关会在响应中返回这些 ID,不会将上述任何请求头转发给模型提供商。使用 OpenAI Python SDK 时,单个请求的请求头放在 extra_headers 中:

resp = client.chat.completions.create(
    model="gpt-6-luna",
    messages=messages,
    extra_headers={
        "X-Session-Id": session_id,   # one per conversation
        "X-Trace-Id": trace_id,       # one per user message
        "X-Span-Id": "plan",          # one per call
        "X-Synthorai-Metadata": '{"feature":"support-agent","_user":"u_1002"}',
    },
)

如果智能体已经通过其他工具发送追踪 ID,可能无需改动。对于请求中缺失的三个 ID,网关会分别读取 OpenTelemetry、LiteLLM、Langfuse、Open WebUI、Claude Code 或 OpenAI Codex CLI 的对应请求头。OpenTelemetry 是追踪领域的开放标准,其 traceparent 请求头包含追踪 ID。用 3 个 HTTP 请求头追踪 LLM 智能体 逐步搭建了演示智能体:先用 GPT-6 Luna 规划,再调用两个本地工具,接着用 DeepSeek V4.1 Flash 并行执行三项检查,最后调用模型生成回答。演示运行共发起 21 次模型调用,花费 $0.0017。

不同问题该看哪个视图?

本系列中的每个问题,都可以在控制台的某个位置找到答案,或通过控制台之外的日志查询方式解决。控制台将每条追踪显示为瀑布图:每次模型调用对应一条横条,共用一条时间轴。并行调用的横条会重叠,存在等待关系的调用则呈阶梯状排列。

问题查看位置指南
这次运行为什么用了 8 秒?追踪摘要:对比网关耗时和应用耗时智能体延迟
这次对话哪一轮最贵?会话页面,每行对应一条追踪智能体费用
缓存命中率为什么是 0%?会话页面的缓存命中列智能体费用
这个用户昨天的请求出了什么问题?在追踪列表中按标签搜索智能体调试
Claude Code 的哪个子智能体花了钱?会话页面的智能体表格按子智能体分析 Claude Code 费用
能在聊天窗口里问这些问题吗?Claude 中的 MCP 连接器让 Claude 查询 LLM 日志
能用自己的程序分析日志吗?MCP 工具或 REST API给智能体接入日志工具

每个追踪页面还有一个 Compare 按钮,可以在同一页面对比两条追踪:按名称配对各次调用,并将两张瀑布图放在同一时间轴上。本系列的每项修复都用这种方式核验过,对比修复前后的运行结果。

LLM 智能体为什么慢?

先看追踪顶部的耗时拆分。它将实际总耗时(用户从第一个请求发出到最后一个响应返回的等待时间)分成两部分:至少有一个模型请求尚未完成时,计入网关耗时;只有业务代码在运行时,计入应用耗时。演示追踪的总耗时为 8.5 s,其中网关耗时 7.0 s,应用耗时 1.6 s,因此应先检查模型调用。延迟指南复现了三种原因,每种都运行了五次:

原因追踪中的表现修复方式修复前中位数修复后中位数
互不依赖的调用逐个发送横条呈阶梯状排列用 asyncio.gather 并发执行,这是 Python 同时等待多个调用的方式3.7 s1.8 s
调用之间的代码执行慢your app 行很长并发执行四次查询11.0 s9.2 s
一行就能回答的问题也开启推理输出 token 数远大于实际回复reasoning_effort="none"五个回答耗时 25.6 s10.2 s

在代码执行慢的案例中,两次运行的模型调用耗时基本相同,变化的是应用耗时:指南展示的两次运行中,your app 行从 4.6 s 缩短到 1.3 s。换模型无法缩短这部分时间,需要从自己的性能分析器或 OpenTelemetry 跨度入手。第三个案例使用 GPT-6 Luna。请求参数 reasoning_effort 控制模型回答前的推理量,将其设为 none 后,五个回答的输出 token 数从 1,150 降至 190。LLM 智能体为什么慢? 提供了这三个案例的代码和并排追踪对比。

LLM 智能体为什么贵?

先将追踪列表按费用排序,再打开最贵的会话,逐轮查看缓存命中和输入列。缓存命中率是从提供商的提示词缓存中读取的输入 token 占比。对于之前见过的提示词前缀,提供商按普通输入价格的一小部分收费。费用指南复现了四种原因。演示规模很小,金额均不足一美分,因此更值得参考的是比例:

原因表现位置修复前修复后
提示词首行放了时间戳缓存命中率始终为 0%缓存命中率 0%缓存命中率 73%,输入费用降低 66%
历史记录每轮都重发全部工具结果输入量逐轮增长24,546 个输入 token8,053 个输入 token
重试循环一条追踪中调用过多,状态码均为 20010 次调用2 次调用
简单步骤使用了昂贵模型会话页面的智能体表格$0.0012$0.0003

第一行使用 GPT-6 Luna,从空缓存开始测试。指南还介绍了另一种导致缓存失效的情况:发送时给每条用户消息追加一段指令,保存时却没有保留。这样每一轮重建出的提示词,都与上一轮实际发送的内容不同。按实际发送的内容保存消息后,该对话的缓存命中率从 0% 升至 76%。在历史记录案例中,输入 token 数增加到三倍,输入费用却只增加了 21%,因为其中 71% 来自缓存。最后一行中,使用 GPT-6.1 Sol 的三项子智能体检查占会话总费用的 81%,换成 DeepSeek V4.1 Flash 执行相同检查后,费用只有原来的十分之一。LLM 智能体为什么贵? 逐一分析了这些案例。

如何根据用户反馈调试 LLM 智能体?

先通过标签找到用户的运行记录,再查看追踪,定位出错的那次调用。出错调用往往也会返回状态码 200。如果每个请求都带有 _user 标签,在追踪列表中搜索 metadata._user = u_1002,就能找到该用户的会话和追踪。调试指南随后复现了三种故障:

  • 返回 404 后重试。调用一个不存在的模型 ID,95 ms 后失败,费用为 $0。重试沿用追踪 ID,并使用新的跨度名称(policy-check.retry),因此失败调用和重试会在瀑布图中相邻显示。
  • 状态码为 200,回复却被截断。设置 max_tokens=40 并保持推理开启时,连续三次调用 DeepSeek V4.1 Flash 都返回状态码 200,输出恰好为 40 个 token,但回复为空,因为推理耗尽了额度。追踪中同一跨度出现三次,每次输出量都等于上限。将上限提高到 2,000 并关闭推理后,只需一次调用就得到了 49 个 token 的回答。仅提高上限也能解决问题,但那次调用用了 1,876 个 token 推理,耗时 22 s。
  • 第二轮返回 400。保存的历史记录丢失了一次工具调用,导致 GPT-6 Luna 在第二轮用 0.5 s 拒绝请求,未收取费用,而第一轮运行正常。

第二种故障说明,每次调用都应该记录 finish_reason,这个响应字段表示模型停止生成的原因。值为 length 表示回复触及了 max_tokens 上限,即使状态码是 200,也应算作失败。调试 LLM 智能体 列出了每个智能体都应该记录的五个字段,本文末尾也会再次列出。

不是自己写的编程智能体,也能追踪吗?

无需修改 Claude Code 就能追踪它,因为它的每个请求已经带有会话 ID 和智能体 ID。设置两个环境变量即可将请求指向网关,第三个变量用于附带各子智能体的类型:

export ANTHROPIC_BASE_URL="https://synthorai.io"   # no /v1: Claude Code adds /v1/messages itself
export ANTHROPIC_API_KEY="<your gateway key>"
export CLAUDE_CODE_GATEWAY_HINT_HEADERS=1          # optional: names sub-agent types such as Explore

Claude Code 使用 Claude Sonnet 5.5,通过两个子智能体修复一个失败测试,共发起 11 个请求,花费 $0.1728。会话页面按智能体拆分了费用:两个子智能体占 39%,缓存写入占 77%,三个智能体各自的首次调用合计占 72%。半分钟后,在缓存已预热的情况下重复同一次运行,费用为 $0.0812。按子智能体分析 Claude Code 费用 还介绍了如何按开发者和代码仓库拆分团队费用。

能让模型帮你分析追踪吗?

模型可以通过 MCP 读取追踪。MCP 即 Model Context Protocol,是向模型提供工具的标准协议;网关以 MCP 服务器的形式提供请求日志。该用哪种方式读取,取决于谁在查询:

查询者使用方式模型 token实测结果
带着问题来查询的人在 Claude 中将网关添加为连接器包含在聊天套餐中3 个问题用了 14 次工具调用,所有数字均与账单记录一致
执行固定查询的程序REST API不需要查询费用最高的 3 个会话,花费 $0
自主决定检查内容的自建智能体程序中的 MCP 工具需要付费一次费用排查花费 $0.0015

在聊天场景中,Claude Fable 5.1 通过 OAuth 连接,即通过浏览器登录,无需粘贴 API key,并且只被授予请求日志的读取权限。它获得了四个只读工具,以及一枚 7 天后过期的密钥。工具返回费用、token 数和状态,不包含提示词或回复正文。在程序场景中,GPT-6 Luna 只用一次工具调用,就从 26 个会话中找出了缓存、模型选错和重试循环对应的会话,花费 $0.0015;Claude Sonnet 5.5 先查询价格,再用三次工具调用找到相同会话,花费 $0.0631。让 Claude 查询 LLM 日志 和给智能体接入日志工具 分别介绍了这两种配置。

每个智能体都应该记录什么?

五个字段就能覆盖本系列的所有问题:

  • 每次运行的追踪 ID 和每次对话的会话 ID,通过请求头发送,同时写入自己的日志。
  • 每次调用的跨度名称,包含步骤和尝试次数,例如 plan-2 或 policy-check.retry。
  • 用户、功能和发布版本标签,便于从用户反馈或账单定位到相关运行。
  • 每次调用响应中的 x-request-id 请求头,便于事后查询该调用的计费金额。
  • 每次调用的 finish_reason 和输出 token 数,将 length 视为失败。

每次调用还应设置客户端超时和 max_tokens,两者都要留足余量。上面的空回复 200 问题,就是按可见回复长度设置上限造成的;推理模型的一次长调用可能持续数分钟。

网关侧追踪覆盖不到什么?

基于请求日志的追踪只能覆盖模型调用,看不到业务代码内部。网关根据请求间的空档推算代码运行时间,前面的慢代码案例就是如此。工具、检索和队列的跨度需要通过 OpenTelemetry SDK 采集。两种视图可以共用追踪 ID,因为缺少 X-Trace-Id 时,网关会读取 traceparent。追踪也不包含提示词和响应正文,费用则是事后统计的:如果要实时控制预算,就需要在智能体循环中,每收到一个响应便根据其中的 usage 计算费用。

常见问题

什么是 LLM 智能体可观测性?

LLM 智能体可观测性,是指能够看清智能体每次运行做了什么:调用了哪些模型、顺序如何、每次调用用了多久、花了多少钱,以及哪些调用失败了。实际落地时,就是将调用组织成追踪(一次运行)和会话(一次对话),并附上用户和功能标签。

延伸阅读

← 返回博客