跳至内容

追踪

Agents SDK内置了追踪功能,能够全面记录代理运行期间的所有事件:包括LLM生成内容、工具调用、任务交接、防护机制以及发生的自定义事件。通过Traces dashboard,您可以在开发和生产环境中对工作流进行调试、可视化及监控。

注意

默认情况下已启用追踪功能。有两种禁用追踪的方法:

  1. 您可以通过设置环境变量OPENAI_AGENTS_DISABLE_TRACING=1来全局禁用追踪
  2. 您可以通过将agents.run.RunConfig.tracing_disabled设置为True来禁用单次运行的追踪功能

对于使用OpenAI API并遵循零数据保留(ZDR)政策的组织,无法使用追踪功能。

追踪与跨度

  • Traces represent a single end-to-end operation of a "workflow". They're composed of Spans. Traces have the following properties:
    • workflow_name: 这是逻辑工作流或应用程序的名称。例如"代码生成"或"客户服务"。
    • trace_id: 追踪的唯一ID。如果不传入则会自动生成。必须符合trace_<32位字母数字>的格式。
    • group_id: 可选的组ID,用于关联来自同一对话的多个追踪记录。例如,您可以使用聊天线程ID。
    • disabled: 如果为True,则不会记录该跟踪。
    • metadata: 可选的跟踪元数据。
  • Spans represent operations that have a start and end time. Spans have:
    • started_atended_at 时间戳。
    • trace_id,用于表示它们所属的追踪记录
    • parent_id,指向该Span的父级Span(如果有的话)
    • span_data,即关于Span的信息。例如,AgentSpanData包含关于Agent的信息,GenerationSpanData包含关于LLM生成的信息等。

默认追踪

默认情况下,SDK会追踪以下内容:

  • 整个 Runner.{run, run_sync, run_streamed}() 方法都被封装在 trace() 中。
  • 每次代理运行时,它都会被封装在agent_span()
  • LLM生成的内容被包裹在generation_span()
  • 函数工具调用都被封装在function_span()
  • 防护栏被封装在guardrail_span()
  • 交接操作被封装在handoff_span()
  • 音频输入(语音转文字)被包裹在 transcription_span()
  • 音频输出(文本转语音)被包裹在 speech_span()
  • 相关的音频片段可能归属于一个speech_group_span()父节点

默认情况下,跟踪记录被命名为"Agent trace"。您可以通过使用trace来设置此名称,或者通过RunConfig配置名称及其他属性。

此外,您可以设置自定义跟踪处理器将跟踪数据推送到其他目的地(作为替代或次要目的地)。

高级追踪

有时,您可能希望将多次调用run()作为单个追踪的一部分。您可以通过将整个代码包裹在trace()中来实现这一点。

from agents import Agent, Runner, trace

async def main():
    agent = Agent(name="Joke generator", instructions="Tell funny jokes.")

    with trace("Joke workflow"): # (1)!
        first_result = await Runner.run(agent, "Tell me a joke")
        second_result = await Runner.run(agent, f"Rate this joke: {first_result.final_output}")
        print(f"Joke: {first_result.final_output}")
        print(f"Rating: {second_result.final_output}")
  1. 由于两次调用Runner.run都被包裹在with trace()中,因此各个运行将成为整体跟踪的一部分,而不是创建两个独立的跟踪。

创建追踪

您可以使用trace()函数来创建跟踪。跟踪需要被启动和结束。您有两种方式来实现:

  1. 推荐: 将trace作为上下文管理器使用,即with trace(...) as my_trace。这会在正确的时间自动开始和结束trace。
  2. 你也可以手动调用 trace.start()trace.finish()

当前跟踪通过Python contextvar实现。这意味着它能自动处理并发。如果您手动开始/结束跟踪,则需要向start()/finish()传递mark_as_currentreset_current参数来更新当前跟踪。

创建跨度

您可以使用各种*_span()方法来创建跨度。通常情况下,您不需要手动创建跨度。我们还提供了一个custom_span()函数用于跟踪自定义跨度信息。

Span会自动成为当前追踪的一部分,并嵌套在最近的当前span之下,这是通过Python的contextvar来跟踪的。

敏感数据

某些跨度可能会捕获潜在的敏感数据。

generation_span() 存储LLM生成的输入/输出,而 function_span() 存储函数调用的输入/输出。这些可能包含敏感数据,因此您可以通过 RunConfig.trace_include_sensitive_data 来禁用捕获这些数据。

类似地,Audio spans默认包含输入和输出音频的base64编码PCM数据。您可以通过配置VoicePipelineConfig.trace_include_sensitive_audio_data来禁用捕获这些音频数据。

自定义追踪处理器

追踪的高级架构如下:

  • 在初始化时,我们会创建一个全局的TraceProvider,它负责创建追踪记录。
  • 我们配置TraceProvider时使用了一个BatchTraceProcessor,它会将跟踪/跨度批量发送到BackendSpanExporter,后者将这些跨度和跟踪批量导出到OpenAI后端。

要自定义此默认设置,将跟踪发送到替代或额外的后端或修改导出器行为,您有两个选项:

  1. add_trace_processor() 允许您添加一个额外的追踪处理器,该处理器将在追踪和跨度准备就绪时接收它们。这样除了将追踪发送到OpenAI的后端外,您还可以进行自己的处理。
  2. set_trace_processors() 允许您替换默认的追踪处理器为自定义处理器。这意味着除非您包含一个执行此操作的TracingProcessor,否则追踪数据将不会被发送到OpenAI后端。

外部追踪处理器列表