Claude Agent SDK

Claude Agent SDK

Claude Code의 에이전트 능력을 활용해 애플리케이션을 만들 때, 그 실행도 Confident AI로 추적하고 싶어요. Claude Agent SDK를 쓰는 Python 애플리케이션을 confident-trace가 추적하고, SDK의 Claude Code 서브프로세스가 OpenTelemetry로 내보내도록 구성해 줍니다.

출처: 문서

본문

개요

Claude Agent SDK는 Claude Code의 에이전트 능력으로 애플리케이션을 만들게 해 줍니다. confident-trace는 Python 애플리케이션을 추적하고, SDK의 Claude Code 서브프로세스가 OpenTelemetry로 내보내도록 구성해요.

네이티브 추적은 실험적입니다. confident-trace 통합은 성공적인 Claude 실행에서 네이티브 스팬이 빠지거나 모델 스팬이 부모 트레이스와 끊어지는 경우를 관찰했어요. 아래 설정은 명시적인 Python 호출 스팬을 사용하고 자식 프로세스 텔레메트리를 꺼서, 신뢰할 수 있는 애플리케이션 트레이스를 제공합니다. Claude 내부의 모델·도구 스팬은 포착하지 않아요.

Runtime Requirements Setup
Python Python 3.10+, claude-agent-sdk, and Claude authentication Call init() and wrap the query in span()
TypeScript Not supported by this confident-trace integration —

자동 계측

EU 리전 사용자는 OTEL 엔드포인트를 EU 버전으로 설정하세요. 그렇지 않으면 트레이스가 우리 US 서버로 보내집니다.

export CONFIDENT_OTEL_ENDPOINT="https://eu.otel.confident-ai.com/v1/traces"

의존성 설치

필요한 패키지를 설치하는 명령을 실행하세요.

pip install confident-trace claude-agent-sdk

Confident AI 키 설정

Confident AI Project API key를 받아 환경 변수로 설정하거나, init()에 직접 전달하세요. 애플리케이션용 Claude 인증을 구성하세요 — 이 예제는 Anthropic API 키를 사용합니다.

export CONFIDENT_API_KEY="<your-confident-api-key>"
export ANTHROPIC_API_KEY="<your-anthropic-key>"
from confident_trace import init

init(api_key="<your-confident-api-key>")

Claude Agent SDK 계측

시작 시 init()을 한 번 호출하고, 쿼리 주위에 스팬을 만드세요. 어댑터는 ClaudeAgentOptions.env의 명시적 텔레메트리 비활성화 스위치를 존중하며, 바깥 호출 스팬을 자동으로 만들지 않아요.

import asyncio

from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query
from confident_trace import init, shutdown, span


async def main():
    init()
    try:
        options = ClaudeAgentOptions(
            max_turns=3,
            env={"CLAUDE_CODE_ENABLE_TELEMETRY": "0"},
        )
        with span("claude.invocation"):
            async for message in query(
                prompt="Explain OpenTelemetry in one sentence.",
                options=options,
            ):
                if isinstance(message, ResultMessage):
                    print(message.result)
    finally:
        shutdown()


asyncio.run(main())

한 번 초기화하고, 한 번 종료하세요. 장기 실행 서버에서는 시작 시 init()을, 정상 종료 시 활성 쿼리가 끝난 뒤 shutdown()을 호출하세요 — 요청마다 하지 마세요. 한 번 초기화를 참고하세요.

에이전트 실행

스크립트를 실행해 호출 스팬을 Confident AI로 보내세요.

python main.py

완료 ✅. Confident AI 프로젝트에서 Observatory를 열어 Python 호출 스팬을 확인하세요.

트레이스가 안 보이면, 종료 전에 반드시 shutdown()(장기 실행 프로세스에선 flush())을 호출하세요 — 트러블슈팅 페이지를 참고하세요.

무엇이 포착되나

위 설정으로 Confident AI는 Claude 쿼리 주위의 애플리케이션 경계를 포착합니다.

  • 호출 수명 주기 — 스팬 범위를 벗어나는 예외에 대한 스팬 이름, 타이밍, 오류 상태
  • 트레이스 속성 — Python 트레이스에 붙인 태그, 메타데이터, 사용자 ID, 스레드 ID
  • 커스텀 스팬 — 호출 범위 안에서 만든 추가 애플리케이션 스팬

래퍼는 Claude Code 안의 프롬프트, 응답, 모델 호출, 도구 호출, 토큰 사용량을 자동으로 포착하지 않아요. 애플리케이션 입력·출력은 스팬 속성으로 추가할 수 있습니다. 자식 텔레메트리를 끄면 그 자식의 네이티브 메트릭과 로그도 꺼지지만, Python 추적은 활성 상태로 유지돼요.

실험적 네이티브 추적

