跳转至

设计 Agent Trace、Replay 与故障归因

  • ID:Q063
  • 难度:进阶 / 系统设计 / 手撕设计
  • 标签:Observability、Trace、Replay、Failure Attribution、Evaluation

同义问法

  • Agent 出错后怎么知道是哪一步的问题?
  • 如何设计 Agent 可观测性?
  • 如何 Replay 一次 Agent 执行?
  • Badcase 如何区分是模型、Prompt、检索、工具还是状态问题?

一句话结论

Agent Trace 不能只记录最终问答,而要记录每次决策所见上下文、模型与配置版本、结构化动作、工具证据、状态变化和验证结果。Replay 的目标不是机械重跑,而是能复现、对比和定位“从哪一步开始偏离”。

可视化图解

flowchart LR
  R[一次 Agent Run] --> S1[Model Span]
  R --> S2[Tool Span]
  R --> S3[State Transition]
  R --> S4[Checkpoint / Approval]
  S1 --> T[统一 Trace]
  S2 --> T
  S3 --> T
  S4 --> T
  T --> P[Replay 重放]
  P --> C[与基线轨迹比较]
  C --> F[定位最早致错点]
  F --> E[修复并回归评测]

一、为什么普通应用日志不够

传统服务通常有:

对应流程使用 Mermaid 图解展示。

Agent 则是:

最终结果错误,根因可能在:

  • 输入理解;
  • Context 缺失或污染;
  • 模型选错工具;
  • 参数错误;
  • 工具返回错误数据;
  • 工具结果被错误摘要;
  • 状态合并丢失;
  • Planner 计划错误;
  • 验收器误判;
  • 外部环境在过程中变化。

只保存最终输出无法归因。

二、Trace 层次

Trace:一次完整 Agent Run
Span:一次模型调用、工具调用、节点执行或验证
Event:Span 内的状态变化和关键事实
Artifact:大日志、文件、Prompt、模型输出等外置证据

三、核心结构

from dataclasses import dataclass
from typing import Any, Literal

@dataclass
class Trace:
    trace_id: str
    run_id: str
    tenant_id: str
    task_type: str
    started_at: int
    ended_at: int | None
    status: Literal["running", "completed", "failed", "cancelled"]
    root_span_id: str
    model_policy_version: str
    runtime_version: str

@dataclass
class Span:
    span_id: str
    trace_id: str
    parent_span_id: str | None
    kind: Literal[
        "agent_turn", "model_call", "tool_call", "retrieval",
        "planner", "replanner", "approval", "verification",
        "context_build", "state_transition"
    ]
    name: str
    started_at: int
    ended_at: int | None
    status: Literal["ok", "error", "cancelled"]
    attributes: dict[str, Any]
    input_ref: str | None
    output_ref: str | None
    error: dict[str, Any] | None

四、模型调用应该记录什么

不应只记录 prompt 文本。至少包括:

{
  "provider": "...",
  "model": "...",
  "model_version": "...",
  "temperature": 0,
  "tool_schema_version": "v12",
  "system_prompt_hash": "...",
  "context_manifest_ref": "artifact://trace/context-7.json",
  "input_tokens": 18230,
  "output_tokens": 942,
  "latency_ms": 4210,
  "finish_reason": "tool_calls",
  "decision_type": "tool_calls"
}

context_manifest 应记录:

  • 候选上下文项;
  • 最终选中项;
  • 被丢弃项;
  • 每项来源、Token、相关性和可信度;
  • 是否被压缩;
  • 工具 Schema 列表。

这样才能判断模型错,是因为能力不够,还是根本没看到关键信息。

五、工具 Span

{
  "tool_name": "search_logs",
  "tool_version": "3.2.1",
  "call_id": "call-8",
  "idempotency_key": "...",
  "arguments_hash": "...",
  "risk_level": "read",
  "attempt": 1,
  "timeout_ms": 30000,
  "status": "success",
  "raw_result_ref": "artifact://trace/call-8/raw.json",
  "normalized_result_ref": "artifact://trace/call-8/normalized.json",
  "truncated": true,
  "latency_ms": 830
}

原始结果和标准化结果都要保存引用,才能判断是工具错,还是摘要/解析错。

六、状态迁移 Span

{
  "from": "running",
  "to": "waiting_approval",
  "state_version_before": 17,
  "state_version_after": 18,
  "patch_ref": "artifact://trace/state-patch-18.json",
  "reason": "dangerous_tool_requires_approval"
}

状态变化需要显式原因,不能只存最终快照。

七、Trace 和业务证据分离

Trace 中不要直接塞:

  • 完整代码仓库;
  • 几十 MB 日志;
  • 用户敏感数据;
  • 密钥;
  • 大型 PDF。

