Idea en 30 segundos
Health checks para agentes de IA muestran si el sistema realmente esta listo para trafico justo ahora.
Ayudan a detectar degradacion antes del incidente: tools lentas, timeouts, problemas de queue o fallos en capa LLM.
Sin health checks, muchas veces solo se ve el fallo final, no las senales tempranas previas.
Problema principal
El sistema puede estar formalmente "up", pero en la practica ya inestable.
API responde, runs inician, pero algunas etapas ya se degradan: sube timeout rate, baja success rate, crece queue time. Sin health checks, esto suele verse solo tras fallo en cascada.
Ahora veamos como leer estas senales y encontrar que componente entra primero en degradacion.
En production esto suele verse asi:
- desde fuera todo "funciona", pero p95 latency ya sale del SLO;
- una tool devuelve timeout con mayor frecuencia, pero la causa aun no es clara;
- synthetic run empieza a fallar antes que el trafico principal;
- el equipo reacciona solo tras caida parcial.
Por eso la health-layer conviene monitorearla por separado, no solo con metricas generales de run.
Como funciona
Health checks normalmente se construyen en dos niveles:
- component checks (
tool_available,llm_reachable,queue_ok,db_ok); - end-to-end checks (
synthetic_run_ok,critical_workflow_ok).
Estas senales responden "el sistema esta sano justo ahora". Logs y tracing son necesarios para explicar por que cayo una verificacion concreta.
Un proceso accesible no garantiza que el workflow esté listo. Los health checks pueden detectar un fallo antes que los usuarios, según su frecuencia y los escenarios cubiertos. No garantizan detectarlo antes que las métricas de errores o latencia.
Liveness, readiness y pruebas sintéticas responden preguntas distintas
- Liveness: ¿debe reiniciarse el proceso?
- Readiness: ¿puede aceptar tareas nuevas?
- Prueba sintética: ¿funciona un escenario de extremo a extremo?
Kubernetes documenta las probes de liveness, readiness y startup.
Un agente de soporte puede funcionar en modo limitado si falla una búsqueda opcional. Si no está disponible el almacén de políticas necesario para autorizar acciones, debe rechazar las nuevas tareas afectadas. Un fallo crítico pesa más que nueve comprobaciones opcionales correctas: el promedio health_score no debe autorizar tráfico por sí solo.
No llames a un LLM externo en cada probe de liveness. Añade costes y una caída del proveedor puede causar reinicios inútiles en todas las réplicas. Recoge los resultados de dependencias por separado con timeouts; readiness lee una instantánea reciente. Las pruebas sintéticas necesitan datos propios, un presupuesto y herramientas sin efectos secundarios (cambios de estado) en producción.
Ejemplo ejecutable de readiness
Guarda el código como readiness_demo.py y ejecuta python3 readiness_demo.py con Python 3.10+. Prueba la lógica de admisión, no probes de red. Todos los tiempos usan el mismo reloj monotónico del proceso; 30 segundos es un ejemplo que debes ajustar al intervalo de comprobación.
from dataclasses import dataclass
@dataclass(frozen=True)
class Check:
ok: bool
observed_at: float
def ready(checks, required, now, max_age=30.0):
if not required or max_age <= 0:
return False
for name in required:
check = checks.get(name)
if check is None or not check.ok:
return False
if not 0 <= now - check.observed_at <= max_age:
return False
return True
required = ("queue", "policy_store")
checks = {
"queue": Check(True, 100.0),
"policy_store": Check(True, 100.0),
"optional_search": Check(False, 100.0),
}
assert ready(checks, required, now=110.0)
assert not ready(checks, required, now=131.0)
assert not ready({}, required, now=110.0)
checks["policy_store"] = Check(False, 100.0)
assert not ready(checks, required, now=110.0)
print("readiness cases: 4 passed")
Resultado esperado: readiness cases: 4 passed. Los casos cubren una dependencia opcional, resultados caducados, resultados ausentes y una dependencia crítica fallida. El colector real debe registrar los fallos y no actualizar la hora del último éxito tras un timeout. Las tareas ya iniciadas requieren una política separada de finalización o recuperación.
Tras una señal de fallo, continúa con la depuración del run afectado.
Metricas tipicas de production para health checks
| Metrica | Que muestra | Para que sirve |
|---|---|---|
| health_check_pass_rate | proporcion de health checks exitosos | evaluacion rapida de estado del sistema |
| health_check_latency_p95 | tiempo de ejecucion de verificaciones | senal temprana de degradacion de dependencias |
| tool_check_latency_p95 | latency de checks de tools concretas | localizar tool-layer lenta |
| synthetic_run_success_rate | exito de synthetic run | control de escenario real E2E |
| degraded_component_count | cuantos componentes estan degradados | estimar alcance del problema |
| timeout_rate | proporcion de timeout en checks y runs | disparador temprano de inestabilidad |
| queue_time_p95 | cuanto espera un run en queue | senal de falta de capacity |
| health_score | indice agregado de salud (0..1) | senal simple para alertas y status page |
health_score normalmente se calcula a nivel dashboard/health service como agregado de varios checks, no como una metrica "magica" unica.
Para que metrica de health sea util, normalmente se segmenta por release, region, workflow y tipo de componente.
Importante: no agregues campos de alta cardinalidad (run_id, request_id, user_id) en labels, o el storage de metricas se sobrecarga rapido.
Como leer la health-layer
Que se verifica -> que se degrada -> que componente rompe el workflow. Son tres niveles que siempre hay que mirar juntos.
Es clave mirar tendencias en el tiempo y diferencias entre releases, no una sola caida puntual de un check.
Ahora revisa combinaciones de senales:
health_check_pass_ratedown +timeout_rateup -> sistema entra en modo inestable;synthetic_run_success_ratedown +degraded_component_countup -> el problema ya impacta workflow critico;queue_time_p95up +run_countup -> falta capacity, hace falta escalar;health_scoredown +error_rateup -> riesgo alto de incidente a corto plazo;tool_check_latency_p95up +synthetic_run_success_ratedown -> bottleneck en tool-layer externa.
Cuando usar
Un set completo de health checks no siempre es necesario.
Para un prototipo temprano, puede bastar una verificacion basica de disponibilidad de API.
Pero health checks detalladas se vuelven criticas cuando:
- el sistema ya esta en production;
- hay SLO/SLA de estabilidad;
- el agente depende de varias tools externas o queues;
- se necesitan alertas tempranas antes de fallo masivo.
Ejemplo de implementacion
Abajo hay un ciclo simplificado de health checks estilo Prometheus. Muestra enfoque base: checks de componentes, synthetic run y health score agregado.
Es una base de instrumentación: instala prometheus-client y proporciona tus propias comprobaciones con timeouts. El promedio sirve para una vista general, no para decidir automáticamente la readiness.
import time
from dataclasses import dataclass
from prometheus_client import Counter, Gauge, Histogram
# perf_counter() se usa para mediciones monotonicas y precisas de latency
HEALTH_CHECK_TOTAL = Counter(
"agent_health_check_total",
"Total health checks by check name and status",
["check", "status", "release"],
)
HEALTH_CHECK_LATENCY_MS = Histogram(
"agent_health_check_latency_ms",
"Health check latency in milliseconds",
["check", "release"],
buckets=(10, 20, 50, 100, 250, 500, 1000, 2000),
)
SYNTHETIC_RUN_TOTAL = Counter(
"agent_synthetic_run_total",
"Total synthetic runs by status",
["status", "release"],
)
DEGRADED_COMPONENT_TOTAL = Counter(
"agent_degraded_component_total",
"Total degraded component detections",
["component", "reason", "release"],
)
HEALTH_SCORE = Gauge(
"agent_health_score",
"Aggregated health score in range 0..1",
["release"],
)
@dataclass
class CheckResult:
ok: bool
reason: str = "ok"
def run_health_checks(checks, run_synthetic, release="2026-03-22"):
total = len(checks)
failed = 0
for check_name, check_fn in checks.items():
started_at = time.perf_counter()
status = "error" # default for any failure path
try:
result = check_fn() # -> CheckResult
status = "ok" if result.ok else "fail"
if not result.ok:
failed += 1
DEGRADED_COMPONENT_TOTAL.labels(
component=check_name,
reason=result.reason,
release=release,
).inc()
except Exception as error:
failed += 1
DEGRADED_COMPONENT_TOTAL.labels(
component=check_name,
reason=type(error).__name__,
release=release,
).inc()
finally:
HEALTH_CHECK_TOTAL.labels(check=check_name, status=status, release=release).inc()
HEALTH_CHECK_LATENCY_MS.labels(check=check_name, release=release).observe(
(time.perf_counter() - started_at) * 1000
)
try:
synthetic_ok = run_synthetic()
SYNTHETIC_RUN_TOTAL.labels(
status="ok" if synthetic_ok else "fail",
release=release,
).inc()
if not synthetic_ok:
failed += 1
except Exception:
SYNTHETIC_RUN_TOTAL.labels(status="error", release=release).inc()
failed += 1
# 1.0 = todos los checks pasaron, 0.0 = todo fallo
# +1 por synthetic run
denominator = total + 1
health_score = max(0.0, 1.0 - (failed / max(1, denominator)))
HEALTH_SCORE.labels(release=release).set(health_score)
return health_score
Las siguientes métricas son valores ilustrativos, no mediciones de un sistema de producción:
| Segment | pass_rate | synthetic_success | health_score | Estado |
|---|---|---|---|---|
| core workflow | 98.7% | 99.1% | 0.97 | ok |
| research workflow | 93.2% | 89.4% | 0.82 | warning |
| tool-heavy workflow | 87.1% | 80.6% | 0.74 | critical: incident risk |
Investigation
Cuando dispara una alerta de health:
- encontrar check o workflow con degradacion;
- revisar runs problematicos en tracing;
- revisar en logs timeout, stop_reason y tool failures;
- encontrar root cause (tool, LLM, queue, routing, release regression).
Errores tipicos
Incluso cuando ya hay health checks, muchas veces no ayudan por errores tipicos.
Solo hay ping/check de disponibilidad del servicio
Disponibilidad de API no garantiza que workflow agente funcione realmente. Sin synthetic run, es facil perder degradacion oculta.
No hay checks de dependencias externas
Si tools, queues o BD no entran en health checks, el sistema puede verse "sano" hasta el primer incidente. En ese escenario, cuesta localizar rapido fallo de herramienta.
No hay desglose por workflow y release
Sin eso, cuesta entender que release o escenario empeoro el estado del sistema.
No hay alertas por degradacion de health score
Sin alertas, health checks se vuelven telemetria pasiva. Asi se pierden senales tempranas de caos multi-agente.
Labels de alta cardinalidad
Agregar run_id, request_id o session_id en labels sobrecarga rapido el backend de metricas.
Es mejor mantener esos datos en logs y tracing.
Autoevaluacion
Abajo tienes checklist corto de health checks base 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
P: En que se diferencian health checks de metricas normales?
R: Metricas muestran tendencia; health checks dan respuesta rapida "sistema listo o no ahora" para escenarios concretos.
P: Cual es el minimo de health checks para empezar?
R: Empieza con llm_reachable, tool_available, queue_ok y un synthetic run para workflow critico.
P: Por que synthetic run es tan importante?
R: Porque valida camino completo de ejecucion, no componente aislado. Es lo que mejor refleja estado real en production.
P: Si baja health score pero API aun responde, ya es incidente?
R: Es degradacion temprana. Hay que iniciar investigation de inmediato antes de fallo masivo.
Paginas relacionadas
Siguiente sobre el tema:
- Observability para agentes de IA — modelo base de tracing, logs y metricas.
- Metricas de agentes — senales generales de sistema para production.
- Alerting en agentes de IA — como construir alertas tempranas.
- Tracing de agente — como localizar paso que rompe health check.
- Latency Monitoring para agentes — como detectar degradacion de velocidad antes de incidente.