> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Trazas de OpenTelemetry

ElevenLabs Agents puede exportar conversaciones como **trazas de OpenTelemetry** codificadas como **JSON de OTLP** (`resourceSpans`). Reenvíalas a Datadog, Grafana Tempo, Honeycomb o cualquier backend que procese OTLP.

> **Info**
>
> ElevenLabs no envía trazas directamente a tu recopilador de OTLP. Recibes JSON con formato OTLP desde
> un webhook, una API o un WebSocket de monitorización, y lo reenvías a tu backend.

## Resumen

Exporta trazas desde tres vías. Las tres comparten el mismo **ID de traza por conversación** y la nomenclatura de atributos `elevenlabs.*`. La forma y la temporización de los spans difieren entre post-llamada/GET (basado en transcripciones) y monitorización (basado en eventos).

### Vías de exportación

| Vía                         | Cuándo recibes los datos                                 | Ideal para                                                    |
| --------------------------- | -------------------------------------------------------- | ------------------------------------------------------------- |
| Webhook post-llamada        | Tras finalizar la conversación y completarse el análisis | Procesos por lotes, facturación y QA, almacenamiento duradero |
| API GET de conversación     | Bajo demanda, cuando la conversación ya existe           | Relleno de datos, depuración, reprocesamiento                 |
| WebSocket de monitorización | Durante una conversación en directo                      | Paneles en directo, alertas, supervisión humana               |

### Elegir una vía

* **Todas las llamadas completadas en tu almacén de datos**: webhook post-llamada
* **Exportación puntual o reparación**: GET de conversación con `format=opentelemetry`
* **Interfaz de supervisión o alertas en directo**: WebSocket de monitorización
* **Cronología completa y detallada a posteriori**: webhook post-llamada o GET de conversación
* **Eventos de herramientas, MCP o medidas de protección a medida que ocurren**: WebSocket de monitorización

Usa `traceId` o `elevenlabs.conversation_id` para unir datos entre vías. Combina la monitorización para operaciones en directo, los webhooks para análisis duradero y GET para rellenar datos.

Necesitas un recopilador o proveedor de observabilidad compatible con OTLP para cada vía. Los webhooks post-llamada requieren una ruta de webhook del espacio de trabajo. La API GET y el WebSocket de monitorización tienen cada uno sus propios ámbitos de clave de API y configuración; consulta las secciones siguientes.

## Webhook post-llamada

Cuando termina una conversación, ElevenLabs envía una solicitud `POST` si hay configurado un webhook post-llamada, `events` incluye `transcript` y `transcript_format` es `opentelemetry`.

El `type` del webhook es `post_call_transcription_otel` (no `post_call_transcription`, que devuelve transcripciones JSON).

### Carga útil del webhook

```json
{
  "type": "post_call_transcription_otel",
  "event_timestamp": 1700000000,
  "data": {
    "conversation_id": "conv_9001k1zph3fkeh5s8xg9z90swaqa",
    "agent_id": "agent_7101k5zvyjhmfg983brhmhkd98n6",
    "otlp_traces": {
      "resourceSpans": []
    }
  }
}
```

### Activar transcripciones de OpenTelemetry

#### Configurar desde el panel

### Crear un webhook de espacio de trabajo

En el panel de ElevenAgents, crea un webhook de espacio de trabajo con tu URL HTTPS y autenticación.

### Vincular el webhook post-llamada

Abre la [configuración de Agents](https://elevenlabs.io/app/agents/settings), asigna el webhook como webhook post-llamada, activa el evento **Transcripción** y habilita las **Cargas útiles de transcripción de OpenTelemetry**.

![Configuración del webhook post-llamada](/docs/_fern-img/eb5d768612d6461a21bc3127611f60724be3e1a55005af43faf48f2d7bf23807.webp)

#### Configurar mediante la CLI

> **Note**
>
> Los webhooks post-llamada de todo el espacio de trabajo se configuran en el panel o en la pestaña de API. Usa la CLI para
> anular la configuración del webhook en un agente específico.

### Obtener la configuración del agente

```bash
elevenlabs agents pull --agent "<agent-name>"
```

### Editar `agent_configs/<agent-name>.json`

Configura `platform_settings.workspace_overrides.webhooks`:

```json
{
  "platform_settings": {
    "workspace_overrides": {
      "webhooks": {
        "post_call_webhook_id": "wh_01jqz7x8y9z0a1b2c3d4e5f6",
        "events": ["transcript"],
        "transcript_format": "opentelemetry"
      }
    }
  }
}
```

### Enviar los cambios

```bash
elevenlabs agents push --agent "<agent-name>"
```

#### Configurar mediante la API

**`Python`**

```python title="Python"
import os

from dotenv import load_dotenv
from elevenlabs import ElevenLabs

load_dotenv()
elevenlabs = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))

elevenlabs.conversational_ai.settings.update(
    webhooks={
        "post_call_webhook_id": "wh_01jqz7x8y9z0a1b2c3d4e5f6",
        "events": ["transcript"],
        "transcript_format": "opentelemetry",
    },
)
```

**`TypeScript`**

```typescript title="TypeScript"
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({
  apiKey: process.env.ELEVENLABS_API_KEY,
});

await elevenlabs.conversationalAi.settings.update({
  webhooks: {
    postCallWebhookId: "wh_01jqz7x8y9z0a1b2c3d4e5f6",
    events: ["transcript"],
    transcriptFormat: "opentelemetry",
  },
});
```

Para un único agente, pasa el mismo objeto `webhooks` en `platform_settings.workspace_overrides` en [Actualizar agente](/docs/es/api-reference/agents/update).

> **Warning**
>
> Los webhooks de transcripción de OpenTelemetry no incluyen audio. Usa `post_call_audio` si necesitas
> grabaciones.
>
> Devuelve **2xx** para indicar éxito. Los códigos **4xx** y **5xx** cuentan como fallos.
>
> Los reintentos se aplican a los webhooks de transcripción (incluido OpenTelemetry) y audio solo cuando **Activar
> reintentos** está habilitado para el webhook del espacio de trabajo. Los errores transitorios (\*\* 5xx \*\*, \*\*429 \*\*, \*\*408 \*\*) se reintentan hasta
> 5 veces; los **4xx** no. Los fallos repetidos pueden desactivar automáticamente el webhook. Consulta
> [Webhooks post-llamada](/docs/es/eleven-agents/workflows/post-call-webhooks) para conocer los detalles y las excepciones
> HIPAA.

### Entrega

| Tema          | Detalle                                                                                   |
| ------------- | ----------------------------------------------------------------------------------------- |
| Método        | `POST` con cuerpo JSON                                                                    |
| Autenticación | `ElevenLabs-Signature: t={unix},v0={hmac}` sobre `{timestamp}.{body}`                     |
| Reintentos    | Requiere **Activar reintentos** en el webhook; consulta la advertencia anterior           |
| Tamaño        | Los parámetros y resultados largos de herramientas se truncan a 4 KB por atributo de span |

### Forma de la traza

Cada entrega es una traza completa: un span raíz y sus elementos secundarios.

```text
elevenlabs.conversation
├── elevenlabs.recv.user_transcript
├── elevenlabs.recv.agent_response
│   └── elevenlabs.tool.{name}
└── ...
```

Los spans de respuesta del agente incluyen `elevenlabs.reasoning_content` cuando la entrega contiene un [resumen de razonamiento](/docs/es/eleven-agents/customization/llm#reasoning-summary).

La temporización procede de `time_in_call_secs` de la transcripción y de los metadatos de la llamada. El span raíz establece `elevenlabs.source` = `post_call_webhook` y el estado `ERROR` cuando la llamada no terminó con una desconexión normal del cliente.

## GET de conversación

Solicita el formato OpenTelemetry en [Obtener conversación](/docs/es/api-reference/conversations/get) para recibir el mismo objeto `otlp_traces` que en el webhook post-llamada de OpenTelemetry, además del modelo completo de conversación.

```http
GET /v1/convai/conversations/{conversation_id}?format=opentelemetry
```

Requiere una clave de API con `CONVAI_READ`. Con `format=json` (predeterminado), se omite `otlp_traces`.

```json
{
  "conversation_id": "conv_9001k1zph3fkeh5s8xg9z90swaqa",
  "agent_id": "agent_7101k5zvyjhmfg983brhmhkd98n6",
  "status": "done",
  "transcript": [],
  "otlp_traces": {
    "resourceSpans": []
  }
}
```

| Tema            | Detalle                                                                      |
| --------------- | ---------------------------------------------------------------------------- |
| Temporización   | Mismo generador basado en transcripciones que el webhook post-llamada        |
| Transcripción   | `transcript` se sigue devolviendo; `otlp_traces` es adicional                |
| URL de archivos | Las URL firmadas de los atributos de span caducan después de unos 15 minutos |

**`Python`**

```python title="Python"
import os

from dotenv import load_dotenv
from elevenlabs import ElevenLabs

load_dotenv()
elevenlabs = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))

conversation = elevenlabs.conversational_ai.conversations.get(
    conversation_id="conv_9001k1zph3fkeh5s8xg9z90swaqa",
    format="opentelemetry",
)

otlp_traces = conversation.otlp_traces
```

**`TypeScript`**

```typescript title="TypeScript"
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({
  apiKey: process.env.ELEVENLABS_API_KEY,
});

const conversation = await elevenlabs.conversationalAi.conversations.get({
  conversationId: "conv_9001k1zph3fkeh5s8xg9z90swaqa",
  format: "opentelemetry",
});

const otlpTraces = conversation.otlpTraces;
```

**`cURL`**

```bash title="cURL"
curl -s "https://api.elevenlabs.io/v1/convai/conversations/conv_9001k1zph3fkeh5s8xg9z90swaqa?format=opentelemetry" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  | jq '.otlp_traces.resourceSpans[0].scopeSpans[0].spans[].name'
```

Los nombres de span esperados incluyen `elevenlabs.conversation`, `elevenlabs.recv.user_transcript` y `elevenlabs.recv.agent_response`.

## WebSocket de monitorización

> **Note**
>
> La monitorización en tiempo real requiere un espacio de trabajo Enterprise o la marca de funcionalidad `realtime-monitoring`.
> Consulta [Monitorización en tiempo real](/docs/es/eleven-agents/guides/realtime-monitoring) para ver la configuración,
> los comandos de control y los requisitos de acceso.

Transmite datos de trazas de OpenTelemetry como JSON de OTLP mientras hay una conversación en curso. Cada mensaje es un pequeño lote de `resourceSpans`, no una traza única al finalizar la llamada.

```
wss://api.elevenlabs.io/v1/convai/conversations/{conversation_id}/monitor?events_format=opentelemetry
```

La autenticación requiere `CONVAI_WRITE`, `xi-api-key` (o `Authorization`) y acceso de **EDITOR** al espacio de trabajo del agente. Conéctate después de que empiece la conversación.

### Activar la monitorización en el agente

Configura `monitoring_enabled: true` y `monitoring_events` antes de la llamada. Consulta [Monitorización en tiempo real](/docs/es/eleven-agents/guides/realtime-monitoring#configuration).

### Conectarse con formato OpenTelemetry

Añade `events_format=opentelemetry` a la URL del WebSocket de monitorización.

> **Warning**
>
> Los eventos de VAD, probabilidad de turno y ping no están disponibles cuando se configuran `monitoring_events`
> personalizados. El flujo incluye solo texto y metadatos, no audio sin procesar.

### Protocolo de sesión

1. Conéctate con encabezados de autenticación.
2. Recibe `{"type": "connected"}`.
3. Recibe un lote de spans raíz (`elevenlabs.conversation`, `elevenlabs.source` = `monitoring`).
4. Recibe el historial almacenado en caché (aproximadamente los últimos 100 eventos) y, después, `{"type": "history_complete"}`.
5. Recibe lotes de spans en directo a medida que se producen los eventos.

Con `events_format=json` (predeterminado), el WebSocket devuelve eventos de cliente sin procesar en lugar de `resourceSpans`. Los comandos de control coinciden con los de [Monitorización en tiempo real](/docs/es/eleven-agents/guides/realtime-monitoring#control-commands).

### Forma de la traza

```text
elevenlabs.conversation
├── elevenlabs.turn.0
│   ├── elevenlabs.event.user_transcript
│   └── elevenlabs.tool.{name}
└── elevenlabs.turn.1
```

| Aspecto              | Post-llamada y GET                        | Monitorización                                                   |
| -------------------- | ----------------------------------------- | ---------------------------------------------------------------- |
| Granularidad         | Una traza por webhook o solicitud         | Muchos mensajes por conversación                                 |
| Spans de eventos     | Turnos de transcripción                   | `elevenlabs.event.{type}`                                        |
| Agrupación de turnos | Implícita en el orden de la transcripción | Explícita `elevenlabs.turn.N`                                    |
| Orden                | Orden estable de la transcripción         | Los eventos pueden llegar fuera de un orden cronológico estricto |

Los eventos estructurados se asignan a atributos específicos (por ejemplo, `elevenlabs.user.text`, `elevenlabs.agent.text`). Los eventos desconocidos usan `elevenlabs.event.data` con JSON truncado.

> **Info**
>
> No asumas que el orden de los eventos coincide con el orden de habla. Correlaciona los spans en directo con los datos post-llamada usando
> el mismo `traceId`.

### Ejemplo de conexión

**`TypeScript`**

```typescript title="TypeScript"
import WebSocket from "ws";

const ws = new WebSocket(
  "wss://api.elevenlabs.io/v1/convai/conversations/conv_9001k1zph3fkeh5s8xg9z90swaqa/monitor?events_format=opentelemetry",
  {
    headers: {
      "xi-api-key": process.env.ELEVENLABS_API_KEY!,
    },
  }
);

ws.on("message", (raw) => {
  const msg = JSON.parse(raw.toString());
  if (msg.type === "connected" || msg.type === "history_complete") return;

  if (msg.resourceSpans) {
    forwardToCollector({ resourceSpans: msg.resourceSpans });
  }
});
```

**`Python`**

```python title="Python"
import asyncio
import json
import os

import websockets
from dotenv import load_dotenv

load_dotenv()

async def monitor_opentelemetry():
    uri = (
        "wss://api.elevenlabs.io/v1/convai/conversations/conv_9001k1zph3fkeh5s8xg9z90swaqa/monitor"
        "?events_format=opentelemetry"
    )
    headers = {"xi-api-key": os.getenv("ELEVENLABS_API_KEY")}

    async with websockets.connect(uri, extra_headers=headers) as ws:
        async for raw in ws:
            msg = json.loads(raw)
            if msg.get("type") in ("connected", "history_complete"):
                continue
            if msg.get("resourceSpans"):
                forward_to_collector({"resourceSpans": msg["resourceSpans"]})

asyncio.run(monitor_opentelemetry())
```

## Estructura JSON de OTLP

Las trazas de OpenTelemetry de todas las vías comparten el mismo diseño de lote JSON de OTLP:

```json
{
  "resourceSpans": [
    {
      "resource": {
        "attributes": [
          { "key": "service.name", "value": { "stringValue": "elevenlabs-convai" } },
          {
            "key": "elevenlabs.conversation_id",
            "value": { "stringValue": "conv_9001k1zph3fkeh5s8xg9z90swaqa" }
          }
        ]
      },
      "scopeSpans": [
        {
          "scope": { "name": "elevenlabs.convai", "version": "1.0.0" },
          "spans": [
            {
              "traceId": "32_hex_chars",
              "spanId": "16_hex_chars",
              "name": "elevenlabs.recv.agent_response",
              "startTimeUnixNano": "1700000000000000000",
              "endTimeUnixNano": "1700000001000000000",
              "status": { "code": 1 }
            }
          ]
        }
      ]
    }
  ]
}
```

## Limitaciones

* No hay envío directo a tu ruta gRPC de OTLP.
* Las cargas útiles son JSON con formato de exportación de OTLP, no protobuf sin procesar en la transmisión.

## Documentación relacionada

* [Webhooks post-llamada](/docs/es/eleven-agents/workflows/post-call-webhooks)
* [Monitorización en tiempo real](/docs/es/eleven-agents/guides/realtime-monitoring)