콘텐츠로 이동

트레이싱

Agents SDK에는 기본 제공 트레이싱이 포함되어 있으며, 에이전트 실행 중 발생하는 이벤트의 포괄적인 기록을 수집합니다. 여기에는 LLM 생성, 도구 호출, 핸드오프, 가드레일, 그리고 발생한 사용자 정의 이벤트까지 포함됩니다. Traces dashboard를 사용하면 개발 중과 프로덕션 환경에서 워크플로를 디버그하고, 시각화하고, 모니터링할 수 있습니다.

Note

트레이싱은 기본적으로 활성화되어 있습니다. 다음의 일반적인 세 가지 방법으로 비활성화할 수 있습니다:

  1. 환경 변수 OPENAI_AGENTS_DISABLE_TRACING=1 을 설정하여 전역적으로 트레이싱을 비활성화할 수 있습니다
  2. 코드에서 set_tracing_disabled(True)를 사용해 전역적으로 트레이싱을 비활성화할 수 있습니다
  3. 단일 실행에 대해서는 agents.run.RunConfig.tracing_disabledTrue로 설정하여 트레이싱을 비활성화할 수 있습니다

OpenAI API를 사용하면서 Zero Data Retention (ZDR) 정책 하에서 운영하는 조직에서는 트레이싱을 사용할 수 없습니다.

트레이스와 스팬

  • 트레이스는 하나의 "워크플로"에 대한 단일 엔드투엔드 작업을 나타냅니다. 트레이스는 스팬으로 구성됩니다. 트레이스에는 다음 속성이 있습니다:
    • workflow_name: 논리적인 워크플로 또는 앱입니다. 예를 들어 "Code generation" 또는 "Customer service"입니다.
    • trace_id: 트레이스의 고유 ID입니다. 전달하지 않으면 자동으로 생성됩니다. 형식은 trace_<32_alphanumeric>이어야 합니다.
    • group_id: 선택적 그룹 ID로, 동일한 대화에서 나온 여러 트레이스를 연결하는 데 사용합니다. 예를 들어 채팅 스레드 ID를 사용할 수 있습니다.
    • disabled: True이면 트레이스가 기록되지 않습니다.
    • metadata: 트레이스에 대한 선택적 메타데이터입니다.
  • 스팬은 시작 시간과 종료 시간이 있는 작업을 나타냅니다. 스팬에는 다음이 있습니다:
    • started_atended_at 타임스탬프
    • trace_id: 이 스팬이 속한 트레이스를 나타냅니다
    • parent_id: 이 스팬의 상위 스팬을 가리킵니다(있는 경우)
    • span_data: 스팬에 대한 정보입니다. 예를 들어 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 workflow"입니다. trace를 사용하는 경우 이 이름을 설정할 수 있으며, RunConfig를 사용해 이름 및 기타 속성을 구성할 수도 있습니다.

또한 사용자 정의 트레이스 프로세서를 설정하여 다른 대상에 트레이스를 전송할 수 있습니다(대체 대상 또는 보조 대상으로).

장기 실행 워커와 즉시 내보내기

기본 BatchTraceProcessor는 몇 초마다 백그라운드에서 트레이스를 내보내며, 메모리 내 큐가 크기 임계값에 도달하면 더 빨리 내보냅니다. 또한 프로세스가 종료될 때 최종 플러시를 수행합니다. Celery, RQ, Dramatiq 또는 FastAPI 백그라운드 작업과 같은 장기 실행 워커에서는 일반적으로 추가 코드 없이도 트레이스가 자동으로 내보내지지만, 각 작업이 끝난 직후 Traces dashboard에 바로 표시되지는 않을 수 있습니다.

작업 단위가 끝날 때 즉시 전달을 보장해야 한다면, 트레이스 컨텍스트가 종료된 후 flush_traces()를 호출하세요.

from agents import Runner, flush_traces, trace


@celery_app.task
def run_agent_task(prompt: str):
    try:
        with trace("celery_task"):
            result = Runner.run_sync(agent, prompt)
        return result.final_output
    finally:
        flush_traces()
from fastapi import BackgroundTasks, FastAPI
from agents import Runner, flush_traces, trace

app = FastAPI()


def process_in_background(prompt: str) -> None:
    try:
        with trace("background_job"):
            Runner.run_sync(agent, prompt)
    finally:
        flush_traces()


