Lo esencial
"It works on my machine" ("en mi máquina funciona") es la frase más cara de la industria. Desplegaste tu agente, funciona, los clientes lo usan. Y luego llega un mensaje: "se rompió desde ayer en la noche". Y te das cuenta de que no te enteraste por tu sistema, sino por un usuario molesto.
La observabilidad en producción (production observability) son tus ojos y oídos dentro del sistema en marcha. Sin ella eres un piloto ciego: el motor funciona, pero no sabes cuándo se va a sobrecalentar, cuándo se acaba el combustible, cuándo se va a desprender un ala.
En esta lección: 5 métricas que DEBES monitorear, 3 niveles de alertas y 4 herramientas para agentes de IA (lista a octubre de 2026). Sin relleno, con ejemplos de cifras y bocetos de tableros. Los umbrales de la lección son un punto de partida: con el tiempo, ajusta los tuyos con datos reales.
🎯 El principio principal: no logs, sino señales
Registrar (logging) ≠ observabilidad. Puedes tener gigabytes de logs y no entender qué pasa. La observabilidad es la capacidad de responder preguntas sobre el sistema sin meterte al código.
Los tres pilares clásicos (según el estándar OpenTelemetry https://opentelemetry.io):
- Metrics (métricas): números en el tiempo (latencia, costo, errores)
- Traces (trazas): el recorrido de una solicitud por todo el sistema
- Logs (registros): eventos con contexto
Para los agentes de IA se agrega un cuarto:
- Lo específico de los LLM: prompts, respuestas, uso de tokens, aciertos de caché
Conceptos clave
- p50 / p95 / p99: percentiles de latencia: la mitad de las solicitudes es más rápida que p50, el 95% más rápida que p95, el 99% más rápida que p99. El p99 muestra el peor caso que ven tus usuarios peor atendidos
- Cardinalidad: el número de valores únicos en una métrica. Las métricas de alta cardinalidad (por usuario) son caras de guardar
- Muestreo (sampling): guardar no el 100% de las trazas, sino 1-10% de las normales + 100% de los errores
- Fatiga de alertas (alert fatigue): cuando hay tantas alertas que las ignoras todas. Es más peligrosa que no tener alertas
- SLI / SLO / SLA: Service Level Indicator (la métrica), Objective (la meta interna), Agreement (el contrato con el cliente)
- Detección de anomalías: desviación respecto a la línea base (el promedio de ayer × 2 = sospechoso)
- Trace ID: un identificador único de la solicitud que pasa por todos los componentes, para correlacionar
- Cache hit ratio: el % de solicitudes que aciertan en la caché de prompts. Afecta directamente el costo
Teoría
Las 5 métricas obligatorias
Es el mínimo. Sin ellas no entiendes qué pasa con tu agente en producción.
Métrica 1: latencia (tiempo de respuesta)
Qué medir: el tiempo de respuesta p50, p95 y p99 por solicitud
Metas 2026:
| Tipo de agente | p50 | p95 | p99 |
|---|---|---|---|
| Chat (texto) | <3s | <8s | <15s |
| Voz (tiempo real) | <500ms | <1s | <2s |
| Batch (segundo plano) | OK 1-24h | OK 1-24h | OK 1-24h |
| API (integración B2B) | <1s | <3s | <5s |
Por qué el p99 es más crítico que el p50: si tienes 1000 solicitudes al día y p99 = 30s, significa que 10 usuarios al día esperan medio minuto. Se van. Un p50 = 2s se ve bonito en el reporte, pero esconde el problema.
Herramientas de seguimiento:
- LangSmith (https://www.langchain.com/langsmith): trazas de las llamadas al LLM; tiene plan gratuito (límites en su sitio)
- Helicone (https://www.helicone.ai/): un proxy de LLM con métricas; en marzo de 2026 la empresa fue comprada por Mintlify y el servicio está en modo mantenimiento, sin funciones nuevas
- Prometheus/Grafana propio: autoalojado, gratis, pero se come tu tiempo en la configuración
Métrica 2: costo por interacción
Qué medir:
- $/conversación (una sesión de un usuario)
- $/usuario (acumulado del mes)
- $/función (a dónde se va el dinero)
- Gasto mensual total (la cuenta completa)
Umbral de anomalía: un pico de más de 2x el promedio diario → alerta. Si ayer gastaste $20 y hoy a mediodía ya vas en $80, algo anda mal. Puede ser que:
- Un error metió un ciclo infinito de llamadas
- Alguien encontró cómo abusar (prompt injection, solicitudes repetidas)
- En el código se cambió por accidente el modelo de Haiku a Opus
Herramientas:
- Anthropic Console (https://platform.claude.com): tablero de facturación integrado
- LangSmith / Helicone: el costo de cada llamada, desglosado por usuario y por función
- Registro propio en KV: un contador hecho por ti en Cloudflare KV / Redis
Señales de ahorro que se ven con el monitoreo:
- Cache hit ratio bajo (<30%) → revisa la estructura del prompt
- Los tokens de salida crecen más rápido que los de entrada → el agente se volvió más platicador (revisa el prompt de sistema)
- Las llamadas a Opus son >20% del total → revisa si usas Opus donde bastaría Sonnet
Métrica 3: tasa de errores
Qué medir (4 categorías):
- Errores de la API: 4xx, 5xx de Anthropic/OpenAI
- Fallas de herramientas: timeouts de MCP, esquemas que no coinciden, excepciones de herramientas
- Fallas de validación: la salida del LLM no coincide con el esquema JSON esperado
- Errores reportados por usuarios: comentarios explícitos de "no funciona"
Meta: <1% de errores en estado estable, <5% en un pico
Umbrales de alerta:
- Tasa de errores >5% en 5 minutos → avisa a quien está de guardia (algo se rompió ahora)
- Tasa de errores >2% en 1 hora → advertencia (tendencia a degradarse)
- Un mismo código de error >50 eventos por hora → investigar (problema sistémico)
Categorizar importa: cada error pide una reacción distinta:
| Tipo de error | Acción |
|---|---|
529 overloaded_error (Anthropic) |
Reintentar con backoff; no es culpa nuestra |
400 invalid_request_error |
Error en el código; corregir de inmediato |
429 rate_limit_error |
Subir de nivel o limitar el ritmo |
tool_use schema mismatch |
El LLM es inestable; agregar validación |
JSON parse error |
Revisar el prompt de sistema |
Métrica 4: uso de tokens
Qué medir:
- Tokens de entrada / de salida (por solicitud + acumulado)
- Cache hit ratio (% que aciertan en la caché de prompts)
- Desglose por modelo (% Haiku / % Sonnet / % Opus)
- Distribución de la longitud del contexto (ves cuándo la gente choca con el límite)
Señales de anomalía:
| Señal | Qué significa |
|---|---|
| Tokens de entrada >5x el promedio para un usuario | Error de ciclo, scraping, ataque de prompt injection |
| Cache hit <20% | La estructura del prompt no está optimizada |
| La salida promedio crece durante una semana | El prompt de sistema se está degradando; el agente se volvió más platicador |
| Contexto >150K de forma constante | Hora de una estrategia de compactación |
El cache hit ratio es una métrica crítica: leer de la caché de prompts cuesta alrededor del 10% del precio normal de los tokens de entrada (a octubre de 2026; condiciones vigentes: Lo vigente). Si el cache hit es alto, buena parte de la entrada sale varias veces más barata. Si el cache hit = 0%, pagas la tarifa completa.
# Seguimiento del cache hit ratio
def log_request(response):
cache_tokens = response.usage.cache_read_input_tokens or 0
total_input = response.usage.input_tokens + cache_tokens
cache_ratio = cache_tokens / total_input if total_input > 0 else 0
metrics.record("cache.hit_ratio", cache_ratio)
metrics.record("tokens.input", response.usage.input_tokens)
metrics.record("tokens.output", response.usage.output_tokens)Métrica 5: métricas de negocio
Las métricas técnicas muestran que el sistema funciona. Las de negocio muestran que el sistema trabaja para el negocio.
Qué medir:
| Métrica | Descripción | Meta |
|---|---|---|
| Conversation completion rate | % de sesiones que lograron su objetivo | >70% |
| CSAT (satisfacción del cliente) | Calificación explícita de 1 a 5 estrellas | >4.0 |
| Escalation rate | % de casos de "llamar a una persona" | <15% |
| Conversion rate | Para IA de ventas/marketing | Variable |
| Time-to-resolution | Cuántos turnos hasta resolver | <5 |
| Retención | % de usuarios que regresan | >30% en la semana 2 |
Herramientas:
- PostHog (https://posthog.com): analítica de producto; tiene un límite mensual gratuito (tamaño vigente en su página de precios)
- Mixpanel (https://mixpanel.com): análisis de embudos; planes en su sitio
Por qué las métricas de negocio importan más que las técnicas: puedes tener p95 = 1s y 0.5% de errores, pero si la tasa de conversaciones completadas es 20%, tu agente no ayuda a los usuarios. Técnicamente sano, en la práctica inútil.
3 niveles de alertas
Las alertas son la causa más común de errores en sistemas de IA en producción. O hay demasiadas (fatiga de alertas) o muy pocas (te enteras por el cliente).
Nivel 1: Info (canal de Slack, sin despertar a nadie)
Qué: resumen diario, reportes semanales, telemetría general Canal: #ai-prod-info o un resumen por email Tiempo de respuesta: cuando haya tiempo
Ejemplos:
- Diario a las 09:00: "Ayer: 1247 solicitudes, $12.40 de gasto, 0.3% de errores, p95 = 4.2s"
- Los lunes: "En la semana: tendencia de costo +12%, error principal: tool timeout (43 eventos)"
- Mensual: "Reporte mensual de optimización de precios"
Objetivo: contexto y tendencias, no monitoreo reactivo.
Nivel 2: Warning (mención en Slack, respuesta en menos de 1 hora)
Qué: señales de degradación, problemas que pueden volverse críticos Canal: #ai-prod-alerts + @here Tiempo de respuesta: 1 hora
Ejemplos:
- Pico de costo de 2x el promedio diario
- Tasa de errores >2% en 15 minutos
- Latencia p95 >2x el SLA
- El cache hit ratio bajó de 30%
- Un usuario con >100 solicitudes en una hora (posible abuso)
Herramienta: webhook entrante de Slack + mensaje estructurado
# Ejemplo de envío de una advertencia
def send_warning(metric, value, threshold):
slack_webhook = os.getenv("SLACK_WARNING_WEBHOOK")
payload = {
"text": f"@here Warning: {metric} = {value} (threshold: {threshold})",
"attachments": [{
"color": "warning",
"fields": [
{"title": "Metric", "value": metric, "short": True},
{"title": "Current", "value": str(value), "short": True},
{"title": "Threshold", "value": str(threshold), "short": True},
{"title": "Dashboard", "value": "https://enlace-a-tu-tablero", "short": True}
]
}]
}
requests.post(slack_webhook, json=payload)Nivel 3: Critical (avisar a quien está de guardia, respuesta en 5 min)
Qué: afecta a clientes, sistema caído, incidentes de seguridad Canal: PagerDuty / llamada / SMS Tiempo de respuesta: 5 minutos
Ejemplos:
- Sistema caído (>50% de errores)
- Pico de costo >5x el diario (posible brecha o ciclo infinito)
- Alerta de seguridad (patrón de acceso inusual, sospecha de clave filtrada)
- Caída reportada por clientes y confirmada por las métricas
- Incumplimiento crítico del SLA
Herramientas:
- PagerDuty (https://www.pagerduty.com/): el estándar de la industria, de pago (precios en su sitio)
- Grafana Cloud IRM (https://grafana.com/docs/grafana-cloud/alerting-and-irm/irm/): la continuación de Grafana OnCall; la versión de código abierto de OnCall se congeló y en marzo de 2026 se archivó. Si trabajas solo, al principio te bastan los avisos de Slack y una llamada a tu celular
4 herramientas de observabilidad en 2026: comparación
| Herramienta | Plan gratuito | Mejor para |
|---|---|---|
| LangSmith | Sí; límites en su sitio | Trazas avanzadas, comparar prompts |
| Helicone | Sí; desde marzo de 2026 el servicio está en modo mantenimiento (lo compró Mintlify), sin funciones nuevas | Específico de LLM, seguimiento de costos, configuración rápida |
| Sentry | Sí; límites en su sitio | Seguimiento de errores, no específico de LLM |
| PostHog | Sí, un límite mensual (tamaño vigente en su página de precios) | Analítica de usuarios, no trazas |
Los precios de los planes de pago de las cuatro cambian: revísalos en sus sitios.
Recomendación por etapa:
- Personal / inicial (<1K usuarios): el plan gratuito de LangSmith o PostHog más Anthropic Console: alcanza para los primeros meses
- Equipo (1K-10K usuarios): LangSmith + Sentry
- Producción (con ingresos): LangSmith + Sentry + PostHog + una herramienta de guardias (PagerDuty o similar)
- Enterprise: Datadog (https://www.datadoghq.com/) + tableros propios
Además:
- El estándar OpenTelemetry (https://opentelemetry.io/): si quieres un enfoque independiente del proveedor
- Anthropic Console (https://platform.claude.com): integrado, mínimo, pero gratis
Patrón de implementación: un proxy, con Helicone como ejemplo
Una de las formas más rápidas de tener observabilidad es envolver el SDK de Anthropic con un proxy, por ejemplo Helicone. Se configura en 5 minutos.
⚠️ A octubre de 2026, Helicone está en modo mantenimiento (ver arriba), así que tómalo como ejemplo del enfoque: un proxy entre tu código y la API, más etiquetas en los encabezados. Para un proyecto nuevo, compáralo con LangSmith (lección MLOps para indie) y con gateways como el AI Gateway de Cloudflare. Revisa la dirección del proxy y los nombres de los encabezados en la documentación del servicio que elijas.
Antes (sin observabilidad):
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hola"}]
)Después (envuelto con Helicone):
from anthropic import Anthropic
import os
client = Anthropic(
base_url="https://anthropic.helicone.ai", # Proxy a través de Helicone
default_headers={
"Helicone-Auth": f"Bearer {os.getenv('HELICONE_KEY')}",
"Helicone-User-Id": user_id, # Seguimiento por usuario
"Helicone-Property-Feature": "chat-bot", # Desglose por función
"Helicone-Property-Environment": "production", # Etiqueta de entorno
"Helicone-Cache-Enabled": "true", # Extra: caché
"Helicone-Property-Tier": user_tier # Dimensión propia
}
)
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hola"}]
)
# Ahora en el tablero ves: latencia, costo, tokens, usuario, función, entornoQué aparece en el tablero de inmediato:
- Cada solicitud con su trace ID
- Costo por solicitud con desglose
- Latencia p50/p95/p99
- Los usuarios que más gastan
- Las funciones más usadas
- Cache hit ratio
Estructura del tablero: qué debe haber en la pantalla principal
Un buen tablero de producción lo miras una vez al día, 30 segundos, y entiendes todo.
┌──────────────────────────────────────────────────────────┐
│ My App Production Dashboard [Last 24h ▼] │
├──────────────────────────────────────────────────────────┤
│ │
│ 📊 LAST 24H OVERVIEW │
│ ┌─────────┬─────────┬─────────┬─────────┐ │
│ │ 1,247 │ $12.40 │ 0.3% │ 4.2s │ │
│ │ requests│ spend │ errors │ p95 │ │
│ └─────────┴─────────┴─────────┴─────────┘ │
│ │
│ 📈 TREND (7 days) │
│ Cost: ▁▂▃▃▄▅▆ +12% wow │
│ Errors: ▁▁▂▁▁▁▁ stable │
│ p95: ▃▃▃▃▃▃▃ stable │
│ │
│ 🚨 ACTIVE ALERTS │
│ • [WARN] Cache hit ratio 24% (target >30%) │
│ │
│ 🐢 TOP ISSUES │
│ 1. Slowest endpoint: /api/research (p95 = 18s) │
│ 2. Most errors: tool_timeout (43 events) │
│ 3. Biggest spender: user_42 ($3.20 today, 25% of total) │
│ │
│ 😊 USER SATISFACTION │
│ CSAT: 4.3 / 5.0 (n=87) │
│ Escalation rate: 12% │
│ │
└──────────────────────────────────────────────────────────┘Reglas de un buen tablero:
- Los números principales arriba, en una sola pantalla, sin scroll
- Tendencias visuales (sparklines), no tablas
- Las alertas activas se ven de inmediato, en rojo
- Los problemas principales te dicen dónde escarbar
- La métrica de negocio (CSAT) al mismo nivel que las técnicas
Flujo de depuración: de la queja a la corrección
Escenario: un usuario escribe "la IA respondió mal a las 14:30"
Paso 1: Localizar: encuentra en los logs las trazas alrededor de las 14:30 para ese usuario
# En el tablero de trazas: filtro user_id = user_42, hora 14:25 — 14:35
Paso 2: Reproducir: cuál fue la entrada, cuál el contexto, cuál la salida
- Toma el prompt exacto de la traza
- Ejecútalo en el playground de Anthropic Console con los mismos parámetros
- Obtén el mismo resultado (o uno distinto)
Paso 3: Correlacionar: con las métricas del sistema en ese momento
- ¿Hubo un pico de latencia? (lento = menos tiempo para pensar)
- ¿Hubo un pico de errores en la API? (servicio degradado)
- ¿Hubo un pico de costo? (un ciclo infinito en ese periodo)
- ¿Hubo un fallo de caché? (caché fría → comportamiento distinto)
Paso 4: Plantear la causa: opciones:
- ¿Desbordamiento de contexto (>180K tokens)? → estrategia de compactación
- ¿Datos malos (entrada corrupta)? → validación de entradas
- ¿Un error en el sistema (race condition)? → prueba unitaria
- ¿Degradación del LLM (actualización del modelo)? → revisar con la suite de evals
- ¿Deriva del prompt (algo cambió)? → control de versiones de los prompts
Paso 5: Corregir + prevenir
- La corrección mínima
- Agrega un caso de prueba a la suite de evals (ver la lección Evals: skills que se mejoran solos)
- Agrega una regla de alerta si es un patrón que se repite
- Documéntalo en el runbook
Buenas prácticas de registro
✅ Qué registrar:
- Todas las solicitudes/respuestas del LLM (entrada, salida, tokens, latencia, costo)
- Todas las llamadas a herramientas (nombre, argumentos, resultado, duración)
- Todos los errores con el stack trace completo
- Las acciones del usuario (sin datos personales: seudonimiza)
- Los eventos del sistema (despliegue, cambio de configuración, reinicio)
❌ Qué NO registrar:
- Contraseñas / claves de API en texto plano
- Datos personales completos (emails → hash, nombre → "User_42")
- Números de tarjeta
- Datos de salud con su contenido completo
- IP internas / rutas del sistema (seguridad)
Estrategia de muestreo:
- 100% de los errores (siempre)
- 5-10% de las trazas normales (equilibrio de costo)
- 100% de las solicitudes lentas (>2x el p95)
- 100% de las solicitudes caras (>$0.50)
Política de conservación:
| Tipo de log | Guardar |
|---|---|
| Errores | 90 días |
| Trazas normales | 30 días |
| Trazas muestreadas (para tendencias) | 1 año |
| Logs de auditoría (cumplimiento) | 7 años (ejemplo: el plazo depende del país y la industria; confírmalo con un abogado) |
Registro estructurado: obligatoriamente en JSON:
import json
import time
def log_llm_call(request, response, duration_ms):
log_entry = {
"ts": time.time(),
"level": "INFO",
"event": "llm_call",
"trace_id": request.headers.get("X-Trace-ID"),
"user_id_hash": hash_user_id(request.user_id),
"model": response.model,
"tokens_input": response.usage.input_tokens,
"tokens_output": response.usage.output_tokens,
"cache_read_tokens": response.usage.cache_read_input_tokens or 0,
"duration_ms": duration_ms,
"cost_usd": calculate_cost(response.usage, response.model),
"feature": request.feature_tag,
"success": True
}
print(json.dumps(log_entry)) # → stdout → agregador de logsAntipatrones (qué no hacer)
❌ Agregar el registro "después": normalmente cuando algo ya se rompió. Para entonces no hay datos para depurar el incidente de ayer.
❌ Una alerta por cada error: ruido, fatiga de alertas. En una semana el equipo silencia el canal. Filtra por gravedad y frecuencia.
❌ Solo seguir errores, sin seguir costos: despiertas con una cuenta sorpresa de $5000. Al principio, monitorear costos es más crítico que monitorear errores.
❌ Registrar sin user_id: imposible depurar los reportes de usuarios. "A mí no me funciona" → no puedes encontrar su traza.
❌ "Yo todo lo tengo en console.log": no es persistente, no se puede buscar, no se correlaciona. Los logs deben ir a un agregador (Helicone / Datadog / uno propio).
❌ Muestrear siempre al 100%: pagas por guardarlo todo. Muestrea con criterio: errores al 100%, normales al 5%.
❌ Alertas sin runbook: se disparó la alerta y quien está de guardia no sabe qué hacer. Cada alerta crítica debe enlazar a un runbook.
❌ Un tablero que nadie mira: si lo abres una vez al mes, te enteras de los problemas con un mes de retraso. El ritual diario importa.
Cuánto cuesta la observabilidad
La pregunta más frecuente es "¿y cuánto cuesta?". La respuesta honesta:
| Categoría | Costo |
|---|---|
| Herramientas (inicial) | Muchas veces bastan los planes gratuitos (LangSmith, Sentry, PostHog) |
| Herramientas (producción) | Planes de pago de varios servicios: calcúlalo con sus precios actuales |
| Tiempo de configuración (inicial) | 4-8 horas |
| Mantenimiento | 1-2 horas al mes (actualizar alertas, ajustar umbrales) |
| Almacenamiento (si es autoalojado) | Depende del volumen de logs y del plan de almacenamiento (S3, R2) |
Cálculo de retorno: un solo pico de costo que se te escape (por ejemplo, un ciclo infinito de llamadas) puede costar más que todas las herramientas de observación de un año. Una caída que afecta a clientes y que no detectas suele costar todavía más.
Recomendaciones según tu madurez
Principiante (sin ingresos, aprendiendo):
- Solo Anthropic Console (integrado) + revisiones manuales semanales
- Sin herramientas extra
- Logs en la consola / en un archivo
- Meta: entender qué está pasando
Intermedio (primeros usuarios, plan gratuito):
- Plan gratuito de LangSmith o PostHog
- Webhook de Slack para las alertas críticas
- Revisión semanal del tablero
- Meta: atrapar los problemas antes que los usuarios
Profesional (producción con ingresos):
- LangSmith (plan de pago) + Sentry + PostHog
- PagerDuty o similar para las alertas críticas
- Tableros propios con métricas de negocio
- Ritual de revisión diaria
- Meta: cumplir los SLA, optimizar de forma proactiva
Enterprise (escala, cumplimiento):
- Datadog o New Relic de stack completo
- Pipeline propio de OpenTelemetry
- Observabilidad multirregión
- Meta: no enterarte nunca de un problema por un cliente
Revisión trimestral de la observabilidad
Una vez por trimestre, dedica 2 horas a revisar tu sistema de observabilidad.
Qué agregar:
- Endpoints / funciones nuevas → métricas nuevas
- SLO nuevos de clientes → alertas nuevas
- Aparecieron tipos de error nuevos → categorizarlos y seguirlos
Qué quitar:
- Tableros sin uso (nadie los vio en 90 días)
- Alertas con falsos positivos (se disparan, pero no es crítico)
- Métricas que nunca se usaron para decidir nada
Qué optimizar:
- Las alertas más ruidosas → ajustar umbrales
- Oportunidades para revertir la tendencia de costos (dónde se puede ahorrar)
- Consultas / endpoints lentos
Qué rotar:
- Claves de acceso (tokens de API de las herramientas de observabilidad)
- Lista de subencargados (cumplimiento)
- URL de los runbooks (si algo se movió)
Práctica
Paso 1: configura Helicone (5 minutos)
Aquí Helicone es un ejemplo del enfoque con proxy: desde marzo de 2026 está en modo mantenimiento. Si no quieres atarte a un servicio así, cambia este paso por la integración de LangSmith de la lección MLOps para indie.
# 1. Regístrate en helicone.ai (tiene plan gratuito)
# 2. Obtén la clave de API en el tablero
# 3. Guárdala en .env
echo "HELICONE_API_KEY=sk-helicone-xxx" >> .env
echo "ANTHROPIC_API_KEY=sk-ant-xxx" >> .env# helicone_setup.py — integración mínima
import os
from dotenv import load_dotenv
from anthropic import Anthropic
load_dotenv()
# Cliente a través del proxy de Helicone
client = Anthropic(
api_key=os.getenv("ANTHROPIC_API_KEY"),
base_url="https://anthropic.helicone.ai",
default_headers={
"Helicone-Auth": f"Bearer {os.getenv('HELICONE_API_KEY')}",
"Helicone-Property-Environment": "production",
"Helicone-Property-App": "my-agent"
}
)
# Solicitud de prueba
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=100,
messages=[{"role": "user", "content": "Saluda"}],
extra_headers={
"Helicone-User-Id": "test_user_001",
"Helicone-Property-Feature": "greeting"
}
)
print("".join(b.text for b in response.content if b.type == "text"))
print(f"\nRevisa el tablero: https://www.helicone.ai/dashboard")
print(f"Costo: se ve en tiempo real")Paso 2: configura las alertas de Slack (15 minutos)
# alerts.py — alertas de tres niveles
import os
import requests
from enum import Enum
class AlertLevel(Enum):
INFO = "good" # verde
WARNING = "warning" # amarillo
CRITICAL = "danger" # rojo
def send_alert(level: AlertLevel, title: str, message: str, dashboard_url: str = None):
"""Envía una alerta a Slack según su nivel de gravedad."""
webhook_map = {
AlertLevel.INFO: os.getenv("SLACK_INFO_WEBHOOK"),
AlertLevel.WARNING: os.getenv("SLACK_WARNING_WEBHOOK"),
AlertLevel.CRITICAL: os.getenv("SLACK_CRITICAL_WEBHOOK"),
}
webhook = webhook_map[level]
mention = "@here" if level == AlertLevel.WARNING else ("@channel" if level == AlertLevel.CRITICAL else "")
payload = {
"text": f"{mention} *{title}*",
"attachments": [{
"color": level.value,
"text": message,
"fields": [
{"title": "Severity", "value": level.name, "short": True},
{"title": "Dashboard", "value": dashboard_url or "N/A", "short": True}
]
}]
}
response = requests.post(webhook, json=payload)
response.raise_for_status()
# Ejemplos de uso
send_alert(
AlertLevel.INFO,
"Daily Summary",
"Ayer: 1247 solicitudes, $12.40 de gasto, 0.3% de errores"
)
send_alert(
AlertLevel.WARNING,
"Cost spike detected",
"Hoy ya van $40 (2x los $20 de ayer). Revisa los logs de la última hora.",
"https://enlace-a-tu-tablero"
)
send_alert(
AlertLevel.CRITICAL,
"System degradation",
"Tasa de errores del 12% en los últimos 5 minutos. Latencia p99 de 30s.",
"https://enlace-a-tu-tablero"
)Paso 3: un proceso que vigila los costos
# cost_monitor.py — revisión de anomalías de costo
import os
import time
from datetime import datetime, timedelta
from anthropic import Anthropic
# Supongamos que tienes una función get_daily_cost() que lee de la API de tu servicio de trazas
def get_daily_cost(date):
"""Regresa los $ gastados en el día. Es un marcador: conecta la API de tu servicio de trazas."""
# Implementación real: una consulta a la API del servicio de trazas para esa fecha
return 12.40 # placeholder
def get_baseline(days_back=7):
"""Costo promedio de los últimos N días."""
costs = []
for i in range(1, days_back + 1):
date = datetime.now() - timedelta(days=i)
costs.append(get_daily_cost(date))
return sum(costs) / len(costs)
def check_cost_anomaly():
today_cost = get_daily_cost(datetime.now())
baseline = get_baseline(days_back=7)
ratio = today_cost / baseline if baseline > 0 else 0
if ratio > 5.0:
send_alert(
AlertLevel.CRITICAL,
"🚨 Cost spike >5x baseline",
f"Today: ${today_cost:.2f}, baseline: ${baseline:.2f} ({ratio:.1f}x)"
)
elif ratio > 2.0:
send_alert(
AlertLevel.WARNING,
"⚠️ Cost spike 2x baseline",
f"Today: ${today_cost:.2f}, baseline: ${baseline:.2f} ({ratio:.1f}x)"
)
# Se ejecuta con cron cada hora
if __name__ == "__main__":
check_cost_anomaly()# crontab -e
# Revisar anomalías de costo cada hora
0 * * * * cd /path/to/project && python cost_monitor.py
# Resumen diario a las 09:00
0 9 * * * cd /path/to/project && python daily_summary.pyPaso 4: registro estructurado
# structured_logging.py — logs en JSON listos para agregarse
import json
import time
import hashlib
from contextlib import contextmanager
def hash_user_id(user_id: str) -> str:
"""Seudonimiza el user_id para los logs."""
return hashlib.sha256(user_id.encode()).hexdigest()[:16]
@contextmanager
def trace_llm_call(user_id: str, feature: str, model: str):
"""Context manager que registra la llamada al LLM en JSON estructurado."""
trace_id = f"trace_{int(time.time()*1000)}"
start = time.time()
log_data = {
"ts": time.time(),
"trace_id": trace_id,
"user_id_hash": hash_user_id(user_id),
"feature": feature,
"model": model,
}
try:
yield log_data
log_data["success"] = True
except Exception as e:
log_data["success"] = False
log_data["error"] = str(e)
log_data["error_type"] = type(e).__name__
raise
finally:
log_data["duration_ms"] = int((time.time() - start) * 1000)
print(json.dumps(log_data)) # → stdout → agregador de logs
# Uso
with trace_llm_call(user_id="user_42", feature="chat", model="claude-sonnet-5-5") as log:
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hola"}]
)
log["tokens_input"] = response.usage.input_tokens
log["tokens_output"] = response.usage.output_tokens
# Precios por millón de tokens a octubre de 2026 (Sonnet 5.5); vigentes: ../actual.html
PRICE_IN, PRICE_OUT = 2.0, 10.0
log["cost_usd"] = response.usage.input_tokens * PRICE_IN / 1_000_000 + \
response.usage.output_tokens * PRICE_OUT / 1_000_000Paso 5: crear tu propio tablero (opcional)
# simple_dashboard.py — un tablero HTML mínimo
from flask import Flask, render_template_string
import time
flask_app = Flask(__name__)
DASHBOARD_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>AI Agent Dashboard</title>
<meta http-equiv="refresh" content="60">
<style>
body { font-family: monospace; background: #1a1a1a; color: #00ff00; padding: 20px; }
.metric { display: inline-block; padding: 20px; border: 1px solid #00ff00; margin: 10px; }
.big { font-size: 32px; }
.alert { color: #ff0000; }
.warn { color: #ffaa00; }
.ok { color: #00ff00; }
</style>
</head>
<body>
<h1>📊 AI Agent Production Dashboard</h1>
<p>Last refresh: {{ ts }}</p>
<div>
<div class="metric">
<div>Requests (24h)</div>
<div class="big">{{ requests }}</div>
</div>
<div class="metric">
<div>Cost (24h)</div>
<div class="big ok">${{ cost }}</div>
</div>
<div class="metric">
<div>Error rate</div>
<div class="big {{ 'alert' if error_rate > 5 else 'warn' if error_rate > 1 else 'ok' }}">{{ error_rate }}%</div>
</div>
<div class="metric">
<div>p95 latency</div>
<div class="big">{{ p95 }}s</div>
</div>
</div>
{% if alerts %}
<h2>🚨 Active alerts</h2>
<ul>{% for a in alerts %}<li class="warn">{{ a }}</li>{% endfor %}</ul>
{% endif %}
</body>
</html>
"""
# Registramos la ruta con add_url_rule para que el tablero muestre los datos
def render_dashboard():
# Pon aquí los datos reales de la API de Helicone / de tu base de datos
return render_template_string(
DASHBOARD_TEMPLATE,
ts=time.strftime("%Y-%m-%d %H:%M:%S"),
requests=1247,
cost="12.40",
error_rate=0.3,
p95=4.2,
alerts=["Cache hit ratio 24% (target >30%)"]
)
flask_app.add_url_rule("/", "dashboard", render_dashboard)
if __name__ == "__main__":
flask_app.run(port=8080)# Abres http://localhost:8080 y ves el tablero
python simple_dashboard.pyChecklist de preparación para producción (✅)
Antes de dejar que usuarios reales usen tu agente:
Si tienes menos de 7 marcas, no estás listo para producción. Termínalo.
Herramientas y recursos
- LangSmith: observabilidad de LangChain, trazas avanzadas; tiene plan gratuito
- Helicone: proxy de LLM con métricas (a octubre de 2026, en modo mantenimiento)
- Sentry: seguimiento de errores, de uso general
- PostHog: analítica de producto, métricas de negocio
- PagerDuty: alertas de guardia, el estándar de la industria
- Datadog: observabilidad enterprise de stack completo
- Grafana Cloud IRM: guardias e incidentes (la versión de código abierto de OnCall se archivó en marzo de 2026)
- Anthropic Console: seguimiento de uso integrado
- OpenTelemetry: estándar de observabilidad independiente del proveedor
Conclusiones clave
La observabilidad no es "para después, cuando crezcamos". Es la condición para poder trabajar en producción. Un solo pico de costo que se te escape puede costar más que la suscripción anual a un servicio de monitoreo. Pon algo, lo que sea: hasta un simple webhook de Slack es mejor que "me entero por los clientes".
Las 5 métricas obligatorias: latencia (¡el p95!), costo (detección de picos), tasa de errores (categorizada), uso de tokens (cache ratio) y negocio (conversaciones completadas). Sin cualquiera de las cinco hay un punto ciego que te va a morder.
Los 3 niveles de alertas te salvan de la fatiga de alertas. Info: resumen diario. Warning: mención en Slack. Critical: avisar a quien está de guardia. Si cada error despierta a alguien en la noche, en una semana el equipo silencia el canal y se le pasa el incidente de verdad.
El flujo de depuración siempre es el mismo: localizar la traza → reproducir → correlacionar con las métricas → plantear la causa → corregir + agregar una prueba a los evals. Sin observabilidad, adivinas. Con ella, diagnosticas.
Siguiente lección
→ La arquitectura final: el stack completo de IA de un negocio
Para saber qué hacer cuando todo se rompió, ve la lección Backup & Disaster Recovery para el stack de IA.
La marca se guarda solo en este navegador y no se envía a ningún sitio. Mi progreso