> ## 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 SDK を使用してマルチターンのエージェント型アプリケーションをインストルメントし、そのアクティビティを Agent Lens で確認します。

CoreWeave Forge SDK を使用してマルチターンのエージェント型アプリケーションをインストルメントし、エージェントの動作を確認、デバッグ、評価する方法について説明します。このガイドは、エージェントを構築または統合する開発者のうち、会話、ターン、LLM Call、ツール実行を構造的に可視化したい方を対象としています。

Agent Lens SDK は、マルチターンのエージェントの会話におけるライフサイクル全体をモデル化します。対象となるのは、複数の会話を持つエージェント、ターンをまとめる会話、ユーザーとエージェント間の個々のやり取り (ターン)、ターン内の LLM Call、そして LLM によってトリガーされるツール実行です。トレースは、CoreWeave Agent Lens の project の **Conversations** タブに表示されます。各会話には、ネストされたツール呼び出し、トークン使用量、フィードバックを含むマルチターンのタイムラインが表示されます。

Agent Lens は、分散トレースのオープン標準である [OpenTelemetry (OTel)](https://opentelemetry.io/docs/concepts/) を基盤としています。ターン、LLM Call、ツール呼び出しはそれぞれ OTel の *スパン* (1 つの操作を表す構造化レコード) を出力します。各スパンには、`gen_ai.agent.name` や `gen_ai.conversation.id` などの [GenAI セマンティック規約](https://opentelemetry.io/docs/specs/semconv/gen-ai/) に基づく属性がタグ付けされます。

<h2 id="before-you-begin">
  始める前に
</h2>

まず、Agent Lens SDK をインストールし、project を初期化します。このステップで entity と project が Agent Lens に登録され、SDK がスパンを UI 上の正しい場所に送信できるようになります。SDK は `WANDB_API_KEY` 環境変数から APIキーを読み取ります。

<Tabs>
  <Tab title="Python">
    ```bash lines theme={"system"}
    pip install coreweave
    ```

    `[YOUR-TEAM]` を Forge の entity 名に、`[YOUR-PROJECT]` をプロジェクト名に置き換えます。entity は必須です。

    ```python lines theme={"system"}
    from coreweave.forge.agentlens import tracing

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

    `start_conversation()`、`start_turn()`、`start_llm()`、`start_tool()`、`start_subagent()` のいずれかを呼び出す前に、`tracing.init()` を呼び出してください。`init()` の実行前や `shutdown()` の実行後は、トレース関数はエラーを出さずに no-op となります。そのため、インストルメンテーションを本番コードに残したまま、設定で有効・無効を制御できます。プロセスの終了時に `tracing.shutdown()` を呼び出して、バッファに残っているスパンをフラッシュしてください。この関数は `atexit` にも登録されています。
  </Tab>

  <Tab title="TypeScript">
    ```bash lines theme={"system"}
    npm install @coreweave/forge-sdk
    ```

    `[YOUR-TEAM]` を Forge の entity 名に、`[YOUR-PROJECT]` をプロジェクト名に置き換えます。entity は必須です。

    ```typescript lines theme={"system"}
    import { tracing } from '@coreweave/forge-sdk/agentlens';

    await tracing.init('[YOUR-TEAM]/[YOUR-PROJECT]');
    ```

    `startConversation()`、`startTurn()`、`startLLM()`、`startTool()`、`startSubagent()` のいずれかを呼び出す前に、`tracing.init()` を一度だけ呼び出してください。また TypeScript では、各リクエストやエージェントの run を `tracing.runIsolated()` でラップする必要があります。これにより、その実行のトレース状態が `await` をまたいで保持され、並行するリクエスト同士で会話が共有されるのを防げます。`tracing.runIsolated()` の外でスパンを開始すると、エラーがスローされます。プロセスの終了時に `tracing.shutdown()` を呼び出して、バッファに残っているスパンをフラッシュしてください。
  </Tab>
</Tabs>

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

Agent Lens は、エージェントの動作を一対多の関係による階層としてモデル化します。1 つのエージェントは複数の会話を持つことができ、1 つの会話は複数のターンを、1 つのターンは複数の LLM Call を持つことができます。さらに、1 つの LLM Call から複数のツール呼び出しをトリガーできます。

| 概念 | Agent Lens SDK クラス | OTel スパンタイプ | 説明 | リファレンスページ |
| - | - | - | - | - |
| エージェント | *(クラスなし)* | *(スパンなし。`agent_name` 属性でグループ化)* | 1 つ以上の会話を含むエージェント型アプリケーション。 | |
| 会話 | `Conversation` | *(スパンなし。ターンは `conversation_id` 属性でグループ化)* | 1 つ以上のターンを含む会話または run。 | [Python](/ja/products/agent-lens/reference/python-sdk/conversation) <br /> [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/classes/conversation) |
| ターン | `Turn` | `invoke_agent` | 1 つのユーザーメッセージと、それに対するエージェントの応答全体。 | [Python](/ja/products/agent-lens/reference/python-sdk/turn) <br /> [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/classes/turn) |
| LLM Call | `LLM` | `chat` | 言語モデル API への 1 回の呼び出し。 | [Python](/ja/products/agent-lens/reference/python-sdk/llm) <br /> [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/classes/llm) |
| ツール呼び出し | `Tool` | `execute_tool` | LLM の応答によってトリガーされる 1 回のツール呼び出し。 | [Python](/ja/products/agent-lens/reference/python-sdk/tool) <br /> [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/classes/tool) |
| サブエージェントの呼び出し | `SubAgent` | `invoke_agent` | ネストされたエージェントの invocation。通常、あるエージェントが別のエージェントに処理を委譲する場合に発生します。 | [Python](/ja/products/agent-lens/reference/python-sdk/subagent) <br /> [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/classes/subagent) |

次の図は、1 つのエージェントが複数の会話を持ち、1 つの会話が複数のターンを持つ、といった階層関係を示しています。

```mermaid theme={"system"}
flowchart TB
    Agent["エージェント<br/>agent_name"]

    Agent --> S1 & S2

    S1["会話 1<br/>conversation_id<br/>（OTel スパンなし）"]
    S2["会話 2<br/>conversation_id<br/>（OTel スパンなし）"]

    S1 --> T1 & T2
    S2 --> T3

    T1["ターン 1<br/>invoke_agent<br/>（ルートスパン、個別のトレース）"]
    T2["ターン 2<br/>invoke_agent<br/>（ルートスパン、個別のトレース）"]
    T3["ターン 1<br/>invoke_agent<br/>（ルートスパン、個別のトレース）"]

    T1 --> L1 & L2
    L1["LLM Call<br/>chat"]
    L2["LLM Call<br/>chat"]

    L1 --> Tool1["ツール呼び出し<br/>execute_tool"]

    classDef agent fill:#DE72FF33,stroke:#454B52,stroke-width:2px
    classDef conversation fill:#FFD95C33,stroke:#454B52,stroke-width:2px
    classDef turn fill:#00CDDB33,stroke:#454B52,stroke-width:2px
    classDef llm fill:#FFCBAD33,stroke:#454B52,stroke-width:2px
    classDef tool fill:#f4f4f5,stroke:#454B52,stroke-width:2px

    class Agent agent
    class S1,S2 conversation
    class T1,T2,T3 turn
    class L1,L2 llm
    class Tool1 tool
```

会話は、親スパンではなく共通の `conversation_id` 属性によってターンをグループ化します。そのため、各ターンはそれぞれ独自の OTel トレースを開始します。この設計により、分散トレースと並列実行がサポートされます。クライアントはサーバー側で集約することなく、スパンを OTel コレクターに直接送信します。

<Tip>
  Claude Agent SDK や Codex などのエージェント SDK またはハーネスと Agent Lens を統合するには、[エージェントインテグレーションを選択する](/ja/products/agent-lens/get-started/integrations)を参照してください。これらのインテグレーションは SDK またはハーネスのセッションから `conversation_id` を設定するため、ターンをグループ化するために `start_conversation()` を使用する必要はありません。一方、LLM プロバイダ SDK のインテグレーション (OpenAI、Anthropic、Google Gen AI) は会話を作成しません。Agent Lens には会話内で実行された Call のみが表示されるため、このページの API を使用して、これらの Call を囲む会話とターンを開始してください。
</Tip>

<h2 id="agent-tracing-apis">
  エージェントトレース API
</h2>

以下のセクションでは、各トップレベルのトレース関数と、その関数が受け入れる引数について説明します。これらの関数を使用して、前のセクションで説明したデータモデルの会話、ターン、LLM Call、ツール呼び出しの各レイヤーをインストルメントします。

Agent Lens は、以下のトップレベル関数を提供します。各関数が返すオブジェクトは、コンテキストマネージャーとして使用する (Python では `with`、TypeScript では `try/finally` を使用) か、`.end()` を呼び出して手動で終了することができます。

<h3 id="start-a-conversation">
  会話を開始する
</h3>

`start_conversation()` (Python) または `startConversation()` (TypeScript) は、すべての子スパンに `conversation_id` 属性を付与し、ターンが **Conversations** タブでグループ化されるようにします。`conversation_id` / `conversationId` を指定する場合は、会話の有効期間を通じて同じ値を使用する必要があります。既存の会話に新しいターンを追加するには、同じ ID を再利用してください。省略した場合は、SDK が UUID を自動的に生成します。

実行中の会話はコンテキスト (Python の `ContextVar` または Node.js の `AsyncLocalStorage`) に保存されます。そのため、同じ非同期コンテキスト内で実行されるコードであれば、会話オブジェクトを明示的に渡さなくても `tracing.get_current_conversation()` / `tracing.getCurrentConversation()` で取得できます。

<Tabs>
  <Tab title="Python">
    ```python lines theme={"system"}
    conversation = tracing.start_conversation(
        agent_name="my-agent",    # オプション: UI でエージェントを識別します。省略すると、会話は名前付きエージェントの下にグループ化されません。
        conversation_id="",       # オプション: ターンをグループ化するための固定の ID。空の場合は自動生成されます。
        model="",                 # オプション: この会話のターンで使用するデフォルトのモデル。
        conversation_name="",     # オプション: UI に表示される、わかりやすいラベル。
        include_content=True,     # オプション: False に設定すると、スパンからメッセージ本文を除外します。
        continue_parent_trace=False,  # オプション: 新しいトレースを開始せず、既存の OTel トレースに紐付けます。
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines theme={"system"}
    const conversation = tracing.startConversation({
      agentName: 'my-agent',  // オプション: UI でエージェントを識別します。省略すると、会話は名前付きエージェントの下にグループ化されません。
      conversationId: '',     // オプション: ターンをグループ化するための固定の ID。空の場合は自動生成されます。
      model: '',              // オプション: この会話のターンで使用するデフォルトのモデル。
    });
    ```
  </Tab>
</Tabs>

<h3 id="start-a-turn">
  ターンを開始する
</h3>

`start_turn()` (Python) および `startTurn()` (TypeScript) は、新しい OTel トレースのルートとなる `invoke_agent` スパンを作成します。Agent Lens は、タイムラインビューでユーザーとエージェント間の 1 回のやり取り全体をこのスパンで表します。

<Tabs>
  <Tab title="Python">
    ```python lines theme={"system"}
    turn = tracing.start_turn(
        user_message="What is the weather in Tokyo?",  # ユーザーの入力テキスト。
        agent_name="my-agent",   # オプション: 会話レベルのエージェント名を上書きします。
        model="gpt-4o",          # オプション: このターンで使用するモデル。
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines theme={"system"}
    const turn = tracing.startTurn({
      userMessage: 'What is the weather in Tokyo?',  // ユーザーの入力テキスト。
      agentName: 'my-agent',  // オプション: 会話レベルのエージェント名を上書きします。
      model: 'gpt-4o',        // オプション: このターンで使用するモデル。
    });
    ```
  </Tab>
</Tabs>

呼び出し方法は 2 通りあります。

* **トップレベル関数として呼び出す** (`tracing.start_turn(...)` / `tracing.startTurn(...)`) : 以下のサンプルではこの形式を使用しています。コンテキストから実行中の会話を解決し、その会話 ID を引き継ぎます。実行中の会話がない場合、ターンは `conversation_id` なしで作成され、他のターンとはグループ化されません。
* **インスタンスメソッドとして呼び出す** (`conversation.start_turn(...)` / `conversation.startTurn(...)
  `) : 参照を保持している会話に対して呼び出します。コンテキストマネージャーのブロック内など、会話オブジェクトが明示的にスコープ内にある場合に便利です。このガイドの後半で紹介する[「コンテキストマネージャーまたは
  try-finally パターン」](#context-manager-or-try-finally-pattern)のサンプルでは、この形式を使用しています。両 SDK の `Conversation`、`Turn`、`LLM`、`Tool`、`SubAgent` のリファレンスページへの直接リンクについては、前述の[データモデルの
  表](#the-agent-data-model)を参照してください。

<h3 id="start-an-llm-call">
  LLM Call を開始する
</h3>

`start_llm()` / `startLLM()` は、現在のターンの下にネストされた `chat` スパンを作成します。Agent Lens はこのスパンを使用して、トークン使用量、モデル名、入力メッセージと出力メッセージ、推論を UI に表示します。

<Tabs>
  <Tab title="Python">
    ```python lines theme={"system"}
    llm = tracing.start_llm(
        model="gpt-4o",             # モデル識別子。
        provider_name="openai",     # オプション: プロバイダー名（例: "openai"、"anthropic"）。下記の注記を参照してください。
        system_instructions=["Be concise."],  # オプション: システムプロンプトの strings。
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines theme={"system"}
    const llm = tracing.startLLM({
      model: 'gpt-4o',          // モデル識別子。
      providerName: 'openai',   // オプション: プロバイダー名（例: "openai"、"anthropic"）。下記の注記を参照してください。
    });
    ```
  </Tab>
</Tabs>

LLM Call が完了したら、`llm` オブジェクトが閉じる前に応答データを割り当てます。

<Tabs>
  <Tab title="Python">
    ```python lines theme={"system"}
    with tracing.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,
        )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines theme={"system"}
    const llm = tracing.startLLM({ model: 'gpt-4o', providerName: 'openai' });
    try {
      const response = await openaiClient.chat.completions.create({ ... });
      llm.record({
        inputMessages: [{ role: 'user', content: '...' }],
        outputMessages: [{ role: 'assistant', content: response.choices[0].message.content ?? '' }],
        usage: {
          inputTokens: response.usage?.prompt_tokens,
          outputTokens: response.usage?.completion_tokens,
        },
      });
    } finally {
      llm.end();
    }
    ```

    `llm.record()` は、`inputMessages`、`outputMessages`、`usage`、`reasoning` を 1 回の呼び出しでまとめて割り当てるためのショートカットです。必要に応じて、各プロパティを個別に設定することもできます。Python SDK にも同じメソッドが `llm.record(...)` として用意されており、snake\_case のキーワード引数で指定します。
  </Tab>
</Tabs>

`provider_name` / `providerName` は明示的に指定してください。Agent Lens はモデル文字列からプロバイダーを推測しません。

<h3 id="start-a-tool-call">
  ツール呼び出しを開始する
</h3>

`start_tool()` / `startTool()` は `execute_tool` スパンを作成します。このスパンは、コンテキスト内でアクティブな OTel スパン (通常は、そのツール呼び出しを生成した LLM Call の `chat` スパン) の子になります。

<Tabs>
  <Tab title="Python">
    ```python lines theme={"system"}
    tool = tracing.start_tool(
        name="get_weather",                  # LLM に宣言したツール名。
        arguments='{"city": "Tokyo"}',       # ツール引数の JSON 文字列。
        tool_call_id="call_abc123",          # オプション: LLM の応答に含まれるツール呼び出し ID。
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines theme={"system"}
    const tool = tracing.startTool({
      name: 'get_weather',            // LLM に宣言したツール名。
      args: '{"city": "Tokyo"}',      // オプション: ツール引数の JSON 文字列。
      toolCallId: 'call_abc123',      // オプション: LLM の応答に含まれるツール呼び出し ID。
    });
    ```
  </Tab>
</Tabs>

スパンを閉じる前にツール結果を設定します。

<Tabs>
  <Tab title="Python">
    ```python lines theme={"system"}
    with tracing.start_tool(name="get_weather", arguments='{"city": "Tokyo"}') as tool:
        result = get_weather_api("Tokyo")
        tool.result = result  # dict、list、または string を受け入れます。自動的に JSON エンコードされます。
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines theme={"system"}
    const tool = tracing.startTool({ name: 'get_weather', args: '{"city": "Tokyo"}' });
    try {
      tool.result = await getWeatherApi('Tokyo');
    } finally {
      tool.end();
    }
    ```
  </Tab>
</Tabs>

<h2 id="usage-patterns-for-agent-tracing">
  エージェントトレースの使用パターン
</h2>

以下のセクションでは、エージェントのコード構成に応じてこれらの関数を組み合わせる方法について説明します。

以下のサンプルでは、Agent Lens SDK の 2 つのタイプを使用します。

* `Message` ([Python](/ja/products/agent-lens/reference/python-sdk/message-types#message) · [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/interfaces/message)) は、会話内の 1 つのエントリ (ユーザー入力、アシスタントの応答、システムプロンプト、ツール結果のいずれか) を表します。メッセージのリストを `llm.input_messages` / `llm.inputMessages` に割り当てるとモデルが受け取った内容が記録され、`llm.output_messages` / `llm.outputMessages` に割り当てるとモデルが生成した内容が記録されます。
* `Usage` ([Python](/ja/products/agent-lens/reference/python-sdk/message-types#usage) · [TypeScript](/ja/products/agent-lens/reference/typescript-sdk/interfaces/usage)) は、LLM の応答からトークン数を取得するもので、`llm.usage` に割り当てます。

Agent Lens はこの 2 つを使用して、各 LLM Call の入力、出力、トークン使用量を UI に表示します。

<h3 id="context-manager-or-try-finally-pattern">
  コンテキストマネージャーまたは try-finally パターン
</h3>

ほとんどのエージェントでは、Python ではコンテキストマネージャーパターンを、TypeScript では try-finally パターンを使用してください。例外が発生した場合でも、スパンはブロックの終了時に閉じられ、送信されます。

Agent Lens は実行中の会話、ターン、LLM Call をコンテキストに保持します。そのため、ブロック内で呼び出される関数は、親への参照を明示的に保持していなくても `start_llm()` / `startLLM()` や `start_tool()` / `startTool()` を呼び出せます。コードが同じ非同期コンテキスト内で実行される限り、モジュールの境界をまたいでも機能します。コールスタックの任意の場所から実行中のオブジェクトを取得するには、`tracing.get_current_conversation()` / `tracing.getCurrentConversation()`、`tracing.get_current_turn()` / `tracing.getCurrentTurn()`、`tracing.get_current_llm()` / `tracing.getCurrentLLM()` を使用します。

<Tabs>
  <Tab title="Python">
    ```python lines highlight="13,14,17,25,29" theme={"system"}
    from coreweave.forge.agentlens import tracing
    from coreweave.forge.agentlens.tracing import Message, Usage

    # プレースホルダー関数: 独自の実装に置き換えてください。
    def call_openai(*args, **kwargs):
        pass  # 使用する LLM クライアントの呼び出しに置き換えてください。

    def get_weather_api(city: str) -> str:
        return "24°C, sunny"  # 使用する天気 API の呼び出しに置き換えてください。

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

    with tracing.start_conversation(agent_name="weather-bot") as conversation:
        with conversation.start_turn(user_message="What is the weather in Tokyo?") as turn:

            # 1 回目の LLM Call: ツール呼び出しを返します。
            with tracing.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)

                # ツール呼び出し: 呼び出し元の LLM Call の子になります。
                with tracing.start_tool(name="get_weather", arguments='{"city":"Tokyo"}') as tool:
                    tool.result = get_weather_api("Tokyo")  # "24°C, sunny" を返します。

            # 2 回目の LLM Call: 最終的な回答を生成します。
            with tracing.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)

    tracing.shutdown()
    ```
  </Tab>

  <Tab title="TypeScript">
    エージェントの run を `tracing.runIsolated()` でラップします。これにより、会話、ターン、LLM のコンテキストが `await` をまたいでも維持され、同時実行中の他の run からも分離されます。

    ```typescript lines highlight="11,12,14,17,25,36" theme={"system"}
    import { tracing } from '@coreweave/forge-sdk/agentlens';
    import type { Message, Usage } from '@coreweave/forge-sdk/agentlens/tracing';

    // プレースホルダー関数: 独自の実装に置き換えてください。
    async function getWeatherApi(city: string): Promise<string> {
      return '24°C, sunny';  // 使用する天気 API の呼び出しに置き換えてください。
    }

    await tracing.init('[YOUR-TEAM]/[YOUR-PROJECT]');

    await tracing.runIsolated(async () => {
      const conversation = tracing.startConversation({ agentName: 'weather-bot' });
      try {
        const turn = conversation.startTurn({ userMessage: 'What is the weather in Tokyo?' });
        try {
          // 1 回目の LLM Call: ツール呼び出しを返します。
          const llm = tracing.startLLM({ model: 'gpt-4o', providerName: 'openai' });
          try {
            llm.inputMessages = [{ 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 = { inputTokens: 100, outputTokens: 20 };

            // ツール呼び出し: 呼び出し元の LLM Call の子になります。
            const tool = tracing.startTool({ name: 'get_weather', args: '{"city":"Tokyo"}' });
            try {
              tool.result = await getWeatherApi('Tokyo');  // "24°C, sunny" を返します。
            } finally {
              tool.end();
            }
          } finally {
            llm.end();
          }

          // 2 回目の LLM Call: 最終的な回答を生成します。
          const llm2 = tracing.startLLM({ model: 'gpt-4o', providerName: 'openai' });
          try {
            llm2.inputMessages = [{ role: 'user', content: 'What is the weather?' }];
            llm2.output('It is 24°C and sunny in Tokyo today.');
            llm2.usage = { inputTokens: 150, outputTokens: 30 };
          } finally {
            llm2.end();
          }
        } finally {
          turn.end();
        }
      } finally {
        conversation.end();
      }
    });

    await tracing.shutdown();
    ```
  </Tab>
</Tabs>

<h3 id="manual-start-and-end-pattern">
  手動で開始と終了を行うパターン
</h3>

`with` ブロックや `try/finally` を使用できない場合は、`.end()` を明示的に呼び出します。たとえば、スパンの開始と終了を別々の関数の Call で行う場合や、コルーチンの外部で非同期のライフサイクルを管理する場合が該当します。スパンを閉じてコレクターにフラッシュするために、作成したすべてのオブジェクトで必ず `.end()` を呼び出してください。TypeScript では、ターンまたは会話を終了すると、その配下でまだ開いている子孫もすべて閉じられます。

<Tabs>
  <Tab title="Python">
    ```python lines highlight="1,2,4,9,15" theme={"system"}
    conversation = tracing.start_conversation(agent_name="weather-bot")
    turn = conversation.start_turn(user_message="What is the weather?")

    llm = tracing.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 = tracing.start_tool(name="get_weather", arguments='{"city": "Tokyo"}')
    tool.result = "24°C, sunny"
    tool.end()   # end() はべき等なので、複数回呼び出しても問題ありません。

    llm.end()

    llm2 = tracing.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()
    conversation.end()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript lines highlight="1,2,3,5,10,16" theme={"system"}
    await tracing.runIsolated(async () => {
      const conversation = tracing.startConversation({ agentName: 'weather-bot' });
      const turn = conversation.startTurn({ userMessage: 'What is the weather?' });

      const llm = tracing.startLLM({ model: 'gpt-4o', providerName: 'openai' });
      llm.inputMessages = [{ role: 'user', content: 'What is the weather?' }];
      llm.output('Let me check.');
      llm.usage = { inputTokens: 100, outputTokens: 20 };

      const tool = tracing.startTool({ name: 'get_weather', args: '{"city": "Tokyo"}' });
      tool.result = '24°C, sunny';
      tool.end();  // end() はべき等なので、複数回呼び出しても問題ありません。

      llm.end();

      const llm2 = tracing.startLLM({ model: 'gpt-4o', providerName: 'openai' });
      llm2.output('It is 24°C and sunny in Tokyo.');
      llm2.usage = { inputTokens: 150, outputTokens: 30 };
      llm2.end();

      turn.end();
      conversation.end();
    });
    ```
  </Tab>
</Tabs>

<h2 id="semantic-conventions">
  セマンティック規約
</h2>

Agent Lens SDK は、[GenAI セマンティック規約](https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/)および [GenAI エージェント スパン規約](https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-agent-spans/)に準拠した OTel スパンを出力します。Agent Lens はあらゆる OTel スパンを受け入れ、すべての属性を保存してクエリできるようにします。任意の Agent Lens トレース オブジェクトで `set_attributes()` / `setAttributes()` を使用すると、スパンに任意の属性を追加できます。詳しくは、[エージェント スパンに属性を設定する](/ja/products/agent-lens/tracing/attributes)を参照してください。

SDK は専用のプライベートな OpenTelemetry トレーサープロバイダーを持っています。このプロバイダーは Agent Lens を通じて作成されたスパンのみをエクスポートします。アプリケーションのグローバル プロバイダーを置き換えることはなく、無関係なインストルメンテーションのスパンをエクスポートすることもありません。

<h2 id="how-data-appears-in-the-agent-lens-ui">
  Agent Lens UI でのデータの表示
</h2>

前述のパターンでエージェントをインストルメントして実行すると、トレースが Agent Lens project の **Conversations** タブ (`https://`) に表示されます。

* **Conversations タブ**には、すべての会話が、ターンのアクティビティを示すミニマップとともに表示されます。
* **会話の詳細ビュー**は、会話をクリックすると開きます。このビューには、その会話のすべてのターン、LLM Call、ツール実行、トークン数、および関連付けられたフィードバックが表示されます。

Agent Lens で取得したデータの表示方法について詳しくは、[エージェントのアクティビティを表示する](/ja/products/agent-lens/conversations/view-activity)を参照してください。
