
从「Agent 出了 bug 不知道哪一步出问题」这个开发者最真实的痛点切入,系统讲解 OpenAI Agents SDK 内置 Tracing 模块的两层核心架构(Trace/Span)、Agent Loop 全链路 Span 类型(AgentSpanData/LLMSpanData/ToolSpanData/HandoffSpanData/CustomSpanData)、trace() 与 custom_span 手动追踪 API、内置 BatchTraceProcessor 与 20+ 第三方平台接入、自定义 Processor 接口实现,以及三个实用控制开关(禁用追踪/敏感数据过滤/group_id 会话关联)。结尾附 4 条可落地实践建议,并预告下一篇 Guardrails。
print()?然后盯着终端输出,猜哪一步出了问题——是 LLM 理解错了指令,还是工具调用返回了奇怪的值,还是 Handoff 把任务交给了错误的子 Agent?print() 根本追不住。Runner.run(),就产生一个 Trace。它是最顶层的容器,记录这次 Agent 执行的全貌。
Trace: customer-service-run
├── AgentSpan: CustomerServiceAgent
│ ├── LLMSpan: gpt-4o (理解用户问题)
│ ├── ToolSpan: search_knowledge_base (查询知识库)
│ ├── LLMSpan: gpt-4o (生成回答)
│ └── HandoffSpan: → HumanAgentHandoff (转人工)create_trace 和 create_span:手动控制追踪Runner.run() 属于同一个逻辑工作流,想把它们归在一个 Trace 下from agents import Runner, trace, custom_span
from agents.tracing import create_trace, create_span
async def run_research_workflow(query: str):
# 用 trace() 创建顶层 Trace,覆盖整个工作流
# workflow_name 会显示在 Dashboard 的 Trace 列表里
with trace("research-workflow", metadata={"query": query}):
# 第一阶段:数据采集(自定义 Span,追踪非 Agent 操作)
with custom_span("data-collection"):
raw_data = fetch_external_data(query) # 你自己的函数
# 第二阶段:Agent 分析(自动产生子 Span)
result = await Runner.run(
research_agent,
input=f"分析以下数据:{raw_data}"
)
# 第三阶段:结果存储(另一个自定义 Span)
with custom_span("result-storage"):
save_to_db(result.final_output)
return resultBatchTraceProcessor 批量上传到 OpenAI 后端,打开 OpenAI Platform Traces Dashboard 就能看到 Span 树、每步耗时和 LLM 输入输出。| 平台 | 特点 |
|---|---|
| Weights & Biases | 适合 ML 实验追踪 |
| Arize Phoenix | 开源,本地部署友好 |
| MLflow | 企业级 MLOps |
| Braintrust | 专为 LLM 评估设计 |
| Langfuse | 开源,社区活跃 |
| LangSmith | LangChain 生态 |
| AgentOps | Agent 专用监控 |
| Pydantic Logfire | Pydantic 团队出品 |
from agents import set_trace_processors
from langfuse.openai_agents import LangfuseTraceProcessor
# 替换默认 Processor,追踪数据发往 Langfuse
set_trace_processors([LangfuseTraceProcessor()])
# 或者追加(同时发往多个平台)
# from agents.tracing import add_trace_processor
# add_trace_processor(LangfuseTraceProcessor())from agents.tracing import set_tracing_export_api_key
set_tracing_export_api_key("your-openai-api-key") # 仅用于追踪导出,不影响模型调用TracingProcessor 接口自己写也不复杂5:from agents.tracing import TracingProcessor, Trace, Span
from agents import add_trace_processor
class MyCustomProcessor(TracingProcessor):
"""把 Trace 数据写入自己的数据库"""
def on_trace_start(self, trace: Trace) -> None:
# Trace 开始时触发:初始化记录
db.insert_trace(trace.trace_id, trace.name, started_at=now())
def on_trace_end(self, trace: Trace) -> None:
# Trace 结束时触发:更新状态
db.update_trace(trace.trace_id, ended_at=now())
def on_span_start(self, span: Span) -> None:
# 每个 Span 开始时触发
db.insert_span(span.span_id, span.trace_id, span.started_at)
def on_span_end(self, span: Span) -> None:
# Span 结束时触发:这里能拿到完整的 span.span_data
# span.span_data 是 AgentSpanData / LLMSpanData / ToolSpanData 等
db.update_span(span.span_id, span.span_data, ended_at=now())
def shutdown(self) -> None:
# 进程退出时调用,做清理工作
db.flush()
def force_flush(self) -> None:
# 长运行应用中立即导出缓冲区
db.flush()
# 注册自定义 Processor
add_trace_processor(MyCustomProcessor())RunConfig 里关掉:from agents import RunConfig, Runner
result = await Runner.run(
agent,
input="...",
run_config=RunConfig(tracing_disabled=True)
)from agents.tracing import set_tracing_disabled
set_tracing_disabled(disabled=True)RunConfig 关掉:run_config=RunConfig(trace_include_sensitive_data=False)run_config=RunConfig(
workflow_name="customer-service", # Dashboard 里显示的工作流名
trace_id="my-custom-id-001", # 自定义 Trace ID,便于关联外部系统
group_id="session-user-123", # 关联同一用户/会话的多次 Run
trace_metadata={"env": "production", "version": "v2.1"}
)group_id 特别有用:同一用户一次对话可能触发多次 Runner.run(),用 group_id 串联起来,在 Dashboard 里就能看到完整对话的全部追踪记录。Trace: research-agent-run (耗时 45s ⚠️)
├── AgentSpan: ResearchAgent (45s)
│ ├── LLMSpan: gpt-4o (2s) ✓
│ ├── ToolSpan: web_search (40s ⚠️) ← 就是这里
│ └── LLMSpan: gpt-4o (3s) ✓web_search 耗时 40 秒,显然是外部 API 超时问题,不是 Agent 逻辑问题。五秒钟定位,不需要猜。group_id 关联用户会话Runner.run() 是独立的 Trace。把同一个 session 的所有 Run 用同一个 group_id 串联,调试时能看到完整的对话流,而不是一堆碎片化的 Trace8。custom_spancustom_span。Tracing 数据才能反映完整的业务链路,而不只是 Agent 内部的执行情况。mp.weixin.qq.com
mp.weixin.qq.com
mp.weixin.qq.com
openai.github.io
openai.github.io
mp.weixin.qq.com
zhuanlan.zhihu.com
openai.github.io
mp.weixin.qq.com
This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.