> ## 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 のサブエージェントスパンを使用して、サブエージェントへの委譲をトレースし、ネストされたエージェントの invocation を表示します。

このガイドでは、CoreWeave Agent Lens を使用してサブエージェントをトレースし、委譲されたエージェントの invocation を、親ターンと同じトレース内にネストされたスパンとして表示する方法を説明します。サブエージェントをトレースすると、親エージェントがどの専門エージェントを呼び出し、それらが何を行い、最終的な回答にどう寄与したかなど、エージェントの推論の階層全体を把握できます。このガイドは、Agent Lens でマルチエージェントシステムをインストルメントする開発者を対象としています。

サブエージェントとは、ターン内で実行される、委譲されたエージェントの invocation です。スーパーバイザーエージェントが専門エージェントにタスクを割り振る場合など、あるエージェントが別のエージェントに処理を引き渡す場面でサブエージェントを使用します。

Agent Lens でインストルメントすると、サブエージェントは親ターンと同じトレース内に、ネストされた `invoke_agent` OpenTelemetry (OTel) スパンを出力します。**Conversations** タブでは、このネスト構造が、サブエージェントを呼び出したターンの下にサブエージェントの invocation としてレンダリングされ、その配下にサブエージェント自身の LLM Call とツール呼び出しがまとめて表示されます。

<h2 id="sub-agent-data-model">
  サブエージェントのデータモデル
</h2>

コードのインストルメンテーションを行う前に、Agent Lens がトレース内でサブエージェントをどのように表現するかを理解しておくと役立ちます。`tracing.start_subagent` スパンは OTel の `invoke_agent` スパンに対応し、親ターンと同じ操作名を出力します。Agent Lens は、トレース内の親子関係に基づいて両者を次のように区別します：

```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` スパンを作成します。このスパンは、OTel コンテキストで現在アクティブなスパン (通常は親ターン、または委譲のきっかけとなった 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 とツール実行を子スパンとして記録します。

これらの例では、エージェント間のトレースに焦点を当てるため、ルーティングロジックを意図的に省略しています。

```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 とツール呼び出しがまとめて表示されます。スーパーバイザーが直接行った LLM Call は、引き続きサブエージェントと同じ階層 (兄弟要素) に表示されます。

<h2 id="trace-multiple-sub-agents">
  複数のサブエージェントをトレースする
</h2>

次の例では、コンテンツパイプラインエージェントを実行します。このエージェントは 1 つのリクエストを処理する際、兄弟関係にある 3 つのサブエージェントに順番に処理を委譲します。事実を収集する `researcher`、投稿の下書きを作成する `writer`、最終的な出力を仕上げる `reviewer` の 3 つです。

Agent Lens は、サブエージェントごとに個別の `tracing.start_subagent` ブロックを開くことで、3 つのサブエージェントすべてを同じターン配下の兄弟として取得します。各サブエージェントは実行中のターンの OTel コンテキストを継承するため、サブエージェント同士が入れ子になることはありません。いずれもターンの配下にネストされた同階層の `invoke_agent` スパンとして表示されます。

```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** タブでは、ターンの中に 3 つのサブエージェントの invocation が兄弟として並び、それぞれの下に個別の LLM Call がネストされています。また、`researcher` にはツール呼び出しも含まれています。サブエージェント同士が親子関係になることはありません。

<h2 id="trace-nested-sub-agents">
  ネストされたサブエージェントをトレースする
</h2>

サブエージェントは、さらに別のサブエージェントに処理を委譲することもできます。`start_subagent` の各呼び出しは、OTel コンテキストで現在アクティブなスパンの配下にネストされます。

```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` のサブエージェントとして表示されます。
