Appearance
Agent 可观测面板:一眼看出它在干什么、花了多少
1. 本节产出
一套 Agent 专属的 Grafana 面板:运行态分布(成功/超时/循环/审批中)、迭代轮次分布、Token 与成本趋势、工具调用排行与失败率、以及单次运行的轨迹回放。
2. 前置依赖
3. 为什么 Agent 的可观测和 RAG 不一样
RAG 关注「慢在哪一环」,是延迟视角。
Agent 还要关注三件 RAG 没有的事:
| 关注点 | 为什么重要 |
|---|---|
| 它在干什么(当前状态、第几轮) | Agent 是长时运行的,需要知道进度 |
| 它花了多少(累计 Token/金额) | 成本失控是首要风险 |
| 它有没有跑偏(轮次异常、工具失败率) | 跑偏不会报错,只会烧钱 |
所以 Agent 的面板要同时是「监控」和「成本仪表盘」和「行为观察窗」。
4. 核心原理
4.1 四类核心指标
| 类别 | 指标 | 用途 |
|---|---|---|
| 状态 | 各状态的运行数(RUNNING/DONE/TIMEOUT/LOOP/WAITING_APPROVAL) | 看健康度 |
| 效率 | 迭代轮次分布(P50/P95)、单轮耗时 | 找异常任务 |
| 成本 | Token/金额(按租户、按场景、按工具) | 控预算 |
| 质量 | 工具调用失败率、循环检测次数、审批率 | 找系统性问题 |
4.2 三个必须设的告警
| 告警 | 阈值 | 说明 |
|---|---|---|
| 单运行 Token 异常 | > 预算的 80% | 即将烧钱失控 |
| 循环检测频率 | 1 小时内 > 5 次 | prompt 或工具设计有问题 |
| 等待审批超时率 | > 30% | 审批人没配好,任务堆积 |
「循环检测频率」这个告警最有价值:它通常指向设计问题(工具描述不清、任务无法完成),而不只是偶发故障。
4.3 轨迹回放
运维视角:看聚合指标
排障视角:看单次运行的完整轨迹
轨迹包含:
每一轮的 Thought / Action / Observation
每轮的 Token 与耗时
工具调用与结果
审批记录
停止原因排障时轨迹比指标有用得多:指标告诉你「有 5% 的任务超时了」,轨迹告诉你「这些任务都卡在同一个工具的同一个错误上」。
4.4 面板布局
第一行(健康度):
运行中 / 已完成 / 超时 / 循环 / 待审批 —— 五个数字卡
第二行(效率):
迭代轮次分布直方图
单轮耗时 P50/P95
第三行(成本):
Token 消耗趋势(按小时)
按租户的成本 Top10
单运行成本分布
第四行(质量):
工具调用排行 + 失败率
循环检测次数趋势
审批通过率5. 代码走查
5.1 指标定义
java
// src/main/java/com/example/harness/metrics/AgentMetrics.java
@Component
public class AgentMetrics {
private final MeterRegistry meters;
public void recordRun(AgentResult r, AgentState s) {
// 状态分布
meters.counter("agent.run.status",
"status", r.status().name(),
"case", s.caseName()).increment();
// 轮次分布
meters.summary("agent.iterations", "case", s.caseName())
.record(s.iteration());
// Token 与成本
meters.counter("agent.tokens", "case", s.caseName())
.increment(s.tokenUsed());
meters.summary("agent.cost.per_run", "case", s.caseName())
.record(estimateCost(s.tokenUsed()));
// 耗时
meters.timer("agent.run.duration", "case", s.caseName())
.record(s.duration());
}
public void recordTool(String tool, boolean success, long ms) {
meters.counter("agent.tool.calls", "tool", tool,
"success", String.valueOf(success)).increment();
meters.timer("agent.tool.duration", "tool", tool).record(ms, TimeUnit.MILLISECONDS);
}
public void recordLoopDetected(String reason) {
meters.counter("agent.loop.detected", "reason", bucket(reason)).increment();
}
}5.2 直方图配置(否则看不到分位数)
yaml
management:
metrics:
distribution:
percentiles-histogram:
agent.iterations: true
agent.run.duration: true
agent.cost.per_run: true
percentiles:
agent.iterations: 0.5,0.95
agent.cost.per_run: 0.5,0.95,0.995.3 轨迹查询接口
java
// src/main/java/com/example/harness/controller/TraceController.java
@RestController
@RequestMapping("/api/agent/trace")
public class TraceController {
@GetMapping("/{runId}")
public TraceView trace(@PathVariable String runId) {
AgentState s = repo.load(runId).orElseThrow();
List<AuditRecord> records = auditRepo.findByRunId(runId);
return new TraceView(
s.runId(), s.goal(), s.status(), s.iteration(),
s.tokenUsed(), s.duration(),
records.stream().map(r -> new TraceStep(
r.iteration(), r.thought(), r.toolName(),
r.toolArgs(), r.observation(), r.tokens(), r.durationMs()))
.toList());
}
}5.4 告警规则示例
yaml
# prometheus rules
groups:
- name: agent
rules:
- alert: AgentTokenBudgetNearLimit
expr: agent_tokens_total > 0.8 * agent_budget_tokens
for: 5m
annotations:
summary: "Agent Token 接近预算上限"
- alert: AgentLoopDetectedFrequently
expr: increase(agent_loop_detected_total[1h]) > 5
annotations:
summary: "1 小时内检测到 5 次以上循环,检查 prompt 或工具设计"
- alert: AgentApprovalTimeoutHigh
expr: agent_approval_timeout_total / agent_approval_total > 0.3
for: 30m
annotations:
summary: "审批超时率超过 30%"6. 跑起来
bash
git checkout ch03-17-agent-observability
docker compose up -d # 含 Prometheus + Grafana
mvn spring-boot:run
# 产生各类运行(正常/超时/循环/审批)
./scripts/generate-traffic.shbash
# 看指标
curl http://localhost:8080/actuator/prometheus | grep ^agent_
# 看单次轨迹
curl http://localhost:8080/api/agent/trace/{runId} | jq .期望指标输出:
agent_run_status_total{status="DONE"} 42
agent_run_status_total{status="TIMEOUT"} 3
agent_run_status_total{status="LOOP_DETECTED"} 2
agent_run_status_total{status="WAITING_APPROVAL"} 5
agent_iterations{quantile="0.95"} 9
agent_tokens_total 1240000
agent_tool_calls_total{tool="queryMetrics",success="true"} 87
agent_tool_calls_total{tool="queryOrder",success="false"} 4
agent_loop_detected_total{reason="repeat_action"} 2| 检查项 | 通过标准 |
|---|---|
| 状态可见 | 五种状态分别计数 |
| 轮次分位数 | 能查到 P95(说明直方图已开) |
| 成本趋势 | 按小时有曲线 |
| 工具失败率 | 每个工具能算成功率 |
| 轨迹回放 | 单次运行能看到每一轮 |
| 告警 | 三条规则都能触发(用故障注入验证) |
7. 生产避坑
- 一定要监控「循环检测次数」趋势。它不是故障指标,而是设计质量指标:循环频繁说明任务设计有问题(工具不够、prompt 不清)。把它当需求优化的信号,而不是当成正常现象忽略。
- 单运行成本要有分布图,不能只看总量。总量正常但分布恶化(少数任务成本暴涨)是很常见的早期信号,只看总量会漏掉。P99 单运行成本是最该盯的一个数字。
- 轨迹回放要能按异常筛选。出问题时你要看的是「超时的那几个任务」,不是随机抽一个。做法:轨迹列表支持按状态、轮次、成本排序,直接定位到最异常的那几个。
8. 延伸与锚点
- 思考题:功能都有了,但怎么证明「Agent 比人工好」或者「这次改动是提升不是退步」?(03 篇最后一节——答案在下一课时)
- 代码锚点:
git checkout ch03-17-agent-observability - 下一课时:03-18 Agent 评测
- 对应课件:L03-17 Agent 可观测