设计目标
Agent 可观测性应回答三个不同问题:
- 发生了什么? 协议、状态、策略、Tool、延迟和错误证据。
- 任务是否完成? 确定性检查、场景评估、人工复核和校准后的 Judge。
- 花费了什么? 对账后的 Provider 用量、下游费用、重试和预算结果。
这些问题需要不同的数据和留存策略。把所有原始模型输入和输出永久放进一个 Trace,会增加隐私和安全风险,却不能保证更好的调试效果。
事件契约,而不是完整转录
定义由应用拥有的事件 Schema。一个有界事件可以是:
{
"event": "tool_call_completed",
"schema_version": 3,
"run_id": "run_7f...",
"request_id": "req_21...",
"trace_id": "4bf92f...",
"step": 4,
"tenant_hash": "h:...",
"subject_hash": "h:...",
"tool": "invoice.list",
"tool_version": "2026-06-1",
"argument_digest": "sha256:...",
"policy": "allow",
"state_version": 12,
"duration_ms": 184,
"result_class": "bounded_page",
"error_code": null,
"usage": {
"input_tokens": 812,
"output_tokens": 164,
"estimated_cost_usd": 0.0019,
"price_table_version": "2026-06-01"
}
}
事件是证据,不代表捕获了模型的私有推理。区分 trace_id、run_id 和 request_id:一个 Trace 可以包含多个 Run,一个 Request 也可能被重试。
建议字段
| 字段 | 作用 | 默认处理 |
|---|---|---|
| Run/Request/Trace ID | 关联有界事件 | 不透明标识 |
| Tenant/Subject | 聚合和调查访问 | 带密钥 Hash 或获批替代值 |
| Tool/Version | 比较版本行为 | 低基数名称 |
| Argument Digest | 发现重复或变化调用 | Digest,不存原始参数 |
| Policy 决策 | 解释 Allow/Deny/Confirm | 枚举 |
| State 版本 | 发现陈旧更新和循环 | 整数 |
| Result 类别 | 衡量有界结果 | 枚举和大小分桶 |
| 耗时/错误 | 诊断运营问题 | 数值和受控错误码 |
| Usage/Cost | 对账预算 | 记录来源和价格版本 |
默认 Span 不应放 Access Token、Authorization Header、原始 Secret、隐藏推理或无限制用户内容。
脱敏与留存
隐私是可观测性设计的一部分:
- 在插桩前分类字段;
- 在生产端脱敏,不只依赖下游 Dashboard;
- 使用适合 Tenant 的密钥 Hash 标识,并记录轮换;
- 限制字符串、数组、Tool Result 和异常消息;
- 确有 Replay 需要时,将原始 Fixture 放在独立的访问控制存储;
- 按 Purpose 和法律依据定义留存;
- 将删除传播到 Trace、Index、Cache、Backup、Export 和评估数据集;
- 测试拒绝请求不会通过 Telemetry 泄露对象存在性。
采样不是隐私策略。1% 的样本仍可能包含敏感记录,而安全事件可能需要完整 Metadata 但不需要原始内容。
Trace 语义
用 Span 或 Event 表达可观察的状态转换:
run_started
-> model_call_completed
-> tool_call_requested
-> policy_decision
-> tool_call_completed
-> state_updated
-> run_finished
分开记录 Policy 决策和执行结果。模型提出 Tool Call 不等于 Tool 已执行,HTTP 成功也不等于业务动作已授权或正确。
可以用有界证据检测循环:
from dataclasses import dataclass
from typing import Iterable
@dataclass(frozen=True)
class StepEvent:
step: int
tool: str | None
argument_digest: str | None
state_version: int
policy: str
outcome: str
def repeats(events: Iterable[StepEvent], window: int = 4) -> bool:
items = list(events)
if window <= 0 or len(items) < window * 2:
return False
signature = lambda event: (
event.tool,
event.argument_digest,
event.state_version,
event.policy,
event.outcome,
)
return [signature(e) for e in items[-window * 2:-window]] == [
signature(e) for e in items[-window:]
]
它只识别重复的可观察行为,不推断隐藏推理,也不能证明循环具有恶意性。
评估是测量
使用带有明确 Oracle 的多层评估:
| 层级 | 示例 | 优点 | 局限 |
|---|---|---|---|
| Contract | Schema、Event、Policy、大小和超时 | 确定性 | 范围窄 |
| Scenario | 预期 Tool、对象、状态和结果 | 面向任务 | 需要 Fixture |
| Replay | 固定脱敏案例跨版本回放 | 回归证据 | 可能漏掉新分布 |
| Abuse | 跨 Tenant、注入、重复和外发 | 安全证据 | 需要威胁建模 |
| Human | 专家标注和分歧分析 | 判断细腻 | 成本高且有差异 |
| Model Judge | 带证据的校准量表 | 可扩展分流 | 有偏差且非确定 |
不要把这些结果压成一个“质量分数”。高 Judge 分数不能覆盖授权不变量失败。
校准 LLM Judge
如果 Judge 适合分流:
- 定义量表和允许使用的证据;
- 准备正例、负例、模糊例和对抗样本;
- 与独立人工标注比较;
- 按任务切片测量一致性,而不是只看总体平均;
- 将 Prompt、Model 和量表变化作为评估器回归测试;
- 将 Judge 结果与权威 Pass/Fail Oracle 分开保存。
不要要求 Judge 重建隐藏推理,应评估可观察的声明、引用、Tool 结果、Policy Event 和任务结果。
成本账本
成本账本应保留来源和不确定性:
{
"run_id": "run_7f...",
"currency": "USD",
"input_tokens": 812,
"output_tokens": 164,
"cached_tokens": 0,
"provider_charge": 0.0017,
"tool_charge": 0.0002,
"retry_charge": 0,
"estimated": false,
"price_table_version": "provider-2026-06-01"
}
按 Run、Tenant、Model、任务类型、Tool 和 Release 对账。将对用户计费和内部估算分开,并考虑重试、取消、缓存、流式输出、货币转换和下游服务。
成本控制应是预算和策略:
- 每 Request/Run 的 Token、Step 和时间上限;
- Principal 和 Tenant 配额;
- 在质量和延迟约束下测试 Model Routing;
- 只有隐私、时效和 Key Scope 正确时才使用 Cache;
- 高成本或外部副作用需要审批;
- 根据工作负载基线和预算承诺配置告警。
不存在通用节省百分比,任何变化都应在真实工作负载前后测量。
工具与框架选择
Langfuse、LangSmith、Phoenix、Helicone、Braintrust 和 OpenTelemetry 在托管方式、数据模型、集成、留存、评估、定价上都有差异。选择记录至少包括:
| 决策 | 需要收集的证据 |
|---|---|
| 数据驻留 | Region、Subprocessor、加密和删除 API |
| 插桩 | SDK 版本、OpenTelemetry 导出和异步行为 |
| 隐私 | 生产端脱敏、字段控制和访问审计 |
| 评估 | 数据集、人工标注、Judge 校准和 Replay |
| 运营 | 采样、尾延迟、告警和故障行为 |
| 成本 | 摄入、留存、查询、席位和外发价格 |
| 退出 | 导出格式、所有权和迁移成本 |
使用能回答当前运营问题的最少数据和最小集成。Provider 能力与价格会变化,应按版本重新核对。
按风险分阶段落地
阶段 1:Contract 与隐私
先定义 Event Schema、脱敏、留存、删除、访问角色和预算字段,再建立 Dashboard。
阶段 2:运行证据
用有界字段记录 Initialization、Model Call、Tool 提议、Policy 决策、执行结果、State 变化、取消和错误。
阶段 3:评估
建立小型脱敏 Scenario Set、确定性 Oracle、Abuse Case、Replay 对比和人工复核。先测量 Judge 分歧,再引入 Judge。
阶段 4:成本与运营
对账 Provider 账单,设置工作负载预算,监控尾延迟和下游饱和,并测试 Exporter 故障不会意外阻塞 Agent。
阶段 5:发布门禁
Prompt、Model、Tool、Policy 或插桩变化,都应通过 Contract、Scenario、Replay、Abuse、Privacy 和 Cost 证据。
可观测性不能证明什么
- Trace 不能证明模型推理真实;
- 成功的 Tool Span 不能证明对象授权;
- Judge 分数不能证明未知输入安全;
- Token 数不能证明 Provider 发票;
- Dashboard 不能替代删除、访问控制和事件响应;
- OpenTelemetry Exporter 不能替应用定义语义。
生产清单
- [ ] 拥有并版本化 Event Contract。
- [ ] 在生产端脱敏和限制大小。
- [ ] 默认排除隐藏推理、Token、Secret 和原始用户内容。
- [ ] 区分 Trace、Run 和 Request ID。
- [ ] 分开记录 Policy 决策和业务结果。
- [ ] 使用 Contract、Scenario、Replay、Abuse、Human 和校准 Judge 评估。
- [ ] 将权威 Oracle 与模型分数分开。
- [ ] 使用版本化价格表和不确定性标记对账 Usage。
- [ ] 将删除传播到 Telemetry 和评估存储。
- [ ] 测试 Exporter 故障、留存、访问、回滚和预算执行。
总结
好的 Agent 可观测性不是记录模型看过或“想过”的一切,而是隐私优先的证据系统:有界事件解释执行,分层评估衡量结果,对账账本控制成本。先定义这些契约,再选择 Dashboard,并让每个结论都不超出证据真正能证明的范围。