1. Agent 上线后为什么必须盯住这三类指标
Agent 系统上线之后,最让人头疼的不是它跑不起来,而是它跑起来了你却不知道它跑得好不好。传统微服务那套监控思路放到 Agent 场景里会直接失灵:一个 HTTP 200 的响应,内容可能是模型一本正经地胡说八道;一个后台 Agent 因为意图理解偏了,连续发起十几次工具调用,一分钟烧掉几万 Token;用户等首字等了八秒,而服务器 CPU 利用率还不到 15%。这些异常在 CPU、内存、QPS 这些常规指标上完全看不出来。
所以 Agent 的可观测性需要一套专属指标体系。我把它收敛成三类最核心、最能直接定位问题的指标:Token 消耗速率、幻觉拦截率、工具调用延迟。Token 消耗速率回答“钱花在哪、花得多快”,幻觉拦截率回答“输出质量有没有失控”,工具调用延迟回答“链路卡在哪个环节”。这三类指标覆盖了成本、质量、性能三个维度,是 Agent 上线后最先要建起来的监控底座。
这篇文章面向的是已经或即将把 Agent 推上生产的团队,尤其是多工具调用、长链路推理的场景。我会给出可复制的 Prometheus 埋点配置、Grafana 看板 PromQL,以及用 TaoToken 统一 Key 通道跑通指标上报的完整验证动作。你跟着做,就能在半小时内搭起一套能用的 Agent 监控。
先说清楚三类指标的采集口径,这是后面所有配置的基础。
Token 消耗速率,单位是 tokens/s,按租户、Agent 名称、模型、token 类型(prompt/completion)四个维度打标。它不是一个瞬时值,而是用rate()在时间窗口上算出来的速率。为什么要按租户打标?因为月末要出分摊账单,没有 tenant_id 你根本不知道是哪个业务线在烧钱。
幻觉拦截率,是一个比率指标,分子是被幻觉检测或安全审查拦截的次数,分母是总请求数。拦截原因要细分:prompt_injection、hallucination、pii_leak。这个指标的价值在于,某一类 Prompt 的拦截率突然升高,说明提示词结构有歧义,需要迭代。
工具调用延迟,用 Histogram 采集,按 tool_name 和 status(success/timeout/error)打标。它和普通接口延迟的区别在于,Agent 的工具调用是链式的,一次推理可能触发多次工具调用,所以要能区分是哪个工具、哪种状态拖慢了整体链路。
这三类指标落到 Prometheus 里,就是 Counter、Histogram、Gauge 三种类型的组合。下面进入具体配置。
2. TaoToken 统一 Key 通道的前置准备
在写埋点之前,先把模型调用通道统一掉。多 Agent 系统最常见的一个坑是:每个 Agent 各自配 Key、各自配 Base URL,结果指标上报时模型名对不上、租户归属混乱、Token 统计口径不一致。用 TaoToken 做统一 Key 通道,可以把模型调用收敛到一个入口,指标埋点只需要在一个网关层做,不用在每个 Agent 里重复实现。
TaoToken 在这里的角色是统一的模型接入通道,它提供兼容 OpenAI 风格的 API,你只需要一个 Base URL 和一个 Key,就能在多个模型之间切换。对监控来说,这意味着所有请求都经过同一个出口,Token 消耗、延迟、拦截这些数据可以在网关层一次性采集,不用去每个 Agent 里翻日志。
前置准备分三步。第一步,拿到 API Key。访问 https://taotoken.net/api-keys 创建你的 Key,注意这个 Key 要按环境隔离,生产环境和测试环境用不同的 Key,方便在指标里用 tenant_id 区分。
第二步,确认 Base URL。TaoToken 的 API 入口是 https://taotoken.net/api,所有兼容 OpenAI 的 SDK 都把 base_url 指向这里。注意这个地址不带任何查询参数,是纯净的 API 根路径。
第三步,选定 Model ID。TaoToken 支持多个模型,你在控制台 https://taotoken.net/console 里能看到可用模型列表。监控埋点里 model 这个标签就填你实际调用的 Model ID,比如 claude-sonnet 这类标识。这里要提醒一句:Base URL、Key、Model ID 这三件套必须成对出现,缺一个请求就会失败,后面排障章节会专门讲这三件套配错时的报错。
如果你用的是 Claude Code 这类编码 Agent,TaoToken 也提供了对应的接入方式,文档在 https://taotoken.net/doc。对于长期跑编码任务或 Agent 工作流的团队,可以考虑 Coding Plan,地址是 https://taotoken.net/coding-plan,它适合需要稳定通道和额度管理的场景。
前置准备做完,你手上应该有三样东西:一个 API Key、Base URLhttps://taotoken.net/api、一个确定的 Model ID。接下来把它们写进配置,并开始埋点。
3. 可复制的指标埋点配置与看板模板
这一节是全文的核心,给出可以直接复制粘贴的配置。我按“指标定义 → 流式埋点 → 看板 PromQL → 告警阈值”四步走。
先看指标定义。下面这段 Python 代码定义了五类 Prometheus 指标,覆盖 Token 消耗、首字延迟、生成速率、幻觉拦截、工具调用耗时。你可以直接放进你的网关层或 Agent 运行时。
from prometheus_client import Counter, Histogram, Gauge # 1. 成本指标:Token 消耗计数器(分租户、分模型、分类型) TOKEN_CONSUMPTION_TOTAL = Counter( "agent_token_consumed_total", "累计消耗的 Token 总量", ["tenant_id", "agent_name", "model", "token_type"] # token_type: prompt / completion ) # 2. 体验指标:首字延迟 TTFT 直方图 AGENT_TTFT_SECONDS = Histogram( "agent_time_to_first_token_seconds", "从用户发起请求到大模型吐出第 1 个 Token 的耗时分布(秒)", ["agent_name", "model"], buckets=[0.1, 0.25, 0.5, 0.8, 1.2, 2.0, 3.5, 5.0, 10.0] ) # 3. 体验指标:单 Token 生成速率 AGENT_TOKEN_SPEED = Histogram( "agent_token_generation_speed_tps", "流式生成阶段的每秒 Token 吐出速率 (Tokens/s)", ["model"], buckets=[10, 20, 30, 40, 50, 60, 80, 100] ) # 4. 质量指标:幻觉与安全审查拦截计数器 AGENT_GUARD_INTERCEPT_TOTAL = Counter( "agent_guard_intercept_total", "安全审查与幻觉检测拦截的总次数", ["agent_name", "intercept_reason"] # prompt_injection / hallucination / pii_leak ) # 5. 工具指标:工具调用耗时与状态 TOOL_CALL_DURATION_SECONDS = Histogram( "agent_tool_call_duration_seconds", "下游 Function Calling 工具执行耗时(秒)", ["tool_name", "status"], # status: success / timeout / error buckets=[0.05, 0.1, 0.25, 0.5, 1.0, 2.0, 5.0] )指标定义好之后,在流式生成中间件里埋点。下面这段代码展示了如何在流式响应过程中捕捉首字延迟、计算生成速率、统计 completion tokens。
import time async def stream_agent_generator(agent_name: str, model_name: str, tenant_id: str, llm_stream): start_time = time.time() first_token_received = False token_count = 0 stream_start_time = 0 try: async for chunk in llm_stream: # 1. 捕捉首字延迟 (TTFT) if not first_token_received: ttft = time.time() - start_time AGENT_TTFT_SECONDS.labels(agent_name=agent_name, model=model_name).observe(ttft) first_token_received = True stream_start_time = time.time() token_count += 1 yield chunk # 2. 计算流式生成速率 stream_duration = time.time() - stream_start_time if stream_duration > 0: tps = token_count / stream_duration AGENT_TOKEN_SPEED.labels(model=model_name).observe(tps) # 3. 统计 Completion Tokens TOKEN_CONSUMPTION_TOTAL.labels( tenant_id=tenant_id, agent_name=agent_name, model=model_name, token_type="completion" ).inc(token_count) except Exception as e: # 异常埋点,记录失败状态 raise e工具调用的埋点单独包一层装饰器,这样每个工具函数都能自动上报耗时和状态。
import functools def monitor_tool_call(tool_name: str): def decorator(func): @functools.wraps(func) async def wrapper(*args, **kwargs): start = time.time() status = "success" try: result = await func(*args, **kwargs) return result except TimeoutError: status = "timeout" raise except Exception: status = "error" raise finally: duration = time.time() - start TOOL_CALL_DURATION_SECONDS.labels( tool_name=tool_name, status=status ).observe(duration) return wrapper return decorator埋点写完,接下来是 Grafana 看板的 PromQL。下面三条查询分别对应 Token 消耗速率、首字延迟 P99、工具调用失败率。
# 1. 实时 Token 消耗速率(用于账单与成本预警) sum(rate(agent_token_consumed_total[5m])) by (tenant_id, model) # 2. 首字延迟 P99 分位数大盘 histogram_quantile(0.99, sum(rate(agent_time_to_first_token_seconds_bucket[5m])) by (le, agent_name)) # 3. 工具调用失败率百分比(触发 P1 报警) ( sum(rate(agent_tool_call_duration_seconds_count{status!="success"}[5m])) / sum(rate(agent_tool_call_duration_seconds_count[5m])) ) * 100幻觉拦截率的 PromQL 稍微不同,因为它是拦截数除以总请求数,需要你有一个总请求计数器配合。
# 4. 幻觉拦截率(按 Agent 维度) sum(rate(agent_guard_intercept_total{intercept_reason="hallucination"}[5m])) by (agent_name) / sum(rate(agent_request_total[5m])) by (agent_name)告警阈值这块,我给出经过实测的参考值。Token 消耗速率:单租户 5 分钟速率超过 5000 tokens/s 触发预警,超过 10000 触发 P1。首字延迟 P99:超过 3 秒预警,超过 5 秒 P1。工具调用失败率:超过 5% 预警,超过 15% P1。幻觉拦截率:单 Agent 超过 3% 预警,说明提示词需要迭代。这些阈值不是死的,你要根据自己的业务基线调整,但作为起步值是够用的。
配置写完之后,把 Prometheus 的 scrape 配置指向你的网关/metrics端点,Grafana 数据源选 Prometheus,导入上面的 PromQL 就能出图。下面进入验证环节。
4. 验证请求与成功结果确认
配置写完不代表跑通了,必须发一个真实请求验证指标有没有上报。这一步用 TaoToken 统一 Key 通道来做,因为所有请求都经过同一个出口,验证起来最直接。
先写一个最小验证脚本,用 OpenAI SDK 指向 TaoToken 的 Base URL,发一个流式请求,同时观察指标端点。
import time from openai import OpenAI client = OpenAI( api_key="你的_TaoToken_Key", base_url="https://taotoken.net/api" ) start = time.time() first_token_time = None token_count = 0 stream = client.chat.completions.create( model="你的_Model_ID", messages=[{"role": "user", "content": "用一句话解释什么是 Agent 监控"}], stream=True ) for chunk in stream: if chunk.choices[0].delta.content: if first_token_time is None: first_token_time = time.time() - start print(f"首字延迟 TTFT: {first_token_time:.3f}s") token_count += 1 total = time.time() - start print(f"总 Token 数: {token_count}") print(f"生成速率: {token_count / (total - first_token_time):.2f} tokens/s")跑完这个脚本,你应该看到三个输出:首字延迟、总 Token 数、生成速率。这三个值就是埋点要采集的原始数据。
然后验证指标端点。假设你的网关跑在本地 8000 端口,执行:
curl -s http://localhost:8000/metrics | grep agent_token_consumed_total你应该看到类似这样的输出:
agent_token_consumed_total{agent_name="demo",model="你的_Model_ID",tenant_id="test",token_type="completion"} 42.0如果看到了这个,说明 Token 消耗指标上报成功。再查首字延迟:
curl -s http://localhost:8000/metrics | grep agent_time_to_first_token_seconds_count正常应该看到计数增加了 1。工具调用延迟同理,发一个触发工具调用的请求,然后 grepagent_tool_call_duration_seconds_count,确认 status 标签有 success 或 timeout 的记录。
最后在 Grafana 里确认看板出图。打开你配置好的看板,Token 消耗速率面板应该能看到一条上升的曲线,首字延迟面板能看到刚才那次请求的 P99 值。如果曲线是空的,先检查 Prometheus 的 targets 页面,确认 scrape 状态是 UP。
验证通过的标准很简单:发一次请求,三类指标都能在/metrics里查到对应记录,Grafana 看板有数据。做到这一步,你的 Agent 监控就算跑通了。
5. 本篇常见错误排查
这一节列出实际部署中最容易踩的坑,每个都给出真实报错和定位方法。
第一个坑:401 认证失败。报错长这样:
openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Invalid API key'}}原因通常是 Key 配错了,或者 Key 和 Base URL 不匹配。检查三件套:Base URL 是不是https://taotoken.net/api,Key 是不是从 https://taotoken.net/api-keys 复制的完整字符串,Model ID 是不是控制台里存在的。三个里错一个都会 401。特别注意 Base URL 末尾不要多加/v1或斜杠,TaoToken 的 API 根路径就是https://taotoken.net/api。
第二个坑:local proxy failed。报错类似:
APIConnectionError: Connection error. local proxy failed to connect这个通常是本地网络配置问题,或者你把 base_url 写成了带端口的本地地址。确认 base_url 是完整的https://taotoken.net/api,不要指向 localhost。如果你在容器里跑,检查容器能不能访问外网。
第三个坑:reading choices 报错。报错长这样:
KeyError: 'choices' 或 IndexError: list index out of range这个多半是流式响应解析写错了。流式返回的 chunk 里,chunk.choices可能是空列表(比如最后一个 chunk 只带 usage 信息),直接取chunk.choices[0]就会越界。正确写法是先判断:
if chunk.choices and chunk.choices[0].delta.content: # 处理内容第四个坑:OAuth 相关报错。如果你用的是 Claude Code 或类似工具,报错可能是:
OAuth token expired or invalid这类工具走的是 OAuth 流程,和 API Key 是两套认证。检查你的工具配置里,Base URL 和 Key 是不是按文档填的。Claude Code 的接入方式在 https://taotoken.net/doc 里有说明,对照检查。如果工具同时支持 OAuth 和 API Key,确认你用的是 API Key 模式。
第五个坑:指标不上报。/metrics端点返回空,或者 grep 不到你的指标。原因通常是 Prometheus 客户端没注册,或者 scrape 配置没指向正确的端口。检查你的应用启动时有没有 import 指标定义模块,以及 Prometheus 的scrape_configs里 target 地址对不对。
第六个坑:工具调用延迟指标缺失。如果你用了装饰器但没看到agent_tool_call_duration_seconds,检查装饰器有没有真正包住工具函数。异步函数要用async def wrapper,同步函数用普通def,混用会导致装饰器不生效。
这几个坑覆盖了 90% 的部署问题。遇到报错先对照上面的关键词定位,基本都能解决。
6. 把监控变成日常动作
指标搭起来只是第一步,真正有价值的是把它变成团队的日常动作。我自己的做法是:每天早上看一次 Token 消耗速率大盘,确认没有异常突增;每周复盘一次幻觉拦截率,把拦截率高的 Prompt 挑出来迭代;工具调用失败率设成 P1 告警,一旦触发立刻查是哪个工具超时。
对于需要长期跑 Agent 工作流的团队,建议把模型调用统一走 TaoToken 的通道,这样指标口径一致,账单也能按租户自动分摊。如果你还在选型阶段,可以先用模型对话 https://taotoken.net/api 快速验证几个模型的延迟和 Token 消耗特征,再决定生产用哪个。长期编码或 Agent 任务量大的,看 Coding Plan https://taotoken.net/coding-plan 的额度方案。
最后给一个实用技巧:在网关层加一个单请求 Token 硬阈值,比如单个请求超过 10000 Token 就打标并记录 Trace。这个动作能帮你抓住那些死循环工具调用导致的 Token 突增,比事后看账单有用得多。监控的意义不是出图好看,而是让问题在烧钱之前就被发现。