第十篇:AI Agent 可观测性建设:用 Trace 串联模型、MCP、A2A 与业务系统
系列:《2026 可验证企业级 AI Agent 工程》
本文关键词:AI Observability、OpenTelemetry、Trace、Spring AI、MCP、A2A
文章目录
- 第十篇:AI Agent 可观测性建设:用 Trace 串联模型、MCP、A2A 与业务系统
- 一、传统微服务监控为什么不够?
- 二、Agent 可观测性的三大支柱
- 三、一个完整的 Agent Trace 应该是什么样?
- 四、引入 OpenTelemetry
- 五、Spring Boot 接入可观测性
- 六、Spring AI 已经提供哪些观测能力?
- 七、自定义 Agent 顶层 Observation
- 八、记录 Agent 规划过程
- 九、为 MCP 工具调用创建 Span
- 十、为 A2A 委派传播 Trace Context
- 十一、记录 A2A Task 生命周期
- 十二、日志如何关联 Trace?
- 十三、Prompt 和 Completion 应该记录吗?
- 十四、Token 与成本监控
- 十五、核心 Metrics 设计
- 十六、使用 Micrometer 创建自定义指标
- 十七、如何定位一个慢请求?
- 十八、错误分类比错误数量更重要
- 十九、采样策略
- 二十、告警规则设计
- 二十一、Agent 可观测性看板
- 二十二、可观测性与评测如何结合?
- 二十三、常见反模式
- 《AI Agent 安全攻防:Prompt Injection、越权工具调用与数据泄露防护》
前言
某天,用户反馈:
AI 分析一个简单的能耗问题,为什么用了 45 秒?
传统日志可能只记录:
2026-09-22 10:20:45 INFO 分析完成
但真正的执行过程可能是:
意图识别:800ms
→ RAG检索:1.2s
→ 第一次模型调用:4.5s
→ MCP能耗查询:18s
→ 第二次模型调用:5s
→ A2A设备诊断:12s
→ 生成最终回答:3.5s
也可能是 Agent 陷入了循环:
查询能耗
→ 查询告警
→ 再次查询相同能耗
→ 再次查询相同告警
→ 重新规划
如果没有完整可观测性,开发者只能猜测:
- 是模型响应慢?
- 数据库查询慢?
- MCP Server 超时?
- A2A 子 Agent 阻塞?
- RAG 检索内容过多?
- Agent 重复调用工具?
- Token 数量突然增加?
因此,生产级 AI Agent 必须建立覆盖模型、工具、检索、任务与业务结果的可观测体系。
一、传统微服务监控为什么不够?
传统微服务主要关注四类指标:
请求量
错误率
响应时间
资源使用率
这些指标仍然重要,但无法回答 Agent 特有的问题:
模型为什么选择这个工具?
Prompt使用了多少Token?
RAG检索到了哪些文档?
工具参数是否正确?
Agent执行了多少步骤?
是否发生重新规划?
子Agent完成了哪些任务?
答案是否有证据支持?
本次任务花费了多少成本?
Agent 系统需要同时观察两个世界。
确定性世界
包括:
- HTTP 请求;
- 数据库;
- Redis;
- 消息队列;
- MCP Server;
- 微服务;
- JVM。
概率性世界
包括:
- Prompt;
- 模型响应;
- Tool Calling;
- Agent 规划;
- RAG 结果;
- Memory 召回;
- 多 Agent 委派;
- LLM Judge。
完整可观测性必须把二者连接起来。
二、Agent 可观测性的三大支柱
1. Trace:这次任务经历了什么?
Trace 记录一次任务的完整调用链:
用户请求
→ Agent规划
→ 模型调用
→ RAG检索
→ MCP工具
→ 数据库
→ A2A子Agent
→ 最终回答
它最适合回答:
哪里慢?
哪里失败?
为什么重复调用?
错误从哪个服务开始?
2. Metrics:系统整体表现如何?
Metrics 用于聚合趋势:
任务成功率
P95响应时间
模型Token消耗
工具失败率
Agent平均执行步数
单任务平均成本
它最适合告警和趋势分析。
3. Logs:具体发生了什么?
Logs 用于记录离散事件:
用户确认创建工单
工具参数校验失败
Agent重新规划
MCP Server返回权限不足
A2A任务进入input-required
三者通过 traceId 关联:
Metrics发现异常
→ Trace定位链路
→ Logs查看细节
三、一个完整的 Agent Trace 应该是什么样?
能源诊断任务的理想 Span Tree:
ai.agent.invoke
├── ai.agent.plan
│ └── gen_ai.client.operation
├── ai.rag.retrieve
│ ├── gen_ai.client.operation Embedding
│ └── db.vector.client.operation
├── ai.agent.execute_step
│ ├── gen_ai.client.operation
│ └── ai.mcp.tools_call
│ └── db.clickhouse.query
├── ai.a2a.send_message
│ └── device-diagnosis-agent
│ ├── gen_ai.client.operation
│ └── ai.mcp.tools_call
│ └── db.alarm.query
├── ai.human.confirmation
├── ai.mcp.tools_call
│ └── business.create_order
└── ai.agent.finalize
└── gen_ai.client.operation
看到这棵树,就可以迅速判断:
- 总耗时是多少;
- 哪个 Span 最慢;
- 调用了多少次模型;
- 使用了哪些工具;
- 是否发生跨 Agent 委派;
- 工单是否真正创建;
- 哪个环节发生异常。
四、引入 OpenTelemetry
OpenTelemetry 提供统一的:
Trace API
Metrics API
Logs关联
上下文传播
OTLP导出协议
数据可以发送到:
- Jaeger;
- Zipkin;
- Grafana Tempo;
- Prometheus;
- Langfuse;
- Arize Phoenix;
- Elastic APM;
- 商业可观测平台。
推荐架构:
应用不应该直接绑定某一个观测平台,而应优先通过 OTLP 输出。
五、Spring Boot 接入可观测性
Maven 依赖示例:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
配置示例:
management:
endpoints:
web:
exposure:
include:
- health
- info
- prometheus
tracing:
sampling:
probability: 1.0
otlp:
tracing:
endpoint: http://otel-collector:4318/v1/traces
生产环境不建议长期使用 1.0 全量采样,应结合流量、成本和故障率配置采样策略。
六、Spring AI 已经提供哪些观测能力?
Spring AI 基于 Micrometer Observation 为以下组件提供观测支持:
ChatClient
Advisor
ChatModel
EmbeddingModel
ImageModel
VectorStore
Tool Calling
典型 Observation 包括:
| Observation | 作用 |
|---|---|
spring.ai.chat.client | ChatClient 整体调用 |
spring.ai.advisor | Advisor 执行 |
gen_ai.client.operation | 模型调用 |
spring.ai.tool | Tool Calling |
db.vector.client.operation | 向量数据库操作 |
模型 Span 可以包含:
gen_ai.request.model
gen_ai.response.model
gen_ai.response.finish_reasons
gen_ai.usage.input_tokens
gen_ai.usage.output_tokens
gen_ai.usage.total_tokens
工具 Span 可以包含:
spring.ai.tool.definition.name
spring.ai.tool.type
spring.ai.tool.call.id
这意味着接入 Spring Boot Observability 后,许多基础模型和工具调用能够自动进入 Trace。
七、自定义 Agent 顶层 Observation
Spring AI 能够观察模型调用,但业务仍需要一个顶层 Agent Span。
@Service
public class ObservableEnergyAgent {
private final ObservationRegistry registry;
private final EnergyAgent delegate;
public ObservableEnergyAgent(
ObservationRegistry registry,
EnergyAgent delegate) {
this.registry = registry;
this.delegate = delegate;
}
public AgentResult execute(AgentRequest request) {
return Observation
.createNotStarted(
"ai.agent.invoke",
registry
)
.lowCardinalityKeyValue(
"agent.name",
"energy-agent"
)
.lowCardinalityKeyValue(
"agent.operation",
"energy-diagnosis"
)
.highCardinalityKeyValue(
"agent.task.id",
request.taskId()
)
.highCardinalityKeyValue(
"tenant.id",
request.tenantId()
)
.observe(() -> delegate.execute(request));
}
}
这里必须区分低基数和高基数标签。
低基数
适合 Metrics 和 Trace:
agent.name
agent.operation
tool.name
result.status
model.name
高基数
只适合 Trace,不能作为 Prometheus 标签:
taskId
userId
conversationId
deviceId
requestId
如果把 userId 或 taskId 放进指标标签,会产生海量时间序列,导致监控系统性能和成本失控。
八、记录 Agent 规划过程
public AgentPlan plan(
AgentRequest request) {
return Observation
.createNotStarted(
"ai.agent.plan",
observationRegistry
)
.lowCardinalityKeyValue(
"agent.name",
"energy-agent"
)
.lowCardinalityKeyValue(
"planner.result",
"pending"
)
.observe(() ->
agentPlanner.createPlan(request)
);
}
建议记录:
计划步骤数量
使用的Planner模型
计划耗时
是否通过校验
是否包含写操作
是否发生重新规划
不建议默认记录完整规划 Prompt 和模型内部推理文本。
更安全的记录方式:
{
"stepCount": 5,
"toolNames": [
"queryDeviceEnergy",
"queryAlarmHistory"
],
"containsWriteAction": false,
"validationResult": "PASSED"
}
九、为 MCP 工具调用创建 Span
MCP Client 调用:
@Component
public class ObservableMcpClient {
private final ObservationRegistry registry;
private final McpClient delegate;
public Object callTool(
String serverName,
String toolName,
Map<String, Object> arguments) {
return Observation
.createNotStarted(
"ai.mcp.tools_call",
registry
)
.lowCardinalityKeyValue(
"mcp.server.name",
serverName
)
.lowCardinalityKeyValue(
"mcp.method",
"tools/call"
)
.lowCardinalityKeyValue(
"mcp.tool.name",
toolName
)
.observe(() ->
delegate.callTool(
toolName,
arguments
)
);
}
}
MCP Span 建议记录:
server.name
protocol.version
transport
method
tool.name
result.status
retry.count
result.size
工具参数和结果可能包含敏感信息,默认不要写入 Span。
可以只记录摘要:
{
"deviceCount": 1,
"timeRangeHours": 24,
"resultRows": 24
}
而不是记录完整设备数据。
十、为 A2A 委派传播 Trace Context
跨 Agent 调用最容易出现 Trace 断裂:
调度Agent:Trace A
设备诊断Agent:Trace B
此时看不到它们属于同一次业务请求。
应使用 W3C Trace Context,通过 HTTP Header 传播:
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
tracestate: ...
在 A2A 调用中还可以传递业务关联字段:
{
"metadata": {
"taskId": "TASK-001",
"contextId": "CTX-001"
}
}
其中:
traceId:连接分布式技术链路
taskId:标识具体任务
contextId:关联多轮A2A协作
不要自行生成新的 traceId 覆盖上游 Trace Context。
十一、记录 A2A Task 生命周期
A2A Task 可能经历:
submitted
→ working
→ input-required
→ working
→ completed
每次状态变化都应记录 Event:
public void recordTaskTransition(
String taskId,
TaskState from,
TaskState to) {
Observation observation =
registry.getCurrentObservation();
if (observation != null) {
observation.event(
Observation.Event.of(
"a2a.task."
+ from.name().toLowerCase()
+ ".to."
+ to.name().toLowerCase()
)
);
}
}
同时记录:
远程Agent名称
Skill ID
A2A Task ID
状态
委派耗时
等待用户时间
Artifact数量
失败原因
用户思考和确认所消耗的时间,应与 Agent 计算时间分开统计。
十二、日志如何关联 Trace?
日志格式中加入:
traceId
spanId
taskId
tenantId
agentName
示例:
INFO traceId=4bf92f... spanId=00f067...
taskId=TASK-001 agent=energy-agent
tool=queryDeviceEnergy result=success duration=823ms
查错流程:
告警发现P95延迟上升
→ 打开对应慢Trace
→ 找到慢Span
→ 使用traceId查询日志
→ 查看具体错误和业务上下文
日志应使用结构化 JSON,而不是拼接大段文本:
{
"level": "INFO",
"traceId": "4bf92f...",
"taskId": "TASK-001",
"event": "mcp_tool_completed",
"toolName": "queryDeviceEnergy",
"durationMs": 823,
"resultRows": 24
}
十三、Prompt 和 Completion 应该记录吗?
Spring AI 默认不会导出 Prompt、Completion、工具参数和工具结果,因为其中可能包含敏感数据。
相关配置包括:
spring:
ai:
chat:
observations:
log-prompt: false
log-completion: false
tools:
observations:
include-content: false
vectorstore:
observations:
log-query-response: false
生产环境应保持默认关闭。
如果排查问题必须记录内容,建议:
只在隔离测试环境开启
只针对白名单请求开启
记录前执行脱敏
设置较短保留周期
限制查看权限
记录访问审计
需要脱敏的信息包括:
- 身份证号;
- 手机号;
- 用户姓名;
- 设备敏感参数;
- 数据库地址;
- 密码和 Token;
- 内部系统信息;
- 租户业务数据。
任何密码、密钥和认证 Token 都不应进入 Trace。
十四、Token 与成本监控
Spring AI 可以提供:
gen_ai.usage.input_tokens
gen_ai.usage.output_tokens
gen_ai.usage.total_tokens
Prometheus 指标通常包括:
gen_ai_client_token_usage_total
可以计算单次调用成本:
public BigDecimal calculateCost(
String model,
long inputTokens,
long outputTokens) {
ModelPrice price =
modelPriceRegistry.get(model);
BigDecimal inputCost =
price.inputPrice()
.multiply(
BigDecimal.valueOf(inputTokens)
)
.divide(BigDecimal.valueOf(1_000_000));
BigDecimal outputCost =
price.outputPrice()
.multiply(
BigDecimal.valueOf(outputTokens)
)
.divide(BigDecimal.valueOf(1_000_000));
return inputCost.add(outputCost);
}
任务总成本包括:
Planner模型调用
+ Executor模型调用
+ Embedding
+ Reranker
+ LLM Judge
+ 子Agent调用
+ 第三方工具费用
建议关注:
每个成功任务平均成本
每种Agent平均成本
每个租户成本
失败任务浪费成本
重复调用造成的成本
十五、核心 Metrics 设计
1. 任务指标
ai_agent_task_total
ai_agent_task_duration_seconds
ai_agent_task_success_total
ai_agent_task_failure_total
ai_agent_task_active
推荐标签:
agent_name
operation
status
failure_type
2. 规划指标
ai_agent_plan_steps
ai_agent_replan_total
ai_agent_loop_detected_total
ai_agent_budget_exhausted_total
3. 工具指标
ai_agent_tool_call_total
ai_agent_tool_call_duration_seconds
ai_agent_tool_error_total
ai_agent_tool_retry_total
4. MCP 指标
ai_mcp_request_total
ai_mcp_request_duration_seconds
ai_mcp_error_total
ai_mcp_result_size
5. A2A 指标
ai_a2a_delegation_total
ai_a2a_task_duration_seconds
ai_a2a_task_failure_total
ai_a2a_input_required_total
6. 质量指标
ai_agent_groundedness_score
ai_agent_task_completion_score
ai_agent_user_feedback_total
ai_agent_unsupported_claim_total
质量分数通常通过异步评测生成,不应阻塞用户主请求。
十六、使用 Micrometer 创建自定义指标
@Component
public class AgentMetrics {
private final MeterRegistry registry;
public AgentMetrics(MeterRegistry registry) {
this.registry = registry;
}
public void recordTask(
String agentName,
String operation,
String status,
Duration duration) {
registry.counter(
"ai.agent.task",
"agent.name", agentName,
"operation", operation,
"status", status
).increment();
registry.timer(
"ai.agent.task.duration",
"agent.name", agentName,
"operation", operation,
"status", status
).record(duration);
}
public void recordToolCall(
String toolName,
String status) {
registry.counter(
"ai.agent.tool.call",
"tool.name", toolName,
"status", status
).increment();
}
}
禁止这样做:
registry.counter(
"ai.agent.task",
"userId", userId,
"taskId", taskId
);
因为用户和任务数量会不断增长,造成指标高基数问题。
十七、如何定位一个慢请求?
假设监控显示:
ai_agent_task_duration_seconds P95 > 30秒
排查顺序:
第一步:查看顶层 Trace
确认慢请求集中在哪个 Agent。
第二步:展开模型 Span
查看:
gen_ai.request.model
输入Token
输出Token
模型响应时间
finish_reason
如果输入 Token 突然增大,可能是上下文没有压缩。
第三步:展开工具 Span
查看:
哪个工具最慢
是否发生重试
结果集是否过大
第四步:检查 Agent 循环
查看:
是否重复调用相同工具
是否多次重新规划
是否没有明确终止条件
第五步:检查跨服务链路
确认 MCP、A2A、数据库是否在同一条 Trace 中。
最终可能定位到:
queryDeviceEnergy查询了30天秒级原始数据,
返回180万条记录,耗时18秒,并产生大量上下文。
修复方式应该是调整查询聚合,而不是更换大模型。
十八、错误分类比错误数量更重要
定义统一错误类型:
public enum AgentErrorType {
MODEL_TIMEOUT,
MODEL_RATE_LIMIT,
CONTEXT_OVERFLOW,
PLAN_INVALID,
LOOP_DETECTED,
TOOL_NOT_FOUND,
TOOL_ARGUMENT_INVALID,
TOOL_TIMEOUT,
MCP_CONNECTION_ERROR,
A2A_TASK_FAILED,
RETRIEVAL_EMPTY,
PERMISSION_DENIED,
USER_CONFIRMATION_TIMEOUT,
BUSINESS_CONFLICT,
BUDGET_EXHAUSTED
}
记录错误时,应区分:
系统错误:网络、服务、数据库
模型错误:规划、工具选择、参数生成
业务错误:设备不存在、工单冲突
安全错误:越权、恶意输入
用户流程:拒绝确认、补充信息超时
否则所有失败都显示为 Agent execution failed,无法进行治理。
十九、采样策略
全量保存 Trace 成本较高,而且可能扩大数据风险。
推荐分层采样:
普通成功请求:5%
慢请求:100%
错误请求:100%
高风险操作:100%
写操作:100%
安全事件:100%
用户投诉关联请求:100%
这种策略通常需要 OpenTelemetry Collector 的 Tail Sampling:
请求执行完成
→ Collector判断状态、延迟和风险
→ 决定是否保留完整Trace
Metrics 应持续全量统计,Trace 可以按策略采样。
二十、告警规则设计
可靠性告警
Agent任务失败率 > 5%
MCP工具错误率 > 3%
A2A任务超时率 > 2%
模型限流错误持续增加
性能告警
Agent P95延迟 > 30秒
模型P95延迟 > 10秒
工具P95延迟 > 5秒
向量检索P95延迟 > 2秒
成本告警
单任务Token较昨日增长50%
单任务平均成本超过预算
失败任务Token消耗持续增长
某个租户调用量异常增加
行为告警
重复工具调用率升高
重新规划次数异常
Agent步骤达到上限
input-required比例突然上升
安全告警
越权访问
敏感工具调用
确认凭证校验失败
Prompt Injection命中
跨租户访问尝试
安全告警不能依赖采样 Trace,必须完整记录。
二十一、Agent 可观测性看板
建议建立四个 Dashboard。
1. 业务总览
任务总量
任务成功率
平均完成时间
异常发现数量
工单创建数量
用户确认率
2. 模型看板
不同模型调用量
输入输出Token
P95延迟
错误率
缓存命中率
单次调用成本
3. 工具看板
工具调用排行
工具失败率
工具P95延迟
重复调用率
结果集大小
4. Agent 行为看板
平均执行步骤
重新规划次数
循环检测次数
预算耗尽次数
A2A委派数量
人工介入比例
二十二、可观测性与评测如何结合?
Observability 关注:
生产环境中真实发生了什么?
Evaluation 关注:
Agent 的行为是否满足预期?
二者结合:
生产Trace
→ 发现失败模式
→ 转换为Eval测试用例
→ 修复Agent
→ 运行回归评测
→ 灰度发布
→ 继续观察生产指标
例如监控发现:
Agent在设备不存在时平均调用了7次查询工具。
将该 Trace 转换为测试用例:
id: device-not-found-loop-regression
expected:
maxToolCalls: 2
finalStatus: FAILED
errorCode: DEVICE_NOT_FOUND
这样,同类问题就不会在下一次升级后重新出现。
二十三、常见反模式
1. 只记录模型请求耗时
这无法区分 MCP、A2A、RAG 和数据库耗时。
2. 把 Prompt 全部写进日志
容易造成隐私、密钥和业务数据泄露。
3. 每个服务生成独立 Trace
跨 Agent 调用链会断裂,无法进行端到端分析。
4. 把用户 ID 作为 Metrics 标签
会制造高基数时间序列。
5. 只有技术指标,没有业务结果
模型调用成功,不代表工单真的创建成功。
6. 只收集数据,不设置告警
没有 SLO、阈值和负责人,可观测数据就难以产生价值。
总结
AI Agent 可观测性的核心不是记录更多日志,而是建立一条完整、可关联的执行链:
用户请求
→ Agent规划
→ 模型调用
→ RAG检索
→ MCP工具
→ A2A协作
→ 业务系统
→ 最终结果
生产级体系需要同时具备:
Trace定位单次问题
Metrics发现整体趋势
Logs解释具体事件
Evaluation判断行为质量
同时必须坚持:
- 默认不记录 Prompt 和工具完整内容;
- 使用 W3C Trace Context 传播链路;
- 控制 Metrics 标签基数;
- 错误和高风险操作全量保留;
- 将生产失败持续转化为回归用例。
真正的 Agent 可观测性,不只是知道“系统是否报错”,而是能够回答:
Agent 为什么做出这个决定、调用了什么、花费了多少、产生了什么真实结果。
下一篇:
《AI Agent 安全攻防:Prompt Injection、越权工具调用与数据泄露防护》
参考资料:
478



被折叠的 条评论
为什么被折叠?



