> ## 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.

# OpenTelemetry のスパンを Agent Lens に送信する

> 任意の OpenTelemetry パイプラインから OTLP トレースデータを Agent Lens のエンドポイントに送信します。SDK インテグレーションは不要です。

CoreWeave Agent Lens は [OpenTelemetry (OTel)](https://opentelemetry.io/docs/concepts/) を基盤として構築されており、スパンを Agent Lens に取り込むための専用の OTLP エンドポイントを提供しています。そのため、OTel エクスポーターの現在のエンドポイント設定を Agent Lens のエンドポイント設定に置き換えるだけで、OTel でインストルメントされたアプリケーションのスパンの送信先をすぐに Agent Lens に切り替えられます。CoreWeave Forge SDK をインストールする必要はありません。

このページでは、エンドポイントへの認証方法とスパンの送信方法について説明します。

<Note>
  Agent Lens は Weights & Biases と同じバックエンドで動作するため、一部の設定名には `wandb` 接頭辞が付いたままになっています。該当するのは、`WANDB_API_KEY` 環境変数、`wandb-api-key` ヘッダー、`wandb.entity` および `wandb.project` リソース属性です。これらの名前は記載どおりに使用してください。
</Note>

<h2 id="authentication">
  認証
</h2>

スパンは次のエンドポイントに送信できます。

* **パス**: `/agents/otel/v1/traces`
* **メソッド**: `POST`
* **Content-Type**: `application/x-protobuf`
* **ベース URL**: Multi-tenant Cloud の場合は `https://trace.wandb.ai`

このエンドポイントが受け入れるのは OTLP protobuf ペイロードのみです。`opentelemetry-exporter-otlp-proto-http` (Python) や `@opentelemetry/exporter-trace-otlp-proto` (TypeScript) などの protobuf HTTP エクスポーターを使用してください。また、`gzip` および `deflate` のコンテンツエンコーディングも受け入れます。

エンドポイントで認証するには、`OTLPSpanExporter` の設定で、次のいずれかの値を使用して [APIキー](https://forge.coreweave.com/settings#apikeys) を指定します。

* `wandb-api-key`: 値に Forge の APIキーを指定します。
* `Authorization`: ユーザーを `api`、パスワードを Forge の APIキーとする HTTP Basic 認証を使用します。エクスポーターまたはコレクターが標準の認証ヘッダーしかサポートしていない場合は、この形式が便利です。

<h2 id="project-routing">
  project のルーティング
</h2>

Agent Lens は、OTel のリソース属性またはリクエストヘッダーを使用して、スパンを project にルーティングします。

* **リソース属性** (推奨) : `TracerProvider` のリソースで、`wandb.entity` に Forge のチーム名またはユーザー名を、`wandb.project` にプロジェクト名を設定します。
* **`project_id` ヘッダー**: 値を `[YOUR-TEAM]/[YOUR-PROJECT]` に設定します。

両方が指定されている場合は、リソース属性が優先されます。entity と project のないスパンは破棄されます。

<h2 id="shape-spans-for-the-conversations-tab">
  Conversations タブ向けにスパンを構成する
</h2>

Agent Lens は任意の OTel スパンを受け入れ、そのすべての属性を保存しますが、Conversations タブでレンダリングされるのは [OTel GenAI セマンティック規約](https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-agent-spans/)に準拠したスパンです。各スパンに `gen_ai.operation.name` を設定して、そのスパンが何を表すかを Agent Lens に指定します。

| `gen_ai.operation.name` | 表す内容 | 表示形式 |
| - | - | - |
| `invoke_agent` | ユーザーとエージェント間の 1 回分の完結したやり取り。 | ターン。 |
| `chat` | 言語モデル API への 1 回の呼び出し。 | ターン内の LLM Call。 |
| `execute_tool` | 1 回のツール実行。 | ツール呼び出し。 |

グループ化は、さらに次の 2 つの属性で制御します。

* `gen_ai.conversation.id`: ターンを会話にまとめます。会話の有効期間中は固定の ID を使用してください。
* `gen_ai.agent.name`: Conversations タブで、会話を名前付きのエージェントごとにまとめます。

`gen_ai.request.model`、`gen_ai.usage.input_tokens`、`gen_ai.usage.output_tokens` など、その他の GenAI セマンティック規約の属性を設定すると、モデル名やトークン数が表示に加わりますが、これらは必須ではありません。これらのスパンが対応するエージェントのデータモデルについては、[エージェントをトレースする](/ja/products/agent-lens/tracing/instrument#the-agent-data-model)を参照してください。

<h2 id="configure-with-environment-variables-only">
  環境変数のみで設定する
</h2>

アプリケーションまたはコレクターが OTel 標準のエクスポーター用環境変数を読み取る場合は、以下の変数を設定するだけで、コードを一切変更せずにスパンを Agent Lens に送信できます。

```bash lines theme={"system"}
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://trace.wandb.ai/agents/otel/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="wandb-api-key=$WANDB_API_KEY"
export OTEL_RESOURCE_ATTRIBUTES="wandb.entity=[YOUR-TEAM],wandb.project=[YOUR-PROJECT]"
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
```

* `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`: エクスポーターがスパンを送信する Agent Lens のエンドポイントです。
* `OTEL_EXPORTER_OTLP_TRACES_HEADERS`: Forge の APIキーを使用して各リクエストを認証します。APIキーは `wandb-api-key` ヘッダーで送信されます。
* `OTEL_RESOURCE_ATTRIBUTES`: スパンの送信先 project を指定します。`wandb.entity` には Forge のチーム名またはユーザー名を、`wandb.project` にはプロジェクト名を設定します。
* `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`: エクスポーターが HTTP 経由で OTLP protobuf を送信するように設定します。エンドポイントは protobuf ペイロードのみを受け入れるため、値には `http/protobuf` を指定する必要があります。

<h2 id="example-emit-agent-spans-without-the-agent-lens-sdk">
  例: Agent Lens SDK を使わずにエージェント スパンを送信する
</h2>

次の例では、OTel パッケージのみを使用して、最小構成のエージェントのターンをインストルメントします。ターンには `invoke_agent` スパン、LLM Call には `chat` スパン、ツール呼び出しには `execute_tool` スパンを送信し、それらを Agent Lens のエージェント エンドポイントにエクスポートします。

まず、必要な依存関係をインストールします。

<CodeGroup>
  ```bash Python theme={"system"}
  pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
  ```

  ```bash TypeScript theme={"system"}
  npm install @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base @opentelemetry/resources @opentelemetry/exporter-trace-otlp-proto
  ```
</CodeGroup>

次に、以下のコード内の `YOUR-TEAM`、`YOUR-PROJECT`、`YOUR_API_KEY` を実際の値に置き換えてから、コードを実行します。

<CodeGroup>
  ```python Python lines highlight="8,9,14" theme={"system"}
  import os
  from opentelemetry import trace
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
  from opentelemetry.sdk import trace as trace_sdk
  from opentelemetry.sdk.resources import Resource
  from opentelemetry.sdk.trace.export import BatchSpanProcessor

  ENTITY = "[YOUR-TEAM]"
  PROJECT = "[YOUR-PROJECT]"

  AGENTS_LENS_OTLP_ENDPOINT = "https://trace.wandb.ai/agents/otel/v1/traces"

  # https://forge.coreweave.com/settings#apikeys でAPIキーを作成します
  WANDB_API_KEY = [YOUR-API-KEY]

  exporter = OTLPSpanExporter(
      endpoint=WEAVE_AGENTS_OTLP_ENDPOINT,
      headers={"wandb-api-key": WANDB_API_KEY},
  )

  tracer_provider = trace_sdk.TracerProvider(resource=Resource({
      "wandb.entity": ENTITY,
      "wandb.project": PROJECT,
  }))
  tracer_provider.add_span_processor(BatchSpanProcessor(exporter))
  trace.set_tracer_provider(tracer_provider)

  tracer = trace.get_tracer("my-agent")

  CONVERSATION_ID = "conversation-001"

  # 1 ターンの例: ユーザーが質問し、エージェントがツールを呼び出したうえで回答します。
  with tracer.start_as_current_span("invoke_agent my-agent") as turn:
      turn.set_attribute("gen_ai.operation.name", "invoke_agent")
      turn.set_attribute("gen_ai.agent.name", "my-agent")
      turn.set_attribute("gen_ai.conversation.id", CONVERSATION_ID)

      with tracer.start_as_current_span("chat gpt-4o") as llm:
          llm.set_attribute("gen_ai.operation.name", "chat")
          llm.set_attribute("gen_ai.conversation.id", CONVERSATION_ID)
          llm.set_attribute("gen_ai.request.model", "gpt-4o")
          # 実際の LLM Call に置き換え、そのトークン使用量を記録します。
          llm.set_attribute("gen_ai.usage.input_tokens", 100)
          llm.set_attribute("gen_ai.usage.output_tokens", 20)

          with tracer.start_as_current_span("execute_tool get_weather") as tool:
              tool.set_attribute("gen_ai.operation.name", "execute_tool")
              tool.set_attribute("gen_ai.conversation.id", CONVERSATION_ID)
              tool.set_attribute("gen_ai.tool.name", "get_weather")
              # 実際のツール実行に置き換えてください。

  tracer_provider.shutdown()  # 終了前に、保留中のスパンをすべてフラッシュします。
  ```

  ```typescript TypeScript lines highlight="7,8,13" theme={"system"}
  import { trace } from "@opentelemetry/api";
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
  import { Resource } from "@opentelemetry/resources";

  const ENTITY = "[YOUR-TEAM]";
  const PROJECT = "[YOUR-PROJECT]";

  const WEAVE_AGENTS_OTLP_ENDPOINT = "https://trace.wandb.ai/agents/otel/v1/traces";

  // https://forge.coreweave.com/settings#apikeys でAPIキーを作成します
  const WANDB_API_KEY = [YOUR-API-KEY]!;

  const exporter = new OTLPTraceExporter({
    url: WEAVE_AGENTS_OTLP_ENDPOINT,
    headers: { "wandb-api-key": WANDB_API_KEY },
  });

  const provider = new NodeTracerProvider({
    resource: new Resource({
      "wandb.entity": ENTITY,
      "wandb.project": PROJECT,
    }),
    spanProcessors: [new BatchSpanProcessor(exporter)],
  });

  provider.register();

  const tracer = trace.getTracer("my-agent");

  const CONVERSATION_ID = "conversation-001";

  // 1 ターンの例: ユーザーが質問し、エージェントがツールを呼び出して回答します。
  tracer.startActiveSpan("invoke_agent my-agent", (turn) => {
    turn.setAttribute("gen_ai.operation.name", "invoke_agent");
    turn.setAttribute("gen_ai.agent.name", "my-agent");
    turn.setAttribute("gen_ai.conversation.id", CONVERSATION_ID);

    tracer.startActiveSpan("chat gpt-4o", (llm) => {
      llm.setAttribute("gen_ai.operation.name", "chat");
      llm.setAttribute("gen_ai.conversation.id", CONVERSATION_ID);
      llm.setAttribute("gen_ai.request.model", "gpt-4o");
      // 実際の LLM Call に置き換え、そのトークン使用量を記録します。
      llm.setAttribute("gen_ai.usage.input_tokens", 100);
      llm.setAttribute("gen_ai.usage.output_tokens", 20);

      tracer.startActiveSpan("execute_tool get_weather", (tool) => {
        tool.setAttribute("gen_ai.operation.name", "execute_tool");
        tool.setAttribute("gen_ai.conversation.id", CONVERSATION_ID);
        tool.setAttribute("gen_ai.tool.name", "get_weather");
        // 実際のツール実行に置き換えます。
        tool.end();
      });

      llm.end();
    });

    turn.end();
  });

  await provider.shutdown(); // 終了前に、未送信のスパンをすべてフラッシュします。
  ```
</CodeGroup>

同じ会話にターンを追加するには、同じ `gen_ai.conversation.id` を持つ `invoke_agent` スパンを追加で出力します。各ターンはそれぞれ独立したトレースのルートスパンとなるため、ターン間で親スパンを共有する必要はありません。

アプリケーションがスパンをエクスポートしたら、Agent Lens project の **Conversations** ビューを開きます。