@app.post("/run")
async def run(prompt: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(process_in_background, prompt)
    return {"status": "queued"}

flush_traces()는 현재 버퍼링된 트레이스와 스팬이 내보내질 때까지 블로킹되므로, 부분적으로만 구성된 트레이스를 플러시하지 않도록 trace()가 닫힌 후 호출해야 합니다. 기본 내보내기 지연이 허용 가능하다면 이 호출은 생략할 수 있습니다.

상위 수준 트레이스

경우에 따라 여러 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. 권장 방식: with trace(...) as my_trace처럼 트레이스를 컨텍스트 매니저로 사용합니다. 이렇게 하면 적절한 시점에 트레이스가 자동으로 시작되고 종료됩니다.
  2. trace.start()trace.finish()를 수동으로 호출할 수도 있습니다.

현재 트레이스는 Python contextvar를 통해 추적됩니다. 이는 동시성 환경에서도 자동으로 동작함을 의미합니다. 트레이스를 수동으로 시작/종료하는 경우, 현재 트레이스를 갱신하기 위해 start()/finish()mark_as_currentreset_current를 전달해야 합니다.

스팬 생성

다양한 *_span() 메서드를 사용해 스팬을 생성할 수 있습니다. 일반적으로는 스팬을 수동으로 생성할 필요가 없습니다. 사용자 정의 스팬 정보를 추적하기 위해 custom_span() 함수를 사용할 수 있습니다.

스팬은 자동으로 현재 트레이스의 일부가 되며, Python contextvar를 통해 추적되는 가장 가까운 현재 스팬 아래에 중첩됩니다.

민감한 데이터

일부 스팬은 잠재적으로 민감한 데이터를 캡처할 수 있습니다.

generation_span()은 LLM 생성의 입력/출력을 저장하고, function_span()은 함수 호출의 입력/출력을 저장합니다. 여기에는 민감한 데이터가 포함될 수 있으므로, RunConfig.trace_include_sensitive_data를 통해 해당 데이터의 캡처를 비활성화할 수 있습니다.

마찬가지로 오디오 스팬은 기본적으로 입력 및 출력 오디오에 대한 base64 인코딩 PCM 데이터를 포함합니다. VoicePipelineConfig.trace_include_sensitive_audio_data를 구성하여 이 오디오 데이터의 캡처를 비활성화할 수 있습니다.

기본적으로 trace_include_sensitive_dataTrue입니다. 앱을 실행하기 전에 OPENAI_AGENTS_TRACE_INCLUDE_SENSITIVE_DATA 환경 변수를 true/1 또는 false/0으로 내보내 코드 변경 없이 기본값을 설정할 수 있습니다.

사용자 정의 트레이싱 프로세서

트레이싱의 상위 수준 아키텍처는 다음과 같습니다:

  • 초기화 시 트레이스 생성을 담당하는 전역 [TraceProvider][agents.tracing.setup.TraceProvider]를 생성합니다
  • TraceProviderBatchTraceProcessor로 구성하며, 이 프로세서는 트레이스/스팬을 배치로 BackendSpanExporter에 전송하고, BackendSpanExporter는 스팬과 트레이스를 OpenAI 백엔드로 배치 단위로 내보냅니다

이 기본 설정을 사용자 정의하여 대체 또는 추가 백엔드로 트레이스를 보내거나 내보내기 동작을 수정하려면 두 가지 옵션이 있습니다:

  1. add_trace_processor()를 사용하면 준비된 트레이스와 스팬을 전달받는 추가 트레이스 프로세서를 추가할 수 있습니다. 이를 통해 트레이스를 OpenAI 백엔드로 전송하는 것에 더해 자체 처리를 수행할 수 있습니다.
  2. set_trace_processors()를 사용하면 기본 프로세서를 사용자의 트레이스 프로세서로 대체할 수 있습니다. 이 경우 TracingProcessor를 포함하지 않으면 트레이스는 OpenAI 백엔드로 전송되지 않습니다.

비 OpenAI 모델과의 트레이싱

트레이싱을 비활성화하지 않고도 OpenAI Traces dashboard에서 무료 트레이싱을 활성화하기 위해 비 OpenAI 모델에 OpenAI API 키를 사용할 수 있습니다. 어댑터 선택 및 설정 시 유의사항은 Models 가이드의 서드파티 어댑터 섹션을 참고하세요.

import os
from agents import set_tracing_export_api_key, Agent, Runner
from agents.extensions.models.any_llm_model import AnyLLMModel

tracing_api_key = os.environ["OPENAI_API_KEY"]
set_tracing_export_api_key(tracing_api_key)

model = AnyLLMModel(
    model="your-provider/your-model-name",
    api_key="your-api-key",
)

agent = Agent(
    name="Assistant",
    model=model,
)

단일 실행에 대해서만 다른 트레이싱 키가 필요하다면, 전역 exporter를 변경하는 대신 RunConfig를 통해 전달하세요.

from agents import Runner, RunConfig

await Runner.run(
    agent,
    input="Hello",
    run_config=RunConfig(tracing={"api_key": "sk-tracing-123"}),
)

추가 참고 사항

  • Openai Traces dashboard에서 무료 트레이스를 확인하세요

에코시스템 통합

다음 커뮤니티 및 벤더 통합은 OpenAI Agents SDK 트레이싱 표면을 지원합니다.

외부 트레이싱 프로세서 목록