Saltar al contenido principal

Heartbeat dinámico: cómo mantengo vivos a mis agentes IA

sysadmin linux self-hosted docker infraestructura agentes-ia

Cuando tienes varios agentes IA operando tu infraestructura —Codex escribiendo código, Palomino gestionando VMs, Lia redactando documentación— saber quién está vivo no es un lujo. Es lo que separa un sistema que funciona de uno donde los agentes escriben sobre archivos que ya no existen porque el que los mantenía se fue a dormir.

Mi solución: un sistema de heartbeat dinámico. Cada agente escribe un JSON en el NAS cada pocos segundos. El Panel de Control lo lee y decide si el agente está trabajando, descansando, o se ha caído.

Cómo funciona

Cada agente tiene un script que genera un archivo JSON en el NAS compartido:

{
  "agent": "codex",
  "status": "working",
  "sensors": {
    "gateway_pid": 123456,
    "session_age_seconds": 420,
    "cpu_loadavg": 0.45,
    "recent_nas_messages": 3,
    "active_shells": 1,
    "telegram_open": true
  },
  "last_seen": "2026-06-09T12:00:00Z"
}

El script se ejecuta cada 30 segundos vía cron de Hermes (modo no-agent — puro shell, sin LLM). Si falla, no pasa nada: el siguiente tick lo intenta de nuevo. El Panel detecta la ausencia de un heartbeat fresco tras 90 segundos y marca al agente como offline.

Siete sensores que monitorizo:

  1. PID del gateway Hermes — si el proceso padre ha muerto, el agente no puede operar
  2. ID de sesión + antigüedad — cuánto lleva la sesión activa
  3. CPU loadavg — si el servidor está saturado, el heartbeat lo refleja
  4. Mensajes NAS recientes — actividad de otros agentes en el bus compartido
  5. Shells activas — si hay alguien conectado manualmente
  6. Telegram abierto — el agente puede recibir instrucciones
  7. Sesiones en disco (fallback) — si el agente está entre reinicios

Los cinco estados

Cada agente transiciona automáticamente entre estos estados según su actividad:

working → idle → descanso_corto → descanso_largo → offline

Los umbrales los aprendí con el uso: menos de 15 minutos sin actividad es working (puede estar compilando o pensando). De 15 a 30 es idle. De 30 a 60, descanso_corto. Más de 60 minutos sin heartbeat, descanso_largo. Y cuando el archivo lleva más de 90 segundos sin actualizarse, offline.

Cada estado cambia el color del indicador en el Panel: verde, amarillo, naranja, rojo, gris. De un vistazo sé si puedo lanzar una tarea o si el agente está ocupado.

La plaga de los 3.100 procesos

No todo fue tan limpio al principio.

En una auditoría descubrimos que el servidor Palomino tenía un load average de 775. Más de 3.100 procesos de heartbeat ejecutándose simultáneamente. La causa: tres métodos de disparo compitiendo —cron entries, systemd con Restart=always, y scripts que se solapaban porque el propio sistema estaba tan saturado que no llegaban a terminar antes del siguiente tick.

El patrón era el clásico “disparar y olvidar”: cada iteración lanzaba un nuevo proceso hijo. Si el script tardaba 90 segundos en completarse (por la carga) y el cron disparaba cada 30 segundos, tenías tres procesos del mismo heartbeat ejecutándose en paralelo. Y si además tenías otro cron + systemd haciendo lo mismo con otro script, la multiplicación era exponencial.

La solución fue unificar en un singleton daemon: un solo script persistente con un while true y sleep 30 al final del bucle, gestionado por un único servicio systemd con Type=simple. Un proceso, un archivo, un punto de control.

[Unit]
Description=Unified Heartbeat Daemon - Palomino
After=network.target

[Service]
Type=simple
User=palomino
ExecStart=/home/palomino/hermes-broker/unified-heartbeat.sh
Restart=on-failure
RestartSec=5

Once líneas que sustituyeron a cuatro crons y un systemd redundante.

Por qué es crítico

En un sistema multi-agente, el heartbeat es el equivalente al ping en redes. Sin él, no sabes si un agente está procesando tu petición o se ha colgado. He visto a Codex lanzar cambios sobre archivos que otro agente estaba reescribiendo en ese mismo momento — el heartbeat no evita el conflicto, pero permite al Panel detectar actividad concurrente y escalar la decisión a mí.

Además, el heartbeat me da métricas históricas. Sé que Codex suele estar en estado working entre las 10:00 y las 14:00, que Palomino entra en descanso_largo cuando no hay tareas nocturnas, y que el sistema es más estable ahora que cuando tenía tres mil procesos peleándose por escribir el mismo archivo.

Si estás montando tu propio sistema de agentes o automatización, implementa el heartbeat antes que el primer agente. No esperes a tener 3.100 procesos fantasma para aprender la lección.