AI Agent 可观测性实战:从 correlationId 到失败时间线

Agent 调用链越长,日志越容易陷入一个反直觉问题:每个组件都记录了内容,但没有人能还原"这一次任务"到底发生了什么。
工程上的选择不是继续堆日志,而是建立端到端关联身份:用一个 correlationId 串起请求、规划、工具、外部动作和验收,再提供有资源边界的时间线查询。
工程场景与决策冲突
一个多步骤 Agent 可能同时拥有 requestId、运行实例 ID、会话 ID、工具调用 ID 和目标对象 ID。它们都有价值,却不能替代端到端任务身份。
如果每一层只记录自己的局部 ID,故障定位就只能靠时间猜测。反过来,如果把所有上下文原样塞进日志,又会带来隐私泄露、存储膨胀和诊断接口失控。
因此我采用三条边界:
correlationId负责串联,不承载秘密;- 结构化事件记录工程事实,不保存完整敏感内容;
- 时间线查询必须有 limit、时间、扫描字节和游标边界。
方案拆解与关键权衡

一条最小执行链可以表示为:
text
Request -> Plan -> Tool -> Action -> Verify -> Outcome
每个节点共享 correlationId,但保留自己的局部 ID。这样既能端到端串联,也能在具体组件中继续下钻。
事件字段控制在可比较范围内:
python
event = {
"ts": now_iso(),
"event": "tool.failed",
"outcome": "failed",
"correlationId": cid,
"requestId": request_id,
"reasonCode": "navigation_timeout",
"target": {"tool": "browser", "tabId": safe_tab_id},
}
这里的 reasonCode 比自由文本更适合统计和自动恢复;自由文本只作为脱敏补充。
实现链路与最小示例
入口只生成一次
python
def start_context(incoming_id: str | None) -> dict[str, str]:
cid = validate_id(incoming_id) or new_uuid()
return {"correlation_id": cid}
上下文应显式向下传递。线程本地变量或隐式全局状态虽然方便,但跨异步任务和进程时更容易断链。
每个副作用动作成对记录
python
record("action.started", cid, target)
try:
result = execute()
except Exception as exc:
record("action.failed", cid, target, classify(exc))
raise
else:
record("action.completed", cid, target, "completed")
查询失败时间线,而不是全文搜索

python
timeline = diagnostics.query(
correlation_id=cid,
mode="failures",
since=incident_start,
until=incident_end,
limit=100,
cursor=cursor,
)
生产实现还应限制 max_scan_bytes 和 timeout_ms。如果查询被截断,就返回 nextCursor 与明确原因,调用方再决定是否续读。
证据、限制与自动化边界
真实实现中的诊断器支持按关联标识、请求标识、事件、相关对象和时间窗口过滤;失败模式只选择 failed、degraded、dropped 等结果。对应测试覆盖游标、扫描上限、超时和损坏记录。
但这些证据并不意味着可以记录模型完整推理。更安全的边界是记录输入输出哈希、工具名、参数的安全摘要、令牌数量、延迟、结果和来源,不保存 Cookie、授权令牌和不必要的个人信息。
自动恢复也不能只看 failed。如果外部写动作超时,结果可能未知;恢复器必须先回读业务事实,再判断是同步状态、继续验收还是使用幂等键重试。
可复用检查清单
- 端到端任务是否只有一个关联标识?
- 局部 ID 是否保留,且能映射到关联标识?
- 事件名、结果和原因码是否受控?
- 是否避免记录敏感正文和令牌?
- 是否记录动作开始与最终结果?
- 时间线查询是否有数量、时间和字节预算?
- 截断是否可用游标稳定续读?
- 外部写操作恢复前是否先回读事实?
- 是否有失败筛选、分页和损坏记录测试?
收束
可观测性的价值不是让日志平台更热闹,而是让一次任务的事实链可以重建、解释和安全恢复。你的 Agent 现在最缺的是统一关联 ID,还是工具调用的结果契约?
发布前门禁
- 减少重复背景
- 突出工程选择而非概念堆砌
- 不给未经验证的数据结论
- 本轮无已认领实验,不自行补写实验结论