네이티브 Claude 추적을 시도하려면, 예제에서 CLAUDE_CODE_ENABLE_TELEMETRY 오버라이드를 제거하세요. query() 전이나 ClaudeSDKClient 연결 전에 init()을 호출하세요. 통합은 기본 서브프로세스 전송을 확인된 OTLP 트레이스 엔드포인트, 인증 헤더, 프로토콜, Claude의 텔레메트리 스위치로 구성합니다.

네이티브 스팬은 Claude Code에서 컬렉터로 직접 내보내집니다. Python의 TracerProvider를 거치지 않으므로, Python in-memory exporter는 받지 못해요. 네이티브 스팬 콘텐츠, 이름, 전달은 Claude Code 버전에 달려 있습니다. Claude의 관찰 문서를 참고하세요.

  • 서브프로세스가 연결될 때 활성 W3C 컨텍스트가 전파되지만, 연결된 네이티브 트레이스는 보장되지 않아요. 장기 생존 ClaudeSDKClient는 각 쿼리에 대한 새 부모가 아니라 연결 시점의 컨텍스트를 상속합니다.
  • query()를 ResultMessage를 받은 후에도 반복자 끝까지 소비하세요. Python의 flush()와 shutdown()은 자식 프로세스를 플러시하지 않아요. 쿼리를 완전히 소비하는 것은 필요하지만, 네이티브 스팬 전달을 보장하지는 않습니다.
  • ClaudeAgentOptions.env의 명시적 exporter 설정은 자식의 연결 구성을 소유해요. 목적지와 인증을 함께 공급하세요. Confident AI 자격 증명은 그 오버라이드에 주입되지 않아요. 커스텀 전송은 그대로 남습니다.
  • Confident 트레이스 메타데이터, 스레드 속성, 콘텐츠 제어는 자식 프로세스 스팬에 자동 적용되지 않아요.

관찰된 제한 사항은 confident-trace 네이티브 추적 조사를 참고하세요. 빠지거나 끊긴 네이티브 스팬은 Python 플러시 타임아웃을 늘린다고 고쳐지지 않아요.

트레이스 스팬 속성 설정

호출 스팬을 만들기 전에 속성을 추가하려면 트레이스 컨텍스트를 사용하세요. 트레이스 컨텍스트는 추가 스팬을 만들지 않고, Python 호출 스팬이 그 속성을 상속받습니다.

from confident_trace import span, trace_context

# Inside your async application, after init().
with trace_context(
    tags=["support"],
    metadata={"release": "2026-09"},
    user_id="user-42",
    customer_id="customer-7",
):
    with span("claude.invocation"):
        async for message in query(prompt="Explain OpenTelemetry.", options=options):
            pass

자식 텔레메트리를 끈 상태로 두려면 위 설정의 options를 사용하세요. 각 ID와 함께 선택적 표시 이름을 설정하려면 사용자와 고객을, 지원되는 모든 트레이스 속성과 갱신 동작은 트레이스 컨텍스트를 참고하세요.

다중 턴 계측

각 대화 턴의 Python 트레이스를 만들려면 turn()을 사용하세요. 이후 턴에서 같은 스레드 ID를 재사용해 Confident AI에서 하나의 대화로 묶으면 돼요. 이는 트레이스를 묶는 것이지, Claude의 세션 기록을 관리하는 게 아니에요.

from confident_trace import turn

# Inside your async application, after init().
with turn("support-turn", thread_id="chat-42"):
    async for message in query(prompt="Explain OpenTelemetry.", options=options):
        pass

스레드 입출력, 턴 ID, 사용자 ID는 스레드를 참고하세요.

Claude Agent SDK 계측 비활성화

통합 식별자는 "claude_agent_sdk"입니다. 특정 통합만 활성화하려면 init()에 식별자 목록을 전달하고, 이 식별자를 빼면 서브프로세스 어댑터가 비활성화돼요. 빈 목록은 모든 자동 계측을 비활성화하면서 커스텀 Python 스팬은 남겨 둡니다.

from confident_trace import init

init(instrumentations=())

이렇게 하면 Confident AI가 향후 서브프로세스 전송을 구성하지 않아요. 이미 연결된 자식의 텔레메트리는 끄지 않습니다. Claude의 네이티브 텔레메트리를 명시적으로 끄려면 자식을 만들 때 ClaudeAgentOptions(env={"CLAUDE_CODE_ENABLE_TELEMETRY": "0"})를 사용하세요.

다음 단계

커스텀 애플리케이션 스팬

Claude 쿼리 주위에 입력, 출력, 애플리케이션 스팬을 추가하세요.

Threads

같은 대화의 호출 트레이스를 스레드로 묶으세요.

더 알아보기

  • Online Evals — 수집되는 트레이스·스팬을 실시간으로 평가
  • Threads — 대화를 스레드로 묶어 평가