메인 콘텐츠로 건너뛰기
Weave for Agents는 공개 프리뷰 상태입니다. 정식 출시 전에 특성, API 및 Agents 뷰 UI가 변경될 수 있습니다.
W&B Weave SDK를 사용해 멀티턴 에이전트형 애플리케이션을 계측하고, 에이전트의 동작을 확인하고 디버그하며 평가하는 방법을 알아보세요. 이 가이드는 에이전트를 구축하거나 통합하면서 세션, 턴, LLM 호출, 도구 실행을 구조화된 방식으로 파악하려는 개발자를 위한 것입니다. 에이전트용 Weave SDK는 멀티턴 에이전트 대화의 전체 라이프사이클을 모델링합니다. 즉, 여러 세션을 소유하는 에이전트, 턴을 함께 묶는 세션, 각각의 사용자-에이전트 상호작용(턴), 턴 내의 LLM 호출, 그리고 LLM이 트리거하는 도구 실행까지 포함합니다. 트레이스는 Weave 프로젝트의 Agents 탭에 표시됩니다. 각 세션에는 중첩된 도구 Call, token 사용량, feedback이 포함된 멀티턴 타임라인이 표시됩니다. 개별 함수를 Ops로 @weave.op decorator를 사용해 트레이싱하는 경우에는 LLM 애플리케이션 트레이스를 참조하세요.

시작하기 전에

시작하려면 weave 패키지를 설치하고 프로젝트를 초기화하세요. 이 단계에서는 팀과 프로젝트를 Weave에 등록하여 SDK가 UI에서 span을 올바른 위치로 라우팅하도록 합니다.
pip install weave
[YOUR-TEAM]은 W&B 팀 이름으로, [YOUR-PROJECT]는 W&B 프로젝트 이름으로 바꾸세요.
import weave

weave.init("[YOUR-TEAM]/[YOUR-PROJECT]")
start_session(), start_turn(), start_llm(), start_tool()를 호출하기 전에 weave.init()를 먼저 호출하세요. 트레이싱이 비활성화되어 있거나 init 호출이 없으면 모든 에이전트 트레이싱 함수는 조용히 no-op로 동작하므로, 프로덕션 코드에 계측을 그대로 남겨 두고 설정을 통해 제어할 수 있습니다.

에이전트 데이터 모델

Weave는 에이전트 동작을 일대다 관계의 계층 구조로 모델링합니다. 각 에이전트는 여러 세션을 가질 수 있고, 각 세션은 여러 턴을 가질 수 있으며, 각 턴은 여러 LLM Call을 가질 수 있고, 각 LLM Call은 여러 도구 Call을 트리거할 수 있습니다.
개념Weave SDK 클래스OTel span 유형설명
에이전트(클래스 없음)(span 없음, agent_name으로 그룹화됨)Agents 탭의 에이전트형 애플리케이션으로, 하나 이상의 세션을 포함합니다
세션Session(span 없음, 턴은 conversation_id로 그룹화됨)하나 이상의 턴을 포함하는 대화 또는 run입니다
Turninvoke_agent사용자 메시지 1개와 에이전트의 전체 응답입니다
LLM CallLLMchat언어 모델 API에 대한 단일 LLM Call입니다
도구 CallToolexecute_toolLLM 응답으로 트리거되는 단일 도구 Call입니다
다음 다이어그램은 하나의 에이전트에 여러 세션이 있고, 하나의 세션에 여러 턴이 있으며, 이런 식으로 이어지는 구조를 보여줍니다. 세션은 상위 span이 아니라 공통 conversation_id 속성을 기준으로 턴을 그룹화하므로, 각 턴이 자체 OTel 트레이스를 시작합니다. 이 설계는 분산 트레이싱과 병렬 실행을 지원합니다. 클라이언트는 서버 측 집계 없이 span을 OTel collector로 직접 전송합니다.
Claude Agent SDK 또는 Codex와 같은 SDK나 하니스와 Weave를 통합하려면 Trace agent integrations를 참조하세요. Weave는 빠르게 통합할 수 있도록 여러 에이전트 구축 SDK와 에이전트 하니스에 자동 patch를 적용합니다.