Trace 保存元数据和 Artifact 引用。Artifact 层负责:

  • 加密;
  • 访问控制;
  • 脱敏;
  • 生命周期;
  • Hash 校验;
  • 不同租户隔离。

八、Replay 类型

1. Exact Replay

使用原始模型输出和工具结果,只重放状态机。

用途:

  • 验证 Runtime 是否确定;
  • 检查 Reducer、状态迁移和恢复逻辑;
  • 不依赖模型随机性。

2. Model Replay

固定原始 Context 和工具结果,重新调用新模型或新 Prompt。

用途:

  • 比较模型版本;
  • 评估 Prompt 改动;
  • 判断原错误是否来自决策层。

3. Tool Replay

固定模型 Tool Call,重新运行工具。

用途:

  • 检查工具版本变化;
  • 复现参数和外部依赖问题。

有副作用工具必须运行在沙箱或 Mock 环境,不能直接重放生产写操作。

4. Counterfactual Replay

替换某一步输出,观察后续是否恢复。

例如:

  • 把错误检索结果替换为正确证据;
  • 把工具错误参数替换为正确参数;
  • 把摘要替换为原始结果。

用于定位“最早致错点”。

九、可重现性限制

完整重现模型输出通常做不到,因为:

  • 模型服务版本可能变化;
  • 即使 temperature=0 也不保证绝对确定;
  • 外部环境会变化;
  • 搜索结果、数据库和网页会变化;
  • 工具版本可能变化。

所以 Replay 需要保存或固定:

  • 模型标识和版本;
  • Prompt 与 Schema Hash;
  • Context Artifact;
  • Tool Result Artifact;
  • Runtime 版本;
  • 时间和环境快照;
  • 随机种子(支持时)。

目标通常是“解释性复现”和“对比实验”,不是保证字节级一致。

十、故障归因分类

FailureType = Literal[
    "user_input_ambiguous",
    "routing_error",
    "context_missing",
    "context_noise",
    "retrieval_miss",
    "retrieval_wrong_rank",
    "planner_error",
    "tool_selection_error",
    "tool_argument_error",
    "tool_execution_error",
    "tool_result_parse_error",
    "state_update_error",
    "memory_pollution",
    "verification_error",
    "policy_or_permission_error",
    "model_reasoning_error",
    "external_state_changed",
]

十一、最早致错点

归因时不要只标记最后失败步骤。应寻找:

第一个使后续成功概率显著下降、且如果纠正可改变最终结果的步骤。

分析流程:

十二、自动归因伪代码

def attribute_failure(trace, expected):
    spans = trace.topological_spans()

    if verification_should_have_failed(trace, expected):
        return "verification_error"

    if final_answer_not_supported(trace):
        return "model_reasoning_error"

    if required_evidence_missing(trace):
        retrieval = inspect_retrieval_spans(trace)
        if retrieval.query_bad:
            return "routing_error"
        if retrieval.candidates_missing:
            return "retrieval_miss"
        if retrieval.relevant_but_dropped:
            return "context_missing"

    for tool_span in trace.tool_spans():
        if tool_span.arguments_invalid:
            return "tool_argument_error"
        if tool_span.raw_correct_but_normalized_wrong:
            return "tool_result_parse_error"
        if tool_span.execution_failed:
            return "tool_execution_error"

    return "needs_human_review"

真实系统需要规则、Judge 和人工联合,不应让一个 LLM Judge 单独决定根因。

十三、Metrics、Logs、Traces 的关系

Metrics:整体趋势
- 成功率、延迟、Token、工具错误率、循环次数

Logs:离散事件和错误细节
- 状态变化、异常、策略命中

Traces:一次 Run 的因果链
- 谁看到什么、做了什么、为什么失败

三者都需要,不能互相替代。

十四、隐私与安全

  • Prompt 和工具结果默认可能包含敏感数据;
  • 记录前做字段级脱敏;
  • Trace 查询按租户、用户和角色鉴权;
  • 高敏 Artifact 使用短期访问令牌;
  • 定义保留周期和删除策略;
  • 不记录模型隐藏推理,只记录可观察决策、结构化理由和证据;
  • 调试便利不能突破数据合规边界。

十五、面试口述版

Agent 可观测性要以 Trace 为核心,记录每次模型调用实际看到的 Context Manifest、模型与 Prompt 版本、结构化动作、工具原始与标准化结果、状态 Patch 和验收结果。Trace 下分模型、工具、检索、规划、审批和状态迁移等 Span,大结果放 Artifact,只保存引用。Replay 分为固定原输出重放 Runtime、固定上下文比较新模型、工具重放和反事实重放;有副作用的工具只能在沙箱中。故障归因重点找最早致错点,区分上下文缺失、检索、规划、工具选择、参数、工具执行、解析、状态和验收错误。Metrics 看趋势,Logs 看事件,Trace 看因果链,三者结合才能让 badcase 可复现、可归因、可回归。