Observabilidad de LLMs en 2026: Guía Completa con LangFuse, LangSmith y Helicone

Guía práctica 2026 para instrumentar aplicaciones LLM en producción con LangFuse, LangSmith, Helicone y OpenTelemetry GenAI. Trazas jerárquicas, evaluaciones LLM-as-a-Judge, métricas de coste y código listo para usar.

Cuando una aplicación basada en LLMs llega a producción, los problemas dejan de ser de "respuestas raras en local" y se convierten en facturas inesperadas, latencias erráticas y alucinaciones imposibles de reproducir. Lo he visto suficientes veces como para perder la cuenta. Sin observabilidad de LLMs, no hay forma de saber por qué un agente decidió llamar tres veces a la misma herramienta, qué prompt generó esa respuesta tóxica del jueves pasado, o por qué el coste mensual se duplicó tras un cambio aparentemente trivial.

Esta guía cubre, paso a paso, cómo instrumentar aplicaciones de IA con las tres plataformas dominantes en 2026 — LangFuse, LangSmith y Helicone — junto con el estándar emergente de OpenTelemetry GenAI. Vamos al grano.

Qué es la observabilidad de LLMs (y por qué no basta con tu APM de siempre)

La observabilidad clásica gira alrededor de tres pilares: métricas, logs y trazas. En el mundo LLM hay que añadir un cuarto pilar crítico: evaluación de calidad de salida.

Piénsalo así: una llamada a un modelo puede tardar 800 ms, costar 0,01 USD y ejecutarse sin un solo error HTTP… y aun así devolver una respuesta incorrecta o sesgada. Las herramientas tradicionales como Datadog APM o New Relic, por buenas que sean en su terreno, no capturan esa dimensión semántica. Simplemente no fueron diseñadas para ello.

Una plataforma de observabilidad de LLMs moderna debe registrar, como mínimo:

  • Trazas jerárquicas: cadena completa de llamadas (LLM → herramienta → LLM → respuesta final), con tokens de entrada, salida y latencia por nodo.
  • Coste por petición: desglosado por modelo, tenant y endpoint.
  • Prompts y respuestas completas: con versionado para reproducir cualquier interacción histórica (sí, incluida la del incidente del lunes).
  • Evaluaciones automáticas: LLM-as-a-judge, métricas de relevancia (RAGAS), similitud semántica, detección de PII y toxicidad.
  • Feedback de usuario: pulgar arriba/abajo, correcciones manuales, sesiones marcadas.
  • Datasets y experimentos: comparar versiones de prompt o cambios de modelo sobre un conjunto fijo.

LangFuse, LangSmith y Helicone: comparativa rápida 2026

Las tres plataformas resuelven el mismo problema con filosofías muy distintas. Esta tabla resume sus diferencias actuales:

CaracterísticaLangFuseLangSmithHelicone
Modelo de despliegueCloud + self-hosted (MIT)Cloud + self-hosted enterpriseCloud + self-hosted (Apache 2.0)
Integración principalSDK nativo + OpenTelemetryVinculado a LangChain/LangGraphProxy HTTP transparente
Cambios de códigoDecoradores o wrappersDecoradores o auto-trace LangChainCambiar baseURL (cero código)
Evaluaciones LLM-as-JudgeSí, integradas y customSí, integradas y customVía integraciones
Playground de promptsSí, con A/B y versionadoSí, hub de promptsLimitado
Caché de respuestasNo nativoNo nativoSí, integrado
Mejor paraStack agnóstico, OSS firstEquipos full LangChainSetup mínimo, gateway

¿Cuál elegir según el caso?

  • Si tu stack es LangChain o LangGraph y trabajas en una empresa con presupuesto, LangSmith ofrece, sin duda, la mejor integración nativa.
  • Si necesitas self-host real, licencia OSS permisiva y un SDK que funcione con cualquier framework (Vercel AI SDK, LlamaIndex, código propio…), LangFuse es la apuesta más segura.
  • Si quieres añadir observabilidad a un proyecto existente sin tocar la lógica y, de paso, ganar caché y rate limiting, Helicone como proxy es lo más rápido. Honestamente, en muchos clientes lo metemos en producción la misma tarde.

Instrumentación con LangFuse y el SDK de OpenAI

LangFuse v3 introduce un decorador @observe que envuelve cualquier función Python o TypeScript y captura la traza automáticamente. Veamos un ejemplo con el SDK de OpenAI v2 y un agente simple con búsqueda web.

pip install langfuse openai==2.* python-dotenv
import os
from langfuse import observe, get_client
from langfuse.openai import openai

# Las variables LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY
# y LANGFUSE_HOST se leen del entorno automáticamente.
langfuse = get_client()

@observe(name="buscar_web")
def buscar_web(query: str) -> str:
    # En produccion aqui iria una llamada real a Tavily, Brave o Exa.
    return f"Resultados simulados para: {query}"

@observe(name="agente_investigador")
def agente_investigador(pregunta: str) -> str:
    # 1. El modelo decide si necesita herramientas.
    plan = openai.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[
            {"role": "system", "content": "Decide si necesitas buscar en la web. Responde SOLO con la query o con NO."},
            {"role": "user", "content": pregunta},
        ],
        metadata={"step": "planning"},
    )
    decision = plan.choices[0].message.content.strip()

    contexto = ""
    if decision != "NO":
        contexto = buscar_web(decision)

    # 2. Respuesta final con el contexto recuperado.
    respuesta = openai.chat.completions.create(
        model="gpt-4.1",
        messages=[
            {"role": "system", "content": "Responde basandote SOLO en el contexto."},
            {"role": "user", "content": f"Contexto:\n{contexto}\n\nPregunta: {pregunta}"},
        ],
        metadata={"step": "answer"},
    )

    # Marcar la traza con metadatos de negocio.
    langfuse.update_current_trace(
        user_id="usuario_42",
        session_id="sesion_demo",
        tags=["produccion", "agente_v2"],
    )

    return respuesta.choices[0].message.content

if __name__ == "__main__":
    print(agente_investigador("Que modelo lanzo Anthropic en marzo de 2026?"))
    langfuse.flush()

El resultado en el panel de LangFuse es una traza jerárquica con dos llamadas LLM y una llamada a herramienta, con tokens, latencia y coste por nodo. La clave (y esto se aprende a base de tropezarse) está en los metadata y tags: te permiten segmentar después por entorno, versión de prompt o cohorte de usuario. Sin ellos, tienes un montón de trazas bonitas… y cero capacidad de filtrar.

Capturar feedback del usuario

El feedback humano es, sin discusión, el dataset más valioso a largo plazo. Para registrarlo, basta con asociar un trace_id a la respuesta y enviar un score cuando el usuario interactúe:

from langfuse import get_client

langfuse = get_client()

def registrar_voto(trace_id: str, util: bool, comentario: str | None = None):
    langfuse.create_score(
        trace_id=trace_id,
        name="utilidad_usuario",
        value=1 if util else 0,
        comment=comentario,
        data_type="BOOLEAN",
    )

Instrumentación con LangSmith para stacks LangChain

Si ya usas LangChain o LangGraph, LangSmith se activa con dos variables de entorno y registra automáticamente cada nodo del grafo, cada herramienta y cada llamada al modelo. No es exageración: literalmente exportas las variables y ya tienes trazas.

export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=ls_...
export LANGSMITH_PROJECT=produccion-agentes
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
from langsmith import traceable

@traceable(name="herramienta_facturacion")
def consultar_factura(cliente_id: str) -> dict:
    return {"cliente_id": cliente_id, "saldo": 124.50, "vencimiento": "2026-05-15"}

agente = create_react_agent(
    model=ChatAnthropic(model="claude-sonnet-4-6"),
    tools=[consultar_factura],
    prompt="Eres un asistente de soporte de facturacion.",
)

resultado = agente.invoke({
    "messages": [{"role": "user", "content": "Cuanto debe el cliente C-991?"}]
})
print(resultado["messages"][-1].content)

En la UI de LangSmith aparece la traza completa con cada paso del bucle ReAct, los tokens consumidos por Claude y las llamadas a la herramienta. Lo realmente potente llega después: convertir trazas reales en datasets para evaluar regresiones.

Crear un dataset desde trazas de producción

from langsmith import Client

client = Client()

# Filtrar trazas con feedback negativo en la ultima semana.
trazas = client.list_runs(
    project_name="produccion-agentes",
    filter='and(eq(feedback_key, "thumbs"), eq(feedback_score, 0))',
    start_time="2026-04-19T00:00:00Z",
)

dataset = client.create_dataset("regresiones-soporte-2026-04")
for r in trazas:
    client.create_example(
        inputs=r.inputs,
        outputs=r.outputs,
        dataset_id=dataset.id,
    )

Helicone como proxy: observabilidad sin tocar código

Helicone es radicalmente distinto. En vez de instrumentar la aplicación, se interpone como proxy entre tu código y el proveedor. Cualquier petición que pasa por él queda registrada con tokens, coste y latencia. Y punto.

import { OpenAI } from "openai";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: "https://oai.helicone.ai/v1",
  defaultHeaders: {
    "Helicone-Auth": `Bearer ${process.env.HELICONE_API_KEY}`,
    "Helicone-User-Id": "usuario_42",
    "Helicone-Property-Tenant": "acme_corp",
    "Helicone-Cache-Enabled": "true",
    "Helicone-Cache-Bucket-Max-Size": "10",
  },
});

const respuesta = await client.chat.completions.create({
  model: "gpt-4.1-mini",
  messages: [{ role: "user", content: "Resume este articulo en 3 puntos." }],
});

Con cabeceras como Helicone-Cache-Enabled activas un caché LRU compartido que devuelve respuestas idénticas sin tocar el modelo (ideal para prompts deterministas o evaluaciones repetidas). Es, probablemente, la forma más barata de reducir el coste de un sistema en producción sin refactorizar absolutamente nada.

OpenTelemetry GenAI: el estándar que unifica todo

En 2026, las semantic conventions GenAI de OpenTelemetry han alcanzado por fin estabilidad y todos los grandes (LangFuse, Arize Phoenix, Datadog, Grafana, Honeycomb) las soportan. Esto significa que puedes instrumentar tu app una sola vez y enviarla a múltiples backends sin cambiar el código. Para mí, este es el mayor cambio del año.

pip install opentelemetry-instrumentation-openai-v2 \
            opentelemetry-exporter-otlp \
            opentelemetry-sdk
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor

# 1. Configurar el exportador (apuntando a LangFuse, Phoenix, etc.).
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(
    endpoint="https://cloud.langfuse.com/api/public/otel/v1/traces",
    headers={"Authorization": "Basic "},
)))
trace.set_tracer_provider(provider)

# 2. Instrumentar OpenAI automaticamente.
OpenAIInstrumentor().instrument()

# 3. A partir de aqui, cualquier llamada genera spans GenAI estandar.
from openai import OpenAI
OpenAI().chat.completions.create(
    model="gpt-4.1-mini",
    messages=[{"role": "user", "content": "Hola"}],
)

Los spans incluirán atributos como gen_ai.request.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens y eventos para los mensajes de chat. ¿La gran ventaja? Si mañana cambias de proveedor de observabilidad, solo cambias el endpoint del exportador. Cero refactor, cero migraciones tediosas.

Evaluaciones automáticas: del log al juicio de calidad

Tener trazas no es suficiente. Hay que medir si las respuestas son buenas, y eso es un mundo aparte. Las tres familias de evaluadores que se usan en 2026 son:

  1. Heurísticas deterministas: longitud, formato JSON válido, presencia de keywords prohibidas, latencia por debajo de SLO.
  2. LLM-as-a-Judge: un modelo (normalmente más barato) puntúa la salida según una rúbrica.
  3. Métricas RAG (RAGAS): faithfulness, answer relevancy, context precision para sistemas con recuperación.

LLM-as-a-Judge en LangFuse

from langfuse import get_client
from openai import OpenAI

langfuse = get_client()
juez = OpenAI()

PROMPT_JUEZ = """Eres un evaluador estricto. Puntua de 0 a 1 si la RESPUESTA
contesta correctamente la PREGUNTA usando solo el CONTEXTO. Devuelve JSON:
{"score": float, "razon": str}.

PREGUNTA: {pregunta}
CONTEXTO: {contexto}
RESPUESTA: {respuesta}"""

def evaluar_traza(trace_id: str, pregunta: str, contexto: str, respuesta: str):
    salida = juez.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[{"role": "user", "content": PROMPT_JUEZ.format(
            pregunta=pregunta, contexto=contexto, respuesta=respuesta
        )}],
        response_format={"type": "json_object"},
    )
    import json
    veredicto = json.loads(salida.choices[0].message.content)
    langfuse.create_score(
        trace_id=trace_id,
        name="faithfulness",
        value=veredicto["score"],
        comment=veredicto["razon"],
    )

Truco práctico (uno que me ha ahorrado mucho dinero): ejecuta el evaluador en un worker asíncrono — Celery, BullMQ, Cloud Tasks, lo que tengas a mano — y aplícalo solo a una muestra del tráfico. Un 5–10% suele bastar para detectar regresiones sin disparar el coste del propio juez.

Métricas y alertas que de verdad importan

Después de instrumentar tres docenas de aplicaciones LLM, los dashboards que aportan valor real son sorprendentemente pocos. Te dejo los que de verdad consulto:

  • Coste por usuario activo diario: si sube de golpe, alguien está en bucle o explotando un endpoint.
  • P95 de latencia end-to-end por endpoint: incluye herramientas y reintentos, no solo el LLM.
  • Tasa de respuestas con feedback negativo: el indicador más barato y honesto de calidad.
  • Tokens de salida medios: caídas bruscas suelen indicar que el modelo está rechazando o truncando.
  • Llamadas a herramientas por turno: en agentes, valores anómalamente altos = bucle.
  • Tasa de error 429/529 por proveedor: para ajustar rate limits y backoff.

Y un consejo aprendido por las malas: configurar alertas sobre cambios relativos (desviación >2σ del último mes) funciona mejor que umbrales absolutos en este dominio. El tráfico LLM es demasiado irregular para los umbrales fijos.

Errores frecuentes al implementar observabilidad de LLMs

  • Loggear prompts con PII sin redacción: usa middleware para enmascarar emails, teléfonos y nombres antes de enviar a la plataforma. LangFuse y Helicone tienen redacción configurable.
  • Capturar todo, evaluar nada: trazas sin scores son solo una factura más cara. Define al menos una métrica de calidad en la primera semana.
  • No versionar prompts: si no puedes responder "qué versión del prompt corrió en esa traza del martes", no tienes observabilidad real. Tienes registros bonitos.
  • Mezclar entornos en el mismo proyecto: separa dev, staging y prod por proyecto u organización; las métricas se contaminan rápido.
  • Confiar solo en LLM-as-a-Judge: combínalo siempre con feedback humano y heurísticas deterministas; los jueces tienen sus propios sesgos (y a veces son sorprendentes).

Preguntas frecuentes

¿Cuál es la diferencia entre LangFuse y LangSmith?

LangSmith está fuertemente integrado con LangChain y LangGraph, ofrece auto-tracing sin código adicional para esos frameworks y es un producto comercial de la propia LangChain. LangFuse, por su parte, es agnóstico (funciona con cualquier SDK), tiene licencia MIT con self-hosting completo y soporta nativamente OpenTelemetry. Para proyectos no-LangChain o que requieran self-host real, LangFuse es la opción más flexible.

¿Helicone reemplaza a LangFuse o LangSmith?

No siempre, y esta es la confusión más común. Helicone es un proxy HTTP, lo que lo hace excelente para añadir métricas, caché y rate limiting sin tocar código. Pero no captura la lógica interna de un agente (decisiones, llamadas a herramientas locales, transformaciones intermedias) tan bien como un SDK con decoradores. Muchos equipos — los más maduros, diría yo — usan Helicone para observabilidad básica y un SDK encima para el detalle de los agentes.

¿Cuánto cuesta la observabilidad de LLMs en producción?

Self-hosting LangFuse en una instancia pequeña (4 vCPU, 8 GB RAM, Postgres + ClickHouse) cuesta entre 50 y 150 USD/mes y cubre millones de eventos. Las versiones cloud arrancan gratis con cuotas y suben a 99–500 USD/mes para equipos. El mayor coste oculto, casi siempre, suele ser el del propio LLM-as-a-Judge si se aplica al 100% del tráfico — limítalo a una muestra y dormirás mejor.

¿Cómo evitar registrar datos sensibles en las trazas?

Implementa una capa de redacción antes de enviar al SDK: regex para emails, teléfonos y números de tarjeta, y un modelo NER (Presidio de Microsoft, por ejemplo) para nombres y direcciones. LangFuse permite configurar reglas de redacción a nivel de proyecto, y Helicone ofrece "PII Detection" como add-on. Para entornos regulados (sanidad, banca), considera self-host obligatorio. No es opcional.

¿Vale la pena migrar a OpenTelemetry GenAI ahora?

Sí, si estás empezando un proyecto nuevo o vas a refactorizar la instrumentación. La inversión inicial es similar a usar un SDK propietario, pero te libera del vendor lock-in: puedes apuntar los mismos spans a LangFuse hoy y a Datadog mañana sin tocar el código de la aplicación. Para proyectos consolidados con un SDK funcionando, la migración no es urgente, pero conviene planificarla en 6–12 meses.

Conclusión

La observabilidad de LLMs en 2026 ya no es opcional. Cualquier sistema que toma decisiones con un modelo en producción necesita trazas, métricas de coste y al menos una señal de calidad. Punto.

La buena noticia es que el ecosistema ha madurado lo suficiente como para empezar en horas, no semanas. Helicone para añadir métricas con cero código, LangFuse para stacks heterogéneos con self-host, LangSmith para equipos enteramente LangChain, y OpenTelemetry GenAI como capa común que asegura que tu inversión en instrumentación sobreviva al próximo cambio de stack. Elige uno, instrúmenta hoy mismo, y agradécete a ti mismo dentro de tres meses cuando algo se rompa en producción y puedas saber, exactamente, qué pasó.

Sobre el Autor Editorial Team

Our team of expert writers and editors.