메인 콘텐츠로 건너뛰기
OpenTelemetry (OTEL)을 사용하여 Weave에서 Google Agent Development Kit (ADK) 에이전트 및 툴 호출을 추적할 수 있습니다. ADK는 AI 에이전트를 개발하고 배포하기 위한 유연하고 모듈화된 프레임워크입니다. Gemini와 Google 에코시스템에 최적화되어 있지만, ADK는 모델 및 배포에 독립적입니다. 단순한 작업부터 복잡한 워크플로우에 이르기까지 에이전트 아키텍처를 생성, 배포 및 오케스트레이션하기 위한 툴을 제공합니다. 이 가이드에서는 OTEL을 사용하여 ADK 에이전트 및 툴 호출을 추적하고, 해당 트레이스를 Weave에서 시각화하는 방법을 설명합니다. 필수 종속성 설치, Weave로 데이터를 전송하기 위한 OTEL tracer 설정, 그리고 ADK 에이전트 및 툴의 계측 방법을 배우게 됩니다.
Weave의 OTEL 추적에 대한 자세한 내용은 Send OTEL Traces to Weave를 참조하세요.

사전 요구 사항

  1. 필수 종속성을 설치합니다:
    pip install google-adk opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
    
  2. Google API 키를 환경 변수로 설정합니다:
    export GOOGLE_API_KEY=your_api_key_here
    
  3. Weave에서 OTEL 추적 설정을 수행합니다.

Weave에서 OTEL 추적 설정

ADK에서 Weave로 트레이스를 보내려면 TracerProviderOTLPSpanExporter로 OTEL을 구성해야 합니다. 인증 및 프로젝트 식별을 위한 올바른 엔드포인트와 HTTP 헤더로 exporter를 설정하세요.
API 키 및 프로젝트 정보와 같은 민감한 환경 변수는 환경 파일(예: .env)에 저장하고 os.environ을 사용하여 로드하는 것이 좋습니다. 이를 통해 자격 증명을 안전하게 유지하고 코드 베이스에 노출되지 않도록 할 수 있습니다.

필수 설정

  • Endpoint: https://trace.wandb.ai/otel/v1/traces. 전용 Weave 인스턴스를 사용하는 경우 URL은 다음 패턴을 따릅니다: {YOUR_WEAVE_HOST}/traces/otel/v1/traces
  • Headers:
    • Authorization: W&B API 키를 사용한 기본 인증(Basic auth)
    • project_id: W&B 엔티티/프로젝트 이름 (예: myteam/myproject)

ADK에서 Weave로 OTEL 트레이스 전송

다음 코드 조각은 ADK 애플리케이션에서 Weave로 OTEL 트레이스를 전송하기 위해 OTLP span exporter 및 tracer provider를 설정하는 방법을 보여줍니다.
Weave가 ADK를 올바르게 추적하도록 하려면 코드에서 ADK 컴포넌트를 사용하기 _전_에 글로벌 tracer provider를 설정하세요.
import base64
import os
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk import trace as trace_sdk
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry import trace

# 환경 변수에서 민감한 값 로드
WANDB_BASE_URL = "https://trace.wandb.ai"
# W&B 엔티티/프로젝트 이름 (예: "myteam/myproject")
PROJECT_ID = os.environ.get("WANDB_PROJECT_ID")  
# https://wandb.ai/settings 에서 W&B API 키를 생성하세요
WANDB_API_KEY = os.environ.get("WANDB_API_KEY")  

OTEL_EXPORTER_OTLP_ENDPOINT = f"{WANDB_BASE_URL}/otel/v1/traces"
AUTH = base64.b64encode(f"api:{WANDB_API_KEY}".encode()).decode()

OTEL_EXPORTER_OTLP_HEADERS = {
    "Authorization": f"Basic {AUTH}",
    "project_id": PROJECT_ID,
}

# 엔드포인트와 헤더를 사용하여 OTLP span exporter 생성
exporter = OTLPSpanExporter(
    endpoint=OTEL_EXPORTER_OTLP_ENDPOINT,
    headers=OTEL_EXPORTER_OTLP_HEADERS,
)

# tracer provider를 생성하고 exporter를 추가
tracer_provider = trace_sdk.TracerProvider()
tracer_provider.add_span_processor(SimpleSpanProcessor(exporter))

# ADK를 임포트하거나 사용하기 전에 글로벌 tracer provider 설정
trace.set_tracer_provider(tracer_provider)

OTEL로 ADK 에이전트 추적

tracer provider를 설정한 후 자동 추적 기능이 포함된 ADK 에이전트를 생성하고 실행할 수 있습니다. 다음 예시는 툴이 포함된 간단한 LLM 에이전트를 생성하고 인메모리 러너로 실행하는 방법을 보여줍니다:
from google.adk.agents import LlmAgent
from google.adk.runners import InMemoryRunner
from google.adk.tools import FunctionTool
from google.genai import types
import asyncio

# 시연을 위한 간단한 툴 정의
def calculator(a: float, b: float) -> str:
    """두 숫자를 더하고 결과를 반환합니다.

    Args:
        a: 첫 번째 숫자
        b: 두 번째 숫자

    Returns:
        a와 b의 합계
    """
    return str(a + b)

calculator_tool = FunctionTool(func=calculator)

async def run_agent():
    # LLM 에이전트 생성
    agent = LlmAgent(
        name="MathAgent",
        model="gemini-2.0-flash",  # 필요한 경우 다른 모델로 변경 가능
        instruction=(
            "당신은 수학을 할 수 있는 유용한 비서입니다. "
            "수학 문제가 주어지면 calculator 툴을 사용하여 해결하세요."
        ),
        tools=[calculator_tool],
    )

    # 러너 설정
    runner = InMemoryRunner(agent=agent, app_name="math_assistant")
    session_service = runner.session_service

    # 세션 생성
    user_id = "example_user"
    session_id = "example_session"
    await session_service.create_session(
        app_name="math_assistant",
        user_id=user_id,
        session_id=session_id,
    )

    # 툴 사용을 트리거할 메시지와 함께 에이전트 실행
    async for event in runner.run_async(
        user_id=user_id,
        session_id=session_id,
        new_message=types.Content(
            role="user", parts=[types.Part(text="5 + 7은 무엇인가요?")]
        ),
    ):
        if event.is_final_response() and event.content:
            print(f"Final response: {event.content.parts[0].text.strip()}")

# 비동기 함수 실행
asyncio.run(run_agent())
모든 에이전트 작업은 자동으로 추적되어 Weave로 전송되므로 실행 흐름을 시각화할 수 있습니다. 모델 호출, 추론 단계 및 툴 호출을 확인할 수 있습니다.
ADK 에이전트의 트레이스 시각화

OTEL로 ADK 툴 추적

ADK에서 툴을 정의하고 사용하면 이러한 툴 호출도 트레이스에 캡처됩니다. OTEL 인테그레이션은 에이전트의 추론 프로세스와 개별 툴 실행을 모두 자동으로 계측하여 에이전트 행동에 대한 포괄적인 뷰를 제공합니다. 다음은 여러 툴을 사용하는 예시입니다:
from google.adk.agents import LlmAgent
from google.adk.runners import InMemoryRunner
from google.adk.tools import FunctionTool
from google.genai import types
import asyncio

# 여러 툴 정의
def add(a: float, b: float) -> str:
    """두 숫자를 더합니다.
    
    Args:
        a: 첫 번째 숫자
        b: 두 번째 숫자
        
    Returns:
        a와 b의 합계
    """
    return str(a + b)

def multiply(a: float, b: float) -> str:
    """두 숫자를 곱합니다.
    
    Args:
        a: 첫 번째 숫자
        b: 두 번째 숫자
        
    Returns:
        a와 b의 곱
    """
    return str(a * b)

# 함수 툴 생성
add_tool = FunctionTool(func=add)
multiply_tool = FunctionTool(func=multiply)

async def run_agent():
    # 여러 툴을 가진 LLM 에이전트 생성
    agent = LlmAgent(
        name="MathAgent",
        model="gemini-2.0-flash",
        instruction=(
            "당신은 수학 연산을 수행할 수 있는 유용한 비서입니다. "
            "숫자를 더하라는 요청을 받으면 add 툴을 사용하세요. "
            "숫자를 곱하라는 요청을 받으면 multiply 툴을 사용하세요."
        ),
        tools=[add_tool, multiply_tool],
    )

    # 러너 설정
    runner = InMemoryRunner(agent=agent, app_name="math_assistant")
    session_service = runner.session_service

    # 세션 생성
    user_id = "example_user"
    session_id = "example_session"
    await session_service.create_session(
        app_name="math_assistant",
        user_id=user_id,
        session_id=session_id,
    )

    # 툴 사용을 트리거할 메시지와 함께 에이전트 실행
    async for event in runner.run_async(
        user_id=user_id,
        session_id=session_id,
        new_message=types.Content(
            role="user", parts=[types.Part(text="먼저 5와 7을 더한 다음, 그 결과에 2를 곱하세요.")]
        ),
    ):
        if event.is_final_response() and event.content:
            print(f"Final response: {event.content.parts[0].text.strip()}")

# 비동기 함수 실행
asyncio.run(run_agent())
ADK 툴 호출의 트레이스 시각화

워크플로우 에이전트 작업

ADK는 더 복잡한 시나리오를 위해 다양한 workflow agents를 제공합니다. 일반 LLM 에이전트와 마찬가지로 워크플로우 에이전트도 추적할 수 있습니다. 다음은 SequentialAgent를 사용한 예시입니다:
from google.adk.agents import LlmAgent, SequentialAgent
from google.adk.runners import InMemoryRunner
from google.genai import types
import asyncio

async def run_workflow():
    # 두 개의 LLM 에이전트 생성
    summarizer = LlmAgent(
        name="Summarizer",
        model="gemini-2.0-flash",
        instruction="주어진 텍스트를 한 문장으로 요약하세요.",
        description="텍스트를 한 문장으로 요약함",
        output_key="summary"  # 출력을 state['summary']에 저장
    )
    
    analyzer = LlmAgent(
        name="Analyzer",
        model="gemini-2.0-flash",
        instruction="주어진 텍스트의 감정을 긍정, 부정 또는 중립으로 분석하세요. 분석할 텍스트: {summary}",
        description="텍스트의 감정을 분석함",
        output_key="sentiment"  # 출력을 state['sentiment']에 저장
    )
    
    # 순차적 워크플로우 생성
    workflow = SequentialAgent(
        name="TextProcessor",
        sub_agents=[summarizer, analyzer],
        description="요약 후 감정 분석을 수행하는 시퀀스를 실행합니다.",
    )
    
    # 러너 설정
    runner = InMemoryRunner(agent=workflow, app_name="text_processor")
    session_service = runner.session_service
    
    # 세션 생성
    user_id = "example_user"
    session_id = "example_session"
    await session_service.create_session(
        app_name="text_processor",
        user_id=user_id,
        session_id=session_id,
    )
    
    # 워크플로우 실행
    async for event in runner.run_async(
        user_id=user_id,
        session_id=session_id,
        new_message=types.Content(
            role="user", 
            parts=[types.Part(text="이 제품은 제 기대를 뛰어넘었습니다. 상자에서 꺼내자마자 완벽하게 작동했고, 설치에 대해 문의했을 때 고객 서비스도 훌륭했습니다.")]
        ),
    ):
        if event.is_final_response() and event.content:
            print(f"Final response: {event.content.parts[0].text.strip()}")

# 비동기 함수 실행
asyncio.run(run_workflow())
이 워크플로우 에이전트 트레이스는 Weave에서 두 에이전트의 순차적 실행을 보여주며, 멀티 에이전트 시스템을 통해 데이터가 어떻게 흐르는지에 대한 가시성을 제공합니다.
Sequential 워크플로우 에이전트의 트레이스 시각화

더 알아보기