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

# Agents 뷰로 OpenTelemetry span 보내기

> Weave SDK 없이 모든 OpenTelemetry 파이프라인에서 Weave agents 엔드포인트로 OTLP 트레이스 데이터를 보내세요.

export const AgentLensBanner = ({href}) => <Tip>
    <strong>This workflow is also available in CoreWeave Agent Lens.</strong> Agent Lens is the Forge experience built for tracing, monitoring, and analyzing AI agents, with automated insights into agent failures and user intents. It uses the same trace data as Weights & Biases Weave, so the traces you already send appear there with nothing to migrate.{' '}
    <a href={href || '/products/agent-lens'}>{href ? 'See how to do this in Agent Lens' : 'Learn about Agent Lens'}</a>.
  </Tip>;

<AgentLensBanner href="/ko/products/agent-lens/get-started/opentelemetry" />

W\&B Weave 에이전트 관측성은 [OpenTelemetry (OTel)](https://opentelemetry.io/docs/concepts/)를 기반으로 하며, span을 **Agents** 뷰로 수집하는 전용 OTLP 엔드포인트를 제공합니다. 따라서 OTel 익스포터의 현재 엔드포인트 설정을 Weave의 엔드포인트 설정으로 바꾸기만 하면 OTel로 계측된 애플리케이션의 span을 Weave로 손쉽게 전송할 수 있습니다. Weave SDK는 설치하지 않아도 됩니다.

이 페이지에서는 엔드포인트에 인증하고 span을 전송하는 방법을 설명합니다.

<h2 id="authentication">
  인증
</h2>

다음 엔드포인트로 span을 전송할 수 있습니다.

* **Path**: `/agents/otel/v1/traces`
* **Method**: `POST`
* **Content-Type**: `application/x-protobuf`
* **Base 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` 설정에서 다음 값 중 하나를 사용해 [W\&B API 키](https://forge.coreweave.com/settings)를 지정하세요.

* `wandb-api-key`: W\&B API 키를 값으로 지정합니다.
* `Authorization`: 사용자 이름은 `api`, 비밀번호는 W\&B API 키로 지정하는 HTTP Basic 인증입니다. 익스포터나 컬렉터가 표준 인증 헤더만 지원하는 경우에 유용합니다.

<h2 id="project-routing">
  프로젝트 라우팅
</h2>

Weave는 OTel 리소스 속성 또는 요청 헤더를 기준으로 span을 프로젝트에 라우팅합니다.

* **리소스 속성** (권장): `TracerProvider` 리소스에서 `wandb.entity`를 CoreWeave Forge 팀 또는 사용자 이름으로, `wandb.project`를 프로젝트 이름으로 설정하세요.
* **`project_id` 헤더**: 값을 `[YOUR-TEAM]/[YOUR-PROJECT]`로 설정하세요.

둘 다 지정된 경우 리소스 속성이 우선 적용됩니다. entity와 프로젝트 정보 없이 수신된 span은 삭제됩니다.

<h2 id="shape-spans-for-the-agents-view">
  Agents 뷰에 맞게 span 구성하기
</h2>

Weave는 모든 OTel span을 받아 해당 속성을 모두 저장하지만, Agents 뷰는 [OTel GenAI 시맨틱 규칙](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md)을 따르는 span만 렌더링합니다. 각 span에 `gen_ai.operation.name`을 설정하여 해당 span이 무엇을 나타내는지 Weave에 알려 주세요.

| `gen_ai.operation.name` | 의미 | 렌더링 형태 |
| - | - | - |
| `invoke_agent` | 사용자와 에이전트 간의 한 차례 완결된 주고받기. | 턴. |
| `chat` | 언어 모델 API 호출 한 번. | 턴 내의 LLM Call. |
| `execute_tool` | 도구 실행 한 번. | 도구 Call. |

그룹화를 제어하는 속성이 두 가지 더 있습니다.

* `gen_ai.conversation.id`: 턴을 대화 단위로 묶습니다. 대화가 이어지는 동안 변하지 않는 고정 ID를 사용하세요.
* `gen_ai.agent.name`: Agents 탭에서 대화를 이름이 지정된 에이전트별로 묶습니다.

`gen_ai.request.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens` 등 그 밖의 GenAI 시맨틱 규칙 속성은 선택 사항이지만, 설정하면 모델 이름과 토큰 수가 함께 표시되어 더 풍부하게 렌더링됩니다. 이러한 span이 매핑되는 에이전트 데이터 모델에 대해서는 [에이전트 트레이스하기](/ko/products/wandb/weave/guides/tracking/trace-agents#the-agent-data-model)를 참조하세요.

<h2 id="configure-with-environment-variables-only">
  환경 변수만으로 설정하기
</h2>

애플리케이션이나 컬렉터가 표준 OTel 익스포터 환경 변수를 읽는 경우, 다음 변수를 설정하면 코드를 변경하지 않고도 span을 Weave로 라우팅할 수 있습니다.

```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]"
```

<h2 id="example-emit-agent-spans-without-the-weave-sdk">
  예시: Weave SDK 없이 에이전트 span 내보내기
</h2>

다음 예시는 OTel 패키지만 사용하여 최소한의 에이전트 턴을 계측합니다. 턴에 대해 `invoke_agent` span을, LLM Call에 대해 `chat` span을, 도구 Call에 대해 `execute_tool` span을 생성한 다음, 이를 Weave agents 엔드포인트로 내보냅니다.

먼저 필요한 의존성을 설치하세요.

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

그런 다음 아래 코드에서 `WANDB_API_KEY`, `ENTITY`, `PROJECT` 값을 설정하고 코드를 실행하세요.

<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]"

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

  # https://forge.coreweave.com/settings 에서 API 키를 생성하세요.
  WANDB_API_KEY = [YOUR-WANDB-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"

  # 턴 하나: 사용자가 질문하면 에이전트가 도구를 호출한 뒤 답변합니다.
  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()  # 종료하기 전에 대기 중인 span을 모두 플러시합니다.
  ```

  ```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 에서 API 키를 생성하세요
  const WANDB_API_KEY = [YOUR-WANDB-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";

  // 하나의 턴: 사용자가 질문하면 에이전트가 도구를 호출한 뒤 답변합니다.
  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(); // 종료하기 전에 대기 중인 모든 span을 플러시합니다.
  ```
</CodeGroup>

같은 대화에 턴을 더 추가하려면 동일한 `gen_ai.conversation.id`로 `invoke_agent` span을 추가로 내보내세요. 각 턴은 자체 트레이스의 루트 span이므로 턴끼리 부모 span을 공유하지 않아도 됩니다.

애플리케이션에서 span을 내보낸 다음 Weave 프로젝트의 **Agents** 탭을 여세요.
