Alerting de fallos de agentes

Las alertas notifican a los equipos sobre fallos en sistemas de agentes.
En esta página
  1. Idea en 30 segundos
  2. Problema principal
  3. Cómo funciona
  4. Métricas típicas de producción para alerting
  5. Cómo leer el alert-layer
  6. Cuándo usarlo
  7. Ejemplo de implementación
  8. Investigación
  9. Errores típicos
  10. Demasiadas alertas sin priorización
  11. Sin cooldown ni deduplicación
  12. Sin alertas basadas en synthetic runs
  13. Alertas no vinculadas a playbook
  14. Labels de alta cardinalidad en alert metrics
  15. Autoevaluación
  16. FAQ
  17. Páginas relacionadas

Idea en 30 segundos

El failure alerting para agentes de IA da una señal temprana cuando el sistema entra en degradación.

Su objetivo no es solo "notificar un error", sino mostrar a tiempo qué se está rompiendo: tools, pasos de LLM, latencia o health checks.

Sin alertas, el equipo suele enterarse de los problemas por los usuarios, no por el sistema.

Problema principal

Los logs y el tracing explican bien un incidente después de que ocurre.

Pero sin alertas es difícil detectar el momento en que el problema recién empieza: sube el timeout rate, baja el synthetic success y crece la p95 latency. Por eso es fácil perder la transición de una degradación local a un fallo en cascada.

Ahora veamos cómo construir alertas para que sean útiles y no ruidosas.

En producción, esto suele verse así:

  • la señal llega demasiado tarde, cuando el SLO ya fue violado;
  • las alertas meten ruido por picos temporales y se empiezan a ignorar;
  • un problema genera decenas de duplicados en distintos canales;
  • no hay una ruta clara: quién debe reaccionar y qué hacer primero.

Por eso, el alert-layer debe diseñarse como una parte separada de observability, no como un "webhook extra".

Cómo funciona

El failure alerting normalmente tiene tres niveles:

  • señales (error_rate, timeout_rate, latency_p95, health_score);
  • reglas (threshold, window, severity, cooldown);
  • enrutamiento (on-call, team, playbook, escalation).

Estos niveles responden: cuándo reaccionar, quién reacciona y cómo actuar. Logs y tracing son necesarios para pasar rápido de la alerta a la root cause. En producción, una alerta normalmente incluye no solo severity, sino también owner/team o playbook_link. Las alert rules deben reflejar violaciones de SLO, no thresholds arbitrarios.

Alert noise != reliability. Si las alertas disparan con frecuencia y sin prioridad, el equipo empieza a ignorarlas.

Las alertas aparecen donde la degradación ya es visible en métricas, latencia o health checks. Las synthetic alerts muestran que el sistema "está vivo", pero el usuario ya no puede completar la tarea.

Métricas típicas de producción para alerting

MétricaQué muestraPara qué sirve
alert_fire_ratecon qué frecuencia disparan las alertascontrol de ruido y estabilidad de reglas
alert_dedup_rateproporción de duplicados fusionadosreducir el spam de alertas
mttamean time to acknowledgevelocidad de respuesta de on-call
mttrmean time to resolvevelocidad de recuperación
false_positive_rateproporción de alertas falsasmejora de la calidad de reglas
missed_incident_ratecuántos incidentes pasaron sin alertacontrol de cobertura de riesgos
escalation_rateproporción de alertas escaladascontrol de fallos graves

mtta y mttr normalmente se calculan en la plataforma de incidentes (PagerDuty/Opsgenie/incident log propio), no directamente en el runtime del agente.

Para que las alertas sean útiles, normalmente se segmentan por severity, workflow, release y component.

Importante: no agregues campos de alta cardinalidad (run_id, request_id, user_id) a labels, o las alert metrics se vuelven inmanejables rápidamente.

Cómo leer el alert-layer

Qué disparó -> por qué disparó -> quién debe hacer qué. Estos tres niveles siempre deben leerse juntos.

Lo importante es mirar tendencias y correlación de señales, no una alerta aislada.

Combinaciones de señales típicas:

  • timeout_rate sube + latency_p95 sube -> la degradación del servicio ya impacta a usuarios;
  • health_score baja + synthetic_run_success_rate baja -> un workflow crítico deja de funcionar end-to-end;
  • tool_error_rate sube + alert_fire_rate sube -> un tool inestable crea una cascada de alertas;
  • false_positive_rate sube + mtta sube -> el equipo pierde confianza en las alertas;
  • missed_incident_rate sube + error_rate sube -> hay huecos en las reglas de alerting.

Cuándo usarlo

El failure alerting completo no siempre es necesario.

Para un prototipo simple, puede bastar una alerta básica de caída del servicio.

Pero el alerting a nivel de sistema se vuelve crítico cuando:

  • el sistema de agentes ya está en producción;
  • hay SLO/SLA de disponibilidad, latencia o éxito de workflow;
  • el sistema depende de múltiples tools y APIs externas;
  • se necesita reacción on-call sin monitoreo manual de dashboards.

Ejemplo de implementación

Debajo hay un loop simplificado de alert evaluator. El ejemplo muestra el enfoque base: threshold + window + cooldown + deduplicación de eventos.

PYTHON
import time
from collections import defaultdict, deque

ALERT_RULES = {
    "high_timeout_rate": {
        "threshold": 0.05,
        "window_sec": 300,
        "severity": "high",
        "cooldown_sec": 600,
    },
    "latency_p95_regression": {
        "threshold": 2500,  # ms
        "window_sec": 300,
        "severity": "medium",
        "cooldown_sec": 600,
    },
    "synthetic_run_failed": {
        "threshold": 1,
        "window_sec": 120,
        "severity": "critical",
        "cooldown_sec": 300,
    },
}


class AlertEngine:
    def __init__(self):
        self.series = defaultdict(deque)  # metric_name -> [(ts, value), ...]
        self.last_fired_at = {}  # rule_name -> ts

    def ingest(self, metric_name, value, ts=None):
        ts = ts or time.time()
        self.series[metric_name].append((ts, value))

    def evaluate(self, ts=None):
        ts = ts or time.time()
        fired = []

        for rule_name, rule in ALERT_RULES.items():
            if self._in_cooldown(rule_name, ts, rule["cooldown_sec"]):
                continue

            if rule_name == "high_timeout_rate":
                value = self._latest_in_window("timeout_rate", ts, rule["window_sec"])
                if value is not None and value >= rule["threshold"]:
                    fired.append(self._build_alert(rule_name, value, rule, ts))

            if rule_name == "latency_p95_regression":
                value = self._latest_in_window("run_latency_p95_ms", ts, rule["window_sec"])
                if value is not None and value >= rule["threshold"]:
                    fired.append(self._build_alert(rule_name, value, rule, ts))

            if rule_name == "synthetic_run_failed":
                value = self._latest_in_window("synthetic_run_failed", ts, rule["window_sec"])
                if value is not None and value >= rule["threshold"]:
                    fired.append(self._build_alert(rule_name, value, rule, ts))

        return fired

    def _latest_in_window(self, metric_name, now_ts, window_sec):
        # NOTA:
        # Este ejemplo revisa solo el ultimo punto (los picos pueden disparar alertas).
        # En produccion (Prometheus/Datadog), normalmente se exige
        # que la anomalia se mantenga durante cierto tiempo (por ejemplo, "for: 5m"),
        # para evitar alertas por picos cortos.
        # Alternativa: revisar breach sostenido durante toda la ventana,
        # no solo en el ultimo punto.
        points = self.series[metric_name]
        while points and now_ts - points[0][0] > window_sec:
            points.popleft()
        return points[-1][1] if points else None

    def _sustained_breach(self, metric_name, now_ts, window_sec, threshold):
        points = self.series[metric_name]
        while points and now_ts - points[0][0] > window_sec:
            points.popleft()
        return points and all(v >= threshold for _, v in points)

    def _in_cooldown(self, rule_name, now_ts, cooldown_sec):
        last_ts = self.last_fired_at.get(rule_name)
        return last_ts is not None and now_ts - last_ts < cooldown_sec

    def _build_alert(self, rule_name, value, rule, now_ts):
        self.last_fired_at[rule_name] = now_ts
        return {
            "rule": rule_name,
            "severity": rule["severity"],
            "value": value,
            "timestamp": now_ts,
        }

En producción, las alertas normalmente no deben disparar por un solo pico, sino cuando el umbral se mantiene durante toda la ventana.

Así pueden verse las alert metrics en un dashboard real:

Rulefire_ratefalse_positivemttaEstado
high_timeout_rate12/day18%4mwarning: noisy
synthetic_run_failed3/day3%2mok
latency_p95_regression9/day11%6mcritical: SLO risk

Investigación

Cuando se dispara una alerta:

  1. revisar la severity y si no es un duplicado en la ventana de cooldown;
  2. encontrar señales correlacionadas en métricas (latency, timeout, health);
  3. abrir los runs problemáticos en tracing;
  4. confirmar la root cause en logs y ejecutar el playbook.

Errores típicos

Incluso con alertas implementadas, a menudo no funcionan bien por errores comunes.

Demasiadas alertas sin priorización

Si todas las alertas son igual de críticas, el equipo pierde confianza rápidamente.

Sin cooldown ni deduplicación

Un solo problema genera decenas de notificaciones idénticas y complica la reacción on-call.

Sin alertas basadas en synthetic runs

Las alertas solo de infraestructura no garantizan que el workflow realmente funcione. Por eso se puede perder el caos multiagente en fases tempranas.

Alertas no vinculadas a playbook

Las notificaciones existen, pero el equipo no sabe qué hacer después. Esto aumenta el MTTR durante un incidente.

Labels de alta cardinalidad en alert metrics

Agregar run_id o request_id en labels sobrecarga rápidamente el sistema de métricas y complica el análisis.

Autoevaluación

Checklist corta de failure alerting baseline antes de release.

Progreso: 0/9

⚠ Falta observability base

Será difícil depurar el sistema en production. Empieza con run_id, structured logs y tracing de tool calls.

FAQ

Q: ¿En qué se diferencia failure alerting de health checks?
A: Los health checks muestran el estado actual del sistema, mientras que el failure alerting define cuándo y a quién notificar para reaccionar a tiempo.

Q: ¿Cuál es el mínimo de alertas para empezar?
A: Empieza con timeout_rate, error_rate, latency_p95 y synthetic_run_success_rate.

Q: ¿Cómo reducir el ruido de alertas?
A: Agrega niveles de severity, cooldown, deduplicación y elimina reglas con false positives frecuentes.

Q: ¿Cómo saber si las alertas cubren riesgos reales?
A: Revisa missed_incident_rate después de incidentes y actualiza reglas donde el sistema se degradó sin notificación.

Páginas relacionadas

Siguiente en este tema:

⏱️ 8 min de lecturaActualizado 22 de marzo de 2026Dificultad: ★★★
Integrado: control en producciónOnceOnly
Guardrails para agentes con tool-calling
Lleva este patrón a producción con gobernanza:
  • Presupuestos (pasos / topes de gasto)
  • Permisos de herramientas (allowlist / blocklist)
  • Kill switch y parada por incidente
  • Idempotencia y dedupe
  • Audit logs y trazabilidad
Mención integrada: OnceOnly es una capa de control para sistemas de agentes en producción.

Autor

Nick — ingeniero que construye infraestructura para agentes de IA en producción.

Enfoque: patrones de agentes, modos de fallo, control del runtime y fiabilidad del sistema.

🔗 GitHub: https://github.com/mykolademyanov


Nota editorial

Esta documentación está asistida por IA, con responsabilidad editorial humana sobre la exactitud, la claridad y la relevancia en producción.

El contenido se basa en fallos reales, post-mortems e incidentes operativos en sistemas de agentes de IA desplegados.