에이전트 트레이싱 API

다음 섹션에서는 각 최상위 트레이싱 함수와 해당 함수가 받는 인수를 설명합니다. 이를 사용해 이전 섹션에서 설명한 데이터 모델의 Session, 턴, LLM Call, 도구 Call 계층을 계측하세요. Weave는 다음과 같은 최상위 함수를 제공합니다. 각 함수의 반환값은 컨텍스트 관리자(Python에서는 with, TypeScript에서는 try/finally 사용)로 사용할 수 있는 객체이거나, .end()를 호출해 수동으로 종료할 수 있는 객체입니다.

Session 시작하기

start_session() / startSession()는 모든 하위 span에 conversation_id 속성을 설정해 Agents 탭에서 턴이 그룹화되도록 합니다. session_id를 전달하는 경우, 대화가 지속되는 동안 안정적으로 유지되어야 합니다. 기존 Session에 새 턴을 추가하려면 동일한 ID를 재사용하세요. session_id를 생략하면 SDK가 UUID를 자동으로 생성합니다. 활성 Session은 컨텍스트(Python ContextVar 또는 Node.js AsyncLocalStorage)에 저장되므로, 같은 비동기 컨텍스트에서 실행되는 코드는 Session 객체를 명시적으로 전달하지 않아도 weave.get_current_session() / weave.getCurrentSession()으로 조회할 수 있습니다.
session = weave.start_session(
    agent_name="my-agent",    # 필수: UI에서 에이전트를 식별합니다.
    session_id="",            # 선택: 턴을 그룹화하는 안정적인 ID입니다. 비어 있으면 자동 생성됩니다.
    model="",                 # 선택: 이 Session의 턴에 사용할 기본 모델입니다.
    session_name="",          # 선택: UI에 표시되는 사람이 읽기 쉬운 레이블입니다.
    include_content=True,     # 선택: 메시지 본문을 span에서 제외하려면 False로 설정합니다.
    continue_parent_trace=False,  # 선택: 새 OTel 트레이스를 시작하는 대신 기존 트레이스에 연결합니다.
)

턴 시작

start_turn() / startTurn()은 새 OTel 트레이스의 루트가 되는 새로운 invoke_agent span을 생성합니다. Weave는 타임라인 뷰에서 이 span을 사용해 사용자와 에이전트 간의 한 번의 전체 상호작용을 나타냅니다. 최상위 함수로 호출하면 컨텍스트에서 활성 Session을 찾아 해당 conversation ID를 상속받습니다. 활성 Session이 없으면 Weave는 conversation_id 없이 턴을 생성하며 다른 턴과 함께 그룹화하지 않습니다.
turn = weave.start_turn(
    user_message="What is the weather in Tokyo?",  # 사용자의 입력 텍스트입니다.
    agent_name="my-agent",   # 선택 사항: Session 수준의 에이전트 이름을 재정의합니다.
    model="gpt-4o",          # 선택 사항: 이 턴에 사용되는 모델입니다.
)

LLM Call 시작

start_llm() / startLLM()은 현재 턴 아래에 중첩되는 chat span을 생성합니다. Weave는 이 span을 사용해 Agents 뷰에서 토큰 사용량, 모델 이름, 입력 및 출력 메시지, 추론을 표시합니다.
llm = weave.start_llm(
    model="gpt-4o",             # 모델 식별자입니다.
    provider_name="openai",     # 필수: 공급자 이름(예: "openai", "anthropic")
    system_instructions=["Be concise."],  # 선택: system 프롬프트 string 목록입니다.
)
LLM Call이 완료되면 닫히기 전에 응답 데이터를 llm 객체에 할당하세요:
with weave.start_llm(model="gpt-4o", provider_name="openai") as llm:
    response = openai_client.chat.completions.create(...)
    llm.input_messages = [Message(role="user", content="...")]
    llm.output_messages = [Message(role="assistant", content=response.choices[0].message.content)]
    llm.usage = Usage(
        input_tokens=response.usage.prompt_tokens,
        output_tokens=response.usage.completion_tokens,
    )
provider_name / providerName은 명시적으로 전달하세요. Weave는 모델 문자열에서 이를 추론하지 않습니다.

도구 Call 시작

start_tool() / startTool()execute_tool span을 생성합니다. 이 span은 컨텍스트에서 현재 활성화된 OTel span의 하위 span이 됩니다(일반적으로 도구 Call을 생성한 LLM 호출의 chat span).
tool = weave.start_tool(
    name="get_weather",                  # LLM에 선언된 도구 이름입니다.
    arguments='{"city": "Tokyo"}',       # 도구 인수의 JSON string입니다.
    tool_call_id="call_abc123",          # 선택 사항: LLM 응답의 도구 Call ID입니다.
)
닫기 전에 도구 결과를 부여하세요:
with weave.start_tool(name="get_weather", arguments='{"city": "Tokyo"}') as tool:
    result = get_weather_api("Tokyo")
    tool.result = result  # dict, 목록 또는 string을 받을 수 있습니다. 자동으로 JSON 인코딩됩니다.

에이전트 트레이싱 사용 패턴

다음 섹션에서는 에이전트 코드 구조에 따라 이러한 함수들을 어떻게 조합할 수 있는지 설명합니다. 아래 예시에서는 Weave SDK의 두 가지 유형을 사용합니다.
  • Message는 대화의 단일 항목을 나타냅니다. 예를 들어 사용자 입력, 어시스턴트 응답, system 프롬프트, 또는 도구 결과가 이에 해당합니다. 모델이 무엇을 입력받고 어떤 출력을 생성했는지 기록하려면 llm.input_messages / llm.inputMessages에 할당하세요.
  • Usage는 LLM 응답의 token 수를 캡처하며, llm.usage에 할당됩니다.
Weave는 이 두 가지를 모두 사용해 Agents 뷰에 각 LLM 호출의 입력, 출력, token 사용량을 표시합니다. 지원되는 모든 데이터 유형은 API 레퍼런스를 참조하세요.

컨텍스트 매니저 또는 try-finally 패턴

대부분의 에이전트에는 Python에서는 컨텍스트 매니저 패턴을, TypeScript에서는 try-finally 패턴을 사용하는 방식이 권장됩니다. 예외가 발생하더라도 블록이 끝날 때 span이 닫히고 전송됩니다. Weave는 현재 활성 Session, 턴, LLM 호출을 컨텍스트에 저장하므로, 블록 내에서 호출되는 모든 함수는 상위를 명시적으로 참조하지 않아도 start_llm() / startLLM() 또는 start_tool() / startTool()을 호출할 수 있습니다. 이 방식은 코드가 동일한 async 컨텍스트에서 실행되는 한 모듈 경계를 넘어도 작동합니다. 호출 스택 어디에서든 현재 활성 객체를 조회하려면 weave.get_current_session() / weave.getCurrentSession(), weave.get_current_turn() / weave.getCurrentTurn(), weave.get_current_llm() / weave.getCurrentLLM()을 사용하세요.
import weave
from weave.session.session import Message, Usage

# 플레이스홀더 함수입니다. 자체 구현으로 바꾸세요.
def call_openai(*args, **kwargs):
    pass  # 자체 LLM 클라이언트 호출로 바꾸세요.

def get_weather_api(city: str) -> str:
    return "24°C, sunny"  # 자체 날씨 API 호출로 바꾸세요.

weave.init("[YOUR-TEAM]/[YOUR-PROJECT]")

with weave.start_session(agent_name="weather-bot") as session:
    with session.start_turn(user_message="What is the weather in Tokyo?") as turn:

        # 첫 번째 LLM 호출: 도구 Call을 반환합니다.
        with weave.start_llm(model="gpt-4o", provider_name="openai") as llm:
            response = call_openai(...)
            llm.input_messages = [Message(role="user", content="What is the weather?")]
            llm.think("User wants weather data, I should call get_weather.")
            llm.output("Let me check the weather for you.")
            llm.usage = Usage(input_tokens=100, output_tokens=20)

            # 도구 Call: 이를 요청한 LLM 호출의 하위 요소입니다.
            with weave.start_tool(name="get_weather", arguments='{"city":"Tokyo"}') as tool:
                tool.result = get_weather_api("Tokyo")  # "24°C, sunny"를 반환합니다.

        # 두 번째 LLM 호출: 최종 답변을 생성합니다.
        with weave.start_llm(model="gpt-4o", provider_name="openai") as llm:
            llm.input_messages = [Message(role="user", content="What is the weather?")]
            llm.output("It is 24°C and sunny in Tokyo today.")
            llm.usage = Usage(input_tokens=150, output_tokens=30)

수동으로 시작하고 종료하는 패턴

with 블록이나 try/finally를 사용할 수 없을 때는 .end()를 명시적으로 사용하세요. 예를 들어, span을 서로 다른 함수 호출에서 시작하고 종료하는 경우나 코루틴 외부에서 비동기 라이프사이클을 관리하는 경우가 이에 해당합니다. 생성한 모든 객체에 대해 .end()를 호출해 span이 종료되고 collector로 플러시되도록 하는 것은 사용자 책임입니다.
session = weave.start_session(agent_name="weather-bot")
turn = session.start_turn(user_message="What is the weather?")

llm = weave.start_llm(model="gpt-4o", provider_name="openai")
llm.input_messages = [Message(role="user", content="What is the weather?")]
llm.output("Let me check.")
llm.usage = Usage(input_tokens=100, output_tokens=20)

tool = weave.start_tool(name="get_weather", arguments='{"city": "Tokyo"}')
tool.result = "24°C, sunny"
tool.end()   # end()는 멱등적이므로 여러 번 호출해도 안전합니다.

llm.end()

llm2 = weave.start_llm(model="gpt-4o", provider_name="openai")
llm2.output("It is 24°C and sunny in Tokyo.")
llm2.usage = Usage(input_tokens=150, output_tokens=30)
llm2.end()

turn.end()
session.end()

시맨틱 규약

Weave SDK는 GenAI 시맨틱 규약GenAI 에이전트 span 규약을 준수하는 OTel span을 내보냅니다. Weave는 어떤 OTel span이든 허용하고, 모든 속성을 저장하며 쿼리할 수 있도록 합니다. 표준 OTel span API와 Weave의 트레이싱 객체를 함께 사용해 span에 임의의 속성을 추가할 수 있습니다.

Weave UI에서 span이 표시되는 방식

앞서 설명한 패턴으로 에이전트에 계측을 적용하고 실행하면 트레이스가 Weave 프로젝트의 https://wandb.ai/[YOUR-TEAM]/[YOUR-PROJECT]/weave/agents에 있는 Agents 탭에 표시됩니다.
  • Sessions list에는 턴 활동의 미니맵과 함께 모든 세션이 표시됩니다.
  • 세션을 클릭하면 각 턴, 해당 턴의 LLM calls, 도구 실행, 토큰 수, 그리고 연결된 피드백을 보여주는 multi-turn session view가 열립니다.
  • chat span에는 입력 메시지, 출력 메시지, 모델 이름, 사용이 표시됩니다.
  • execute_tool span에는 도구 이름, 인수, 결과가 표시됩니다.
Weave에서 Agents 데이터를 보는 방법에 대한 자세한 내용은 에이전트 활동 보기를 참조하세요.