> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 하위 에이전트 트레이싱

> Agent Lens의 하위 에이전트 span을 사용하여 하위 에이전트 위임을 트레이스하고 중첩된 에이전트 호출을 확인하세요.

이 가이드에서는 CoreWeave Agent Lens로 하위 에이전트를 트레이스하여, 위임된 에이전트 호출이 상위 턴과 같은 트레이스 안에 중첩된 span으로 표시되도록 하는 방법을 설명합니다. 하위 에이전트를 트레이싱하면 상위 에이전트가 어떤 전문 에이전트를 호출했는지, 그 에이전트가 무엇을 했는지, 최종 답변에 어떻게 기여했는지 등 에이전트 추론의 전체 계층 구조를 파악할 수 있습니다. 이 가이드는 Agent Lens로 멀티 에이전트 시스템을 계측하는 개발자를 대상으로 합니다.

하위 에이전트는 턴 안에서 실행되는 위임된 에이전트 호출입니다. 감독자 에이전트가 전문 에이전트에게 작업을 배분하는 경우처럼 한 에이전트가 다른 에이전트에게 작업을 넘길 때 하위 에이전트를 사용하세요.

Agent Lens로 계측한 하위 에이전트는 상위 턴과 같은 트레이스 안에 중첩된 `invoke_agent` OpenTelemetry(OTel) span을 생성합니다. **Conversations** 탭에서는 이 중첩 구조가 해당 하위 에이전트를 트리거한 턴 아래에 하위 에이전트 호출로 표시되며, 그 아래에 하위 에이전트의 LLM Call과 도구 Call이 그룹화되어 나타납니다.

<h2 id="sub-agent-data-model">
  하위 에이전트 데이터 모델
</h2>

코드를 계측하기 전에 Agent Lens가 트레이스에서 하위 에이전트를 어떻게 표현하는지 알아 두면 도움이 됩니다. `tracing.start_subagent` span은 OTel `invoke_agent` span에 매핑되며, 상위 턴과 동일한 오퍼레이션 이름을 내보냅니다. Agent Lens는 트레이스 내 부모-자식 관계를 기준으로 두 span을 구분합니다.

```plaintext theme={"system"}
Turn (root invoke_agent span)
├── LLM call (chat)              ← 상위 에이전트의 추론
│   └── SubAgent (invoke_agent)  ← 이 지점에서 위임 발생
│       ├── LLM call (chat)      ← 하위 에이전트 자체의 LLM Call
│       └── Tool call (execute_tool)
└── LLM call (chat)              ← 상위 에이전트가 최종 답변 종합
```

하위 에이전트는 활성 대화의 `conversation_id`를 상속하므로, **Conversations** 탭에서 해당 대화의 다른 항목과 함께 그룹화됩니다.

```python lines theme={"system"}
sub = tracing.start_subagent(
    name="research-specialist",   # 필수: UI에서 이 하위 에이전트를 식별하는 이름입니다.
    model="gpt-4o",               # 선택: 비워 두면 상위 대화의 모델을 기본값으로 사용합니다.
)
```

`tracing.start_subagent`는 `invoke_agent` span을 생성하며, 이 span은 OTel 컨텍스트에서 현재 활성 상태인 span의 하위 span이 자동으로 됩니다. 이 활성 span은 일반적으로 상위 턴이거나 위임을 트리거한 LLM Call입니다. 부모-자식 관계는 OTel 컨텍스트 전파로 처리되므로 위임을 명시적으로 지정할 필요가 없습니다.

<h2 id="trace-a-single-sub-agent">
  단일 하위 에이전트 트레이싱하기
</h2>

다음 예시에서는 감독자 에이전트가 요청을 받아 연구 전문 하위 에이전트에게 위임하고, 이 하위 에이전트는 Wikipedia 검색 도구를 사용해 답을 찾습니다.

Agent Lens는 대화를 `tracing.start_conversation`으로 감싸고 그 안을 다시 `conversation.start_turn`으로 감싸 전체 계층 구조를 캡처합니다. 그런 다음 전문 에이전트용 `tracing.start_subagent` 블록으로 하위 에이전트 트레이스를 캡처하고, 각 LLM Call과 도구 실행을 하위 span으로 기록합니다.

이 예시에서는 에이전트 간 트레이싱에 집중할 수 있도록 라우팅 로직을 의도적으로 생략했습니다.

```python lines highlight="6,7,10,16,22,30" theme={"system"}
from coreweave.forge.agentlens import tracing
from coreweave.forge.agentlens.tracing import Message, Usage

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

with tracing.start_conversation(agent_name="supervisor") as conversation:
    with conversation.start_turn(user_message="Research the founders of Anthropic.") as turn:

        # 감독자 LLM Call: 작업을 위임할 전문가를 결정합니다.
        with tracing.start_llm(model="gpt-4o", provider_name="openai") as llm:
            llm.input_messages = [Message(role="user", content="Research the founders of Anthropic.")]
            llm.output("Delegating to the research specialist.")
            llm.usage = Usage(input_tokens=80, output_tokens=10)

        # 연구 전문가를 하위 에이전트로 호출해 작업을 위임합니다.
        with tracing.start_subagent(name="research-specialist", model="gpt-4o") as sub:
            with sub.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                sub_llm.input_messages = [Message(role="user", content="Find founders of Anthropic.")]
                sub_llm.output("I should search for this.")
                sub_llm.usage = Usage(input_tokens=120, output_tokens=15)

                with tracing.start_tool(name="wikipedia_search", arguments='{"query":"Anthropic"}') as tool:
                    tool.result = "Anthropic was founded by Dario and Daniela Amodei in 2021."

            with sub.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                sub_llm.output("Anthropic was founded by Dario and Daniela Amodei in 2021.")
                sub_llm.usage = Usage(input_tokens=200, output_tokens=25)

        # 감독자 턴으로 돌아와 최종 답변을 종합합니다.
        with tracing.start_llm(model="gpt-4o", provider_name="openai") as llm:
            llm.output("Anthropic was founded by Dario and Daniela Amodei in 2021.")
            llm.usage = Usage(input_tokens=300, output_tokens=20)
```

**Conversations** 탭에서 하위 에이전트는 턴 내부에 중첩된 `invoke_agent` 블록으로 표시되며, 하위 에이전트의 LLM Call과 도구 Call은 그 아래에 그룹화됩니다. 슈퍼바이저가 직접 수행한 LLM Call은 하위 에이전트와 같은 수준의 형제 항목으로 남습니다.

<h2 id="trace-multiple-sub-agents">
  여러 하위 에이전트 트레이스하기
</h2>

다음 예시에서는 콘텐츠 파이프라인 에이전트를 실행합니다. 이 에이전트는 하나의 요청을 처리할 때 형제 관계인 세 하위 에이전트에 작업을 순서대로 위임합니다. 사실 정보를 수집하는 `researcher`, 게시물 초안을 작성하는 `writer`, 최종 출력을 다듬는 `reviewer`입니다.

Agent Lens는 하위 에이전트마다 별도의 `tracing.start_subagent` 블록을 열어 세 하위 에이전트를 모두 같은 턴 아래의 형제로 캡처합니다. 각 하위 에이전트가 활성 턴의 OTel 컨텍스트를 상속하므로, 하위 에이전트끼리 서로 중첩되지 않고 턴 아래에 중첩된 동등한 `invoke_agent` span으로 표시됩니다.

```python lines highlight="1,2,5,11,15,22" theme={"system"}
with tracing.start_conversation(agent_name="content-pipeline") as conversation:
    with conversation.start_turn(user_message="Write a short blog post about Anthropic.") as turn:

        # Researcher 하위 에이전트: 관련 사실을 수집합니다.
        with tracing.start_subagent(name="researcher", model="gpt-4o") as researcher:
            with researcher.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                sub_llm.input_messages = [Message(role="user", content="Find key facts about Anthropic.")]
                sub_llm.output("I should search Wikipedia.")
                sub_llm.usage = Usage(input_tokens=80, output_tokens=15)

                with tracing.start_tool(name="wikipedia_search", arguments='{"query":"Anthropic"}') as tool:
                    tool.result = "Anthropic was founded by Dario and Daniela Amodei in 2021."

        # Writer 하위 에이전트: 게시물 초안을 작성합니다.
        with tracing.start_subagent(name="writer", model="gpt-4o") as writer:
            with writer.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                sub_llm.input_messages = [Message(role="user", content="Draft a post using the research.")]
                sub_llm.output("Anthropic, founded in 2021 by Dario and Daniela Amodei, builds AI safety research...")
                sub_llm.usage = Usage(input_tokens=180, output_tokens=120)

        # Reviewer 하위 에이전트: 초안을 다듬습니다.
        with tracing.start_subagent(name="reviewer", model="gpt-4o") as reviewer:
            with reviewer.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                sub_llm.input_messages = [Message(role="user", content="Review and tighten the draft.")]
                sub_llm.output("Final post: Anthropic, founded in 2021 by Dario and Daniela Amodei, builds AI safety research...")
                sub_llm.usage = Usage(input_tokens=200, output_tokens=140)
```

**Conversations** 탭을 보면 턴에 형제 관계인 하위 에이전트 호출 세 개가 있고, 각 호출 아래에는 해당 호출의 LLM Call이 중첩되어 있으며, `researcher`에는 도구 Call도 포함되어 있습니다. 하위 에이전트는 서로 부모-자식 관계가 아닙니다.

<h2 id="trace-nested-sub-agents">
  중첩된 하위 에이전트 트레이스하기
</h2>

하위 에이전트는 또 다른 하위 에이전트에게 작업을 위임할 수 있습니다. 각 `start_subagent` 호출은 OTel 컨텍스트에서 현재 활성 상태인 span의 하위에 중첩됩니다.

```python lines highlight="1,2,4,5,11,16" theme={"system"}
with tracing.start_conversation(agent_name="orchestrator") as conversation:
    with conversation.start_turn(user_message="Compare Anthropic and OpenAI.") as turn:

        with tracing.start_subagent(name="research-coordinator") as coordinator:
            with tracing.start_subagent(name="anthropic-researcher") as r1:
                with r1.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                    sub_llm.output("Anthropic facts...")
                    sub_llm.usage = Usage(input_tokens=120, output_tokens=30)

                # 중첩: researcher가 자신의 summarizer 하위 에이전트에 작업을 위임합니다.
                with tracing.start_subagent(name="anthropic-summarizer") as summarizer:
                    with summarizer.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                        sub_llm.output("Anthropic summary: ...")
                        sub_llm.usage = Usage(input_tokens=80, output_tokens=20)

            with tracing.start_subagent(name="openai-researcher") as r2:
                with r2.llm(model="gpt-4o", provider_name="openai") as sub_llm:
                    sub_llm.output("OpenAI facts...")
                    sub_llm.usage = Usage(input_tokens=120, output_tokens=30)
```

이 예시를 실행하면 턴 아래에 3단계 중첩 구조가 생성됩니다.

```plaintext theme={"system"}
turn (invoke_agent)
└── research-coordinator (invoke_agent)
    ├── anthropic-researcher (invoke_agent)
    │   ├── chat
    │   └── anthropic-summarizer (invoke_agent)   ← anthropic-researcher 아래에 중첩됨
    │       └── chat
    └── openai-researcher (invoke_agent)          ← anthropic-researcher와 같은 수준(형제)
        └── chat
```

**Conversations** 탭에서 `research-coordinator`는 턴의 하위 에이전트로 표시되고, `anthropic-researcher`와 `openai-researcher`는 코디네이터 아래에 형제 항목으로 표시되며, `anthropic-summarizer`는 `anthropic-researcher`의 하위 에이전트로 표시됩니다.
