Por qué OpenTelemetry se está convirtiendo en infraestructura clave para la IA

OpenTelemetry puede sonar a una pieza bastante aburrida de infraestructura.

Y, en cierto modo, lo es.

Su trabajo consiste en responder preguntas como:

  • ¿Qué está haciendo mi aplicación?
  • ¿Dónde está fallando?
  • ¿Cuánto tarda cada operación?
  • ¿Qué servicio llamó a cuál?
  • ¿Qué ocurrió antes de que apareciera un error?

Para ello, OpenTelemetry proporciona un estándar abierto para generar y transportar trazas, métricas y logs.

Una aplicación puede instrumentarse utilizando OpenTelemetry y enviar después esa telemetría al sistema de observabilidad que quiera.

La arquitectura suele parecerse a esto:

Aplicación
↓
OpenTelemetry
↓
Collector
↓
Backend de observabilidad

La aplicación genera telemetría.

El Collector puede procesarla, filtrarla, transformarla o enrutarla.

Y finalmente herramientas de observabilidad, almacenamiento o análisis pueden consumirla.

La idea parece sencilla, pero resuelve un problema importante: evitar que cada aplicación tenga que implementar una forma distinta de describir lo que está ocurriendo internamente.

Y ese problema se está volviendo especialmente relevante con los sistemas de inteligencia artificial.

Observar sistemas de IA

Una aplicación tradicional puede generar una traza como esta:

HTTP request
└── database query

Una aplicación basada en IA puede parecerse más a esto:

User request

└── Agent
├── LLM call
├── Retrieval
│ └── Vector database
├── Tool call
│ └── CRM
├── LLM call
└── Tool call
└── Payment API

De repente ya no queremos saber únicamente cuánto ha tardado una petición.

También queremos entender cosas como:

  • qué modelo se utilizó,
  • cuántos tokens consumió,
  • qué herramientas llamó un agente,
  • qué documentos recuperó,
  • qué proveedor ejecutó el modelo,
  • cuánto costó una ejecución,
  • por qué terminó una generación,
  • qué pasos siguió un agente,
  • qué evaluación recibió una respuesta.

Aquí aparece un problema aparentemente pequeño.

No existe ninguna razón técnica que impida a cada equipo registrar estos datos como quiera.

Un equipo podría guardar el modelo como:

llm.model

Otro como:

model_name

Y otro como:

provider_model

Los tres campos representan prácticamente lo mismo.

El problema aparece cuando queremos comparar aplicaciones, cambiar de proveedor de observabilidad, construir herramientas sobre esas trazas o analizar sistemas desarrollados con diferentes frameworks.

Multiplica esta inconsistencia por tokens, agentes, herramientas, retrieval, modelos, evaluaciones y proveedores.

Lo que parecía un problema de nomenclatura termina convirtiéndose en un problema de infraestructura.

OpenTelemetry intenta crear un lenguaje común para la IA

Aquí entran las GenAI Semantic Conventions de OpenTelemetry.

Las semantic conventions definen una forma común de representar determinadas operaciones dentro de una traza.

En lugar de que cada SDK, framework o plataforma de observabilidad invente su propia representación de una llamada a un modelo, el objetivo es que todo el ecosistema pueda compartir un mismo vocabulario.

Por ejemplo, una ejecución podría conceptualmente producir una traza como:

agent.run
├── gen_ai.chat
├── retrieval
├── execute_tool
└── gen_ai.chat

Y cada operación puede llevar atributos estructurados sobre el modelo, proveedor, tokens utilizados o herramienta ejecutada.

Lo importante no es exactamente cómo se llame hoy cada atributo.

Lo importante es que exista un contrato común.

Si diferentes aplicaciones producen telemetría siguiendo el mismo esquema, diferentes herramientas pueden entenderla.

Eso permite empezar a separar dos cosas que históricamente han estado demasiado unidas:

Instrumentación ≠ Backend de observabilidad


Instrumentar una vez

Sin un estándar común, integrar una plataforma de observabilidad puede acabar introduciendo código específico del proveedor por toda la aplicación.

Por ejemplo:

vendor.start_llm_span(...)
vendor.log_tokens(...)
vendor.log_tool_call(...)
vendor.finish_span(...)

Si más adelante queremos cambiar de plataforma, parte de esa instrumentación también tiene que cambiar.

Con OpenTelemetry, el modelo puede ser diferente:

with tracer.start_as_current_span("generate_response") as span:
response = model.generate(prompt)

span.set_attribute("gen_ai.request.model", model_name)

La aplicación genera una traza utilizando un estándar común.

Después podemos decidir dónde enviarla.

┌── Backend A
Aplicación → OTel → Collector ── Backend B
└── Data warehouse

Incluso podemos enviarla simultáneamente a varios sistemas.

Esto convierte la telemetría en una capa independiente de la herramienta que finalmente la visualiza.

Y eso es particularmente interesante en IA, donde el ecosistema cambia extremadamente rápido.

Hoy una aplicación puede utilizar un proveedor de modelos, mañana otro.

Hoy puede utilizar un framework de agentes y dentro de seis meses reemplazarlo.

La observabilidad debería sobrevivir a esos cambios.

Un ejemplo: entender qué está haciendo un agente

Imaginemos un agente encargado de resolver una petición de soporte.

El usuario escribe:

Quiero saber por qué todavía no me han devuelto
el dinero del pedido 839281.

El agente realiza estas operaciones:

agent.run
│
├── llm
│
├── tool: get_order
│
├── tool: get_refund_status
│
└── llm

Una traza permite reconstruir la ejecución completa.

Podemos descubrir, por ejemplo, que el primer modelo tardó 800 ms, la llamada a get_order tardó 120 ms, get_refund_status falló una vez y tuvo que repetirse, y la generación final consumió 1.200 tokens.

Cuando un sistema de IA falla, observar únicamente el HTTP 500 de la petición exterior dice muy poco.

Queremos entender qué ocurrió dentro del sistema.

Eso hace que las trazas sean especialmente valiosas para agentes.


Otro ejemplo: encontrar problemas de coste

La observabilidad también puede responder preguntas que no son estrictamente errores.

Supongamos que una nueva versión de un agente empieza a consumir el doble de tokens.

Sin trazas estructuradas podemos saber que la factura ha subido.

Con ellas podemos detectar dónde:

Version 41

average input tokens: 2,140
average output tokens: 430

frente a:

Version 42

average input tokens: 5,870
average output tokens: 460

Tal vez el sistema está enviando demasiado contexto al modelo, recuperando demasiados documentos o una herramienta está devolviendo respuestas enormes.

La telemetría convierte un aumento de costes en algo investigable.

Pero observar IA introduce un problema nuevo

En una aplicación tradicional, una traza suele contener información sobre el software: tiempos de ejecución, errores, endpoints o consultas a bases de datos.

En una aplicación de IA puede contener algo bastante diferente: los datos que el usuario está procesando.

Un prompt puede incluir un nombre, un email, información médica o datos financieros. Una llamada a una herramienta puede incluir el expediente completo de un cliente. Un sistema RAG puede recuperar partes de documentos internos.

Y un agente puede hacer que esos datos pasen por muchos sistemas durante una sola ejecución:

Usuario
↓
Aplicación
├── Modelo
├── Vector database
├── CRM
├── APIs externas
└── Sistema de observabilidad

El problema no es únicamente que existan datos sensibles.

Es que empiezan a existir copias de esos datos en muchos sitios diferentes.

Cada copia puede tener sus propios permisos, políticas de retención, backups, regiones de almacenamiento y proveedores externos.

Una traza creada para depurar un agente puede terminar convirtiéndose accidentalmente en otra base de datos con información personal.

Minimizar antes de almacenar

La primera solución es bastante sencilla: no almacenar aquello que no necesitamos.

Para entender el comportamiento de un agente podemos querer conservar:

model = ...
input_tokens = 1842
output_tokens = 312
tool = get_customer
latency = 842ms
status = success

sin conservar necesariamente:

Me llamo María García,
mi teléfono es +34 612 345 678 y...

Pero en IA esto no siempre es suficiente.

A veces necesitamos parte del contenido para entender por qué un agente tomó una decisión, evaluar una respuesta o reproducir un fallo.

Ahí entra una segunda estrategia: transformar el dato antes de almacenarlo o enviarlo a sistemas externos.

Por ejemplo:

María García solicitó un reembolso del pedido 839281.

puede convertirse en:

<PERSON_71C2> solicitó un reembolso del pedido <ORDER_89AD>.

La traza sigue siendo útil.

Podemos incluso mantener el mismo identificador pseudónimo a través de varios spans para reconstruir qué hizo el agente sin exponer directamente la identidad de la persona.

Hay aquí una distinción importante.

Si destruimos cualquier posibilidad razonable de identificar posteriormente a María, hablamos de anonimización.

Si existe una correspondencia privada que permite recuperar su identidad, hablamos de pseudonimización.

Para observabilidad, la segunda suele ser especialmente interesante porque permite mantener correlaciones sin distribuir el identificador original por todos los sistemas.


Una capa de privacidad antes de que los datos salgan

Una arquitectura posible sería introducir una capa específica para inspeccionar y transformar los datos antes de exportarlos:

AI Application
↓
Instrumentation
↓
Privacy layer
│
├── Detectar PII
├── Eliminar secretos
├── Aplicar políticas
├── Pseudonimizar identificadores
└── Redactar contenido
↓
Telemetry pipeline
↓
Observability backend

La idea importante es dónde ocurre esa transformación.

Si el backend recibe primero:

María García

y después lo transforma en:

<PERSON>

el backend ya ha recibido el dato original.

Es una propiedad de seguridad diferente de hacer la transformación dentro de nuestra propia infraestructura y exportar únicamente:

<PERSON_71C2>

La misma lógica debería aplicarse no solamente a prompts, sino también a:

  • respuestas del modelo,
  • argumentos de herramientas,
  • resultados de herramientas,
  • documentos recuperados mediante RAG,
  • metadatos,
  • excepciones,
  • logs.

En agentes, probablemente son precisamente las llamadas a herramientas y los documentos recuperados los lugares donde aparecen algunos de los datos más sensibles.


Cómo construir esa capa

No hace falta resolver el problema exclusivamente con otro LLM.

Una implementación razonable puede combinar varias técnicas.

Primero, detectores deterministas para información fácil de reconocer:

emails
teléfonos
IPs
tarjetas de crédito
API keys
identificadores internos

Después, modelos de reconocimiento de entidades para información menos estructurada:

personas
organizaciones
direcciones
localizaciones
información médica

Y finalmente reglas específicas de la aplicación.

Un identificador de paciente o un número de contrato interno probablemente no pueda descubrirlo una librería genérica. La propia organización conoce el formato y puede definir cómo tratarlo.

Sobre esas detecciones se puede aplicar una política:

EMAIL → eliminar
PHONE_NUMBER → eliminar
PERSON → pseudonimizar
CUSTOMER_ID → HMAC/hash estable
API_KEY → bloquear completamente
ORDER_ID → conservar

Esto es más útil que aplicar simplemente [REDACTED] a todo.

El objetivo no debería ser eliminar la máxima cantidad posible de información.

Debería ser conservar la mínima cantidad necesaria para que la traza siga siendo útil.

Ya existen piezas open source para hacerlo, entre las más maduras están Presidio, LLM Guard o Guardrails AI. Personalmente he desarrollado dos proyectos open source en dirección a esta solución (pii-firewall y gateforge).

La observabilidad de IA se está convirtiendo en infraestructura

Los sistemas de IA están dejando de ser una única llamada a un modelo.

Cada vez se parecen más a sistemas distribuidos formados por modelos, agentes, herramientas, bases de datos, retrieval y APIs externas.

Necesitamos entender qué ocurre dentro de ellos cuando fallan, cuando empiezan a gastar demasiado o cuando un agente toma una decisión inesperada.

Para hacerlo necesitamos observabilidad.

Pero también necesitamos evitar que conseguir esa visibilidad implique copiar prompts, documentos internos y datos personales en cada sistema que toca una traza.

Por eso creo que las dos piezas van a terminar evolucionando juntas:

Observabilidad estándar
+
Privacy by design

OpenTelemetry puede proporcionar el lenguaje y la infraestructura común para observar estos sistemas.

La siguiente pieza consiste en decidir qué información permitimos cruzar esa frontera.

Porque en sistemas de IA, una buena infraestructura de observabilidad no debería limitarse a explicar qué ocurrió.

También debería permitir hacerlo sin recopilar datos que nunca necesitábamos almacenar.