Trace
Trace 是 Agent 执行过程的完整记录,包含每次 LLM 调用、工具执行、状态转换的详细信息。它是调试、监控和评估 Agent 的基础数据。
#type / concept
#status / evergreen
#tech / ai
#tech / ops
[!info] related notes
- 所属 MOC: Agent Runtime MOC, Observability Engineering MOC
- 上游概念: Run, Step
- 工具: Agent Trace Viewer, LangSmith
- 标准: OpenTelemetry
Trace
一句话定义
Trace 是 Agent 一次 Run 执行过程的完整记录,包含每个 Step 的 LLM 调用(输入/输出/延迟/token)、工具执行(名称/参数/结果/耗时)和状态转换。它是调试 Agent “为什么做出这个决策”的核心数据。
它解决什么问题
Agent 是非确定性的:同样的输入可能产生不同的执行路径。出了问题时你需要知道:
- Agent 为什么选择了这个工具而不是那个?
- 工具返回了什么结果?
- LLM 的 Prompt 里到底塞了什么内容?
- 哪一步花了最多时间?
- token 消耗在哪里?
没有 Trace,Agent 就是一个黑盒。
核心原理
Trace 的数据结构
Trace (一次 Run 的完整记录)
├── Span 1: LLM Call
│ ├── input: system prompt + messages + tools
│ ├── output: tool_call / text
│ ├── tokens: {input: 1200, output: 350}
│ ├── latency_ms: 2300
│ └── model: gpt-4
│
├── Span 2: Tool Execution
│ ├── tool_name: search_knowledge
│ ├── arguments: {query: "..."}
│ ├── result: [...]
│ ├── latency_ms: 450
│ └── status: success
│
├── Span 3: LLM Call
│ ├── input: ... + tool_result
│ ├── output: final answer
│ ├── tokens: {input: 1800, output: 500}
│ └── latency_ms: 3100
│
└── Summary
├── total_tokens: 3850
├── total_latency_ms: 5850
├── tool_calls: 1
└── steps: 2
Trace 与 OpenTelemetry
Trace 遵足 OpenTelemetry 的分布式追踪模型:
- Trace: 一次完整的请求链路
- Span: 链路中的一个操作单元
- Span Context: 跨服务传递的上下文(trace_id, span_id)
Trace (trace_id: abc123)
├── Span: Agent Run (span_id: 001)
│ ├── Span: LLM Call (span_id: 002)
│ ├── Span: Tool Execution (span_id: 003)
│ └── Span: LLM Call (span_id: 004)
Trace vs Log vs Metric
| Trace | Log | Metric | |
|---|---|---|---|
| 关注点 | 请求链路 | 离散事件 | 聚合数值 |
| 粒度 | 一次请求 | 一条记录 | 统计值 |
| 用途 | 调试、性能分析 | 错误排查 | 监控告警 |
| 例子 | 一次 Agent Run 的完整过程 | ”Tool X 调用失败" | "平均延迟 2.3s” |
典型工程实现
Trace 记录器
class AgentTracer:
def __init__(self, run_id: str):
self.run_id = run_id
self.spans: list[Span] = []
self.current_span: Optional[Span] = None
def start_span(self, name: str, attributes: dict = None) -> Span:
span = Span(
trace_id=self.run_id,
span_id=generate_id(),
name=name,
start_time=datetime.now(),
attributes=attributes or {},
parent_id=self.current_span.span_id if self.current_span else None,
)
self.spans.append(span)
self.current_span = span
return span
def end_span(self, span: Span, status: str = "ok"):
span.end_time = datetime.now()
span.duration_ms = (span.end_time - span.start_time).total_seconds() * 1000
span.status = status
def record_llm_call(self, input_tokens, output_tokens, model, latency_ms):
span = self.start_span("llm_call", {"model": model})
span.attributes["input_tokens"] = input_tokens
span.attributes["output_tokens"] = output_tokens
self.end_span(span)
def record_tool_call(self, tool_name, arguments, result, latency_ms, status):
span = self.start_span("tool_call", {"tool_name": tool_name})
span.attributes["arguments"] = arguments
span.attributes["result"] = result
self.end_span(span, status)
Trace 查询
# 查询某个 Run 的所有 Span
trace = tracer.get_trace(run_id="run_001")
# 查询所有慢 LLM 调用
slow_calls = tracer.query(
filter="span.name = 'llm_call' AND span.duration_ms > 5000"
)
# 查询工具调用失败率
fail_rate = tracer.query(
filter="span.name = 'tool_call'",
aggregate="COUNT(*) WHERE status = 'error' / COUNT(*)"
)
常见设计模式
1. 自动 Trace
Agent Runtime 自动记录所有 LLM 调用和工具执行,不需要手动埋点。
2. 采样 Trace
生产环境中只记录部分 Trace(如 10%),减少存储开销。
3. 错误 Trace
出错时自动记录完整 Trace,正常时只记录摘要。
常见坑
- 不记录 LLM 输入: 只记录输出,无法复现问题
- Trace 数据太大: 完整记录所有内容,存储成本高
- 不做采样: 生产环境全量记录,性能影响大
- Trace 和 Log 分离: 同一个请求的 Trace 和 Log 对不上
- 不记录 token 消耗: 无法分析成本
和其他概念的关系
- vs Run: Run 是执行单元,Trace 是 Run 的记录
- vs Checkpoint: Checkpoint 用于恢复,Trace 用于回溯
- vs OpenTelemetry: OTel 是 Trace 的标准框架
- vs Trace Viewer: Viewer 是 Trace 的可视化工具
总结
Trace 是 Agent 的黑盒记录器。没有 Trace,你无法知道 Agent 为什么做出某个决策,也无法优化它的行为。