Heartbeats y rutinas: agentes que trabajan solos

Por: Artiko
paperclipheartbeatsautomatizacióncronrutinas

El problema de los agentes que esperan

Un agente sin heartbeat es como un empleado que solo trabaja cuando alguien le da un tap en el hombro. Técnicamente funciona, pero no es lo que prometió la promesa de la IA autónoma.

Los heartbeats son el mecanismo que hace que los agentes sean proactivos. En lugar de esperar a que tú asignes manualmente cada tarea, los agentes se despiertan según un schedule, revisan qué hay que hacer, y lo hacen. Tú solo revisas el dashboard por las mañanas.

Entender los heartbeats correctamente es quizás la habilidad más importante para sacar provecho real de Paperclip.

Qué es un heartbeat

Un heartbeat es una configuración que dice: “cada vez que se cumpla esta condición, despierta a este agente con este contexto”.

La condición puede ser:

Cuando el heartbeat se dispara, Paperclip:

  1. Verifica que el agente no está ya corriendo (para evitar ejecuciones paralelas del mismo agente).
  2. Construye el contexto completo del agente (company context + skills + heartbeat payload).
  3. Invoca al agente a través de su adapter.
  4. Registra el inicio de la ejecución en el audit log.
  5. Espera el resultado y lo registra también.

Anatomía de un heartbeat

graph TD
    HC[Heartbeat Config] --> S[Schedule: cron o evento]
    HC --> T[Tipo: cron / event / manual]
    HC --> P[Payload: contexto inicial]
    HC --> LIM[Límites: timeout, max retries]
    
    S --> Trigger{Se cumple la condición}
    Trigger -->|sí| Check{¿Agente ya corriendo?}
    Check -->|no| Invoke[Invocar al agente]
    Check -->|sí| Skip[Skipped - log y continuar]
    Invoke --> Result[Registrar resultado]
    Result --> Next[Calcular próxima ejecución]

Los campos principales de configuración de un heartbeat:

# Ejemplo de configuración de heartbeat en YAML
heartbeat:
  id: hb_ceo_daily_review
  agentId: agent_ceo_felipe
  
  # Tipo y schedule
  type: cron
  schedule: "0 9 * * 1-5"    # 9am de lunes a viernes
  
  # Qué decirle al agente cuando se despierta
  payload: |
    Buenos días. Es el momento de tu revisión diaria.
    
    Por favor:
    1. Revisa el estado de todas las iniciativas activas
    2. Prioriza las tareas en el backlog según los goals
    3. Asigna work a tu equipo si hay tareas listas para ejecutar
    4. Identifica bloqueantes y escálalos si es necesario
    5. Prepara un resumen de 3 líneas para el Board
  
  # Configuración de ejecución
  timeout: 1800000             # 30 minutos máximo
  maxRetries: 2               # Reintentar hasta 2 veces si falla
  retryDelay: 300000          # Esperar 5 minutos entre reintentos
  
  # Estado
  enabled: true
  
  # Restricciones opcionales
  runOnlyIf:
    budgetRemainingUsd: 2.00  # Solo correr si queda al menos $2
    previousRunStatus: success # Solo correr si el anterior fue exitoso

Sintaxis cron para heartbeats

Los heartbeats de tipo cron usan la sintaxis estándar de cinco campos:

┌────────── Minuto (0-59)
│ ┌──────── Hora (0-23)
│ │ ┌────── Día del mes (1-31)
│ │ │ ┌──── Mes (1-12)
│ │ │ │ ┌── Día de la semana (0-7, 0 y 7 = domingo)
│ │ │ │ │
* * * * *

Ejemplos para DevCo:

# CEO - revisión diaria de mañana (lunes a viernes a las 9am)
"0 9 * * 1-5"

# CTO - revisión de PRs (cada 2 horas en horario laboral)
"0 9,11,13,15,17 * * 1-5"

# Ingeniero - check de tareas asignadas (cada 30 minutos)
"*/30 * * * 1-5"

# Agente de soporte L1 - siempre activo (cada 5 minutos)
"*/5 * * * *"

# Reporte semanal del CEO al Board (viernes a las 17:00)
"0 17 * * 5"

# Backup de base de datos (medianoche cada día)
"0 0 * * *"

# Análisis de métricas mensuales (primer día del mes a las 8am)
"0 8 1 * *"

Paperclip incluye un validador de cron en la UI que te muestra las próximas 5 ejecuciones del schedule que configures. Úsalo siempre antes de activar un heartbeat para confirmar que el timing es el que esperas.

Tipos de eventos que despiertan agentes

Los heartbeats basados en eventos se disparan cuando algo específico ocurre en el sistema. Esto permite respuestas reactivas sin polling constante.

Los eventos disponibles en Paperclip:

task_assigned          — Una tarea fue asignada a este agente
task_mentioned         — El agente fue @mencionado en una tarea
task_escalated         — Una tarea fue escalada a este agente
task_priority_changed  — La prioridad de una tarea del agente cambió
initiative_created     — Se creó una nueva iniciativa
initiative_updated     — Una iniciativa del agente fue actualizada
budget_warning         — El presupuesto llegó al 80%
budget_exhausted       — El presupuesto se agotó
company_goal_updated   — Los goals de la empresa cambiaron
board_override         — El Board activó este agente directamente
report_requested       — El Board o un manager pidió un reporte

Configuración de un heartbeat basado en eventos:

heartbeat:
  id: hb_cto_on_task_assigned
  agentId: agent_cto_ana
  type: event
  triggers:
    - event: task_assigned
    - event: task_escalated
    - event: task_mentioned
  
  payload: |
    Has recibido una nueva asignación o mención. 
    Revisa tu bandeja de entrada de tareas y procesa la más prioritaria.
    Si es una escalación, trátala con urgencia.
  
  # Debounce: esperar antes de activar para agrupar múltiples eventos
  debounceMs: 30000   # Esperar 30 segundos, procesar como batch
  
  timeout: 900000
  enabled: true

El campo debounceMs es útil cuando podrían llegar múltiples eventos seguidos. Sin debounce, si se asignan 5 tareas en rápida sucesión, el agente se activaría 5 veces. Con debounce de 30 segundos, el agente se activa una vez y procesa todas las tareas pendientes.

Ciclo de vida de un heartbeat

stateDiagram-v2
    [*] --> scheduled : Heartbeat creado y habilitado
    scheduled --> running : Se cumple el trigger
    running --> success : Agente completa sin error
    running --> failure : Timeout o error del adapter
    running --> skipped : Agente ya estaba corriendo
    success --> scheduled : Programar próxima ejecución
    failure --> retrying : Si maxRetries > 0
    retrying --> running : Después del retryDelay
    retrying --> failed_final : Después de maxRetries intentos
    failed_final --> scheduled : Programar próxima ejecución
    failed_final --> disabled : Si configured para disable-on-failure
    skipped --> scheduled : Registrado, programar próxima ejecución
    
    scheduled --> disabled : Board pausa el agente
    disabled --> scheduled : Board re-activa el agente

El estado failed_final merece atención especial. Cuando un heartbeat falla repetidamente, Paperclip puede configurarse para:

Rutina 1: Revisión diaria del CEO

Esta es la rutina más importante para la mayoría de deployments. El CEO se despierta cada mañana, revisa el estado de la empresa, y organiza el trabajo del día.

# heartbeat: CEO daily standup
heartbeat:
  id: hb_ceo_morning_standup
  agentId: agent_ceo_felipe
  type: cron
  schedule: "0 9 * * 1-5"
  
  payload: |
    ## Daily Standup - DevCo CEO
    
    Es tu revisión matinal. Tienes acceso completo al sistema.
    
    ### Tu agenda para hoy:
    
    **1. Estado de iniciativas (5 min)**
    Revisa el progreso de las 4 iniciativas activas. ¿Alguna está bloqueada?
    ¿Alguna va adelantada o atrasada?
    
    **2. Backlog review (10 min)**
    Revisa las tareas en backlog sin asignar. Prioriza las top 3 según los
    goals de la empresa y asígnalas a los agentes apropiados.
    
    **3. Escalaciones pendientes (5 min)**
    ¿Hay algo que tus managers necesitan de ti? ¿Alguna decisión pendiente?
    
    **4. Reporte para el Board (5 min)**
    Crea un resumen de 5 líneas con:
    - Estado general: verde/amarillo/rojo
    - Logro más importante de ayer
    - Principal bloqueante actual
    - Una decisión que tomes hoy
    - Presupuesto consumido este mes
    
    Crea el reporte como una tarea completada con tag "board-report".
    
    ### Contexto del presupuesto
    Tu presupuesto mensual es $20. Hoy es día {{ day_of_month }}.
    Gasta proporcionalmente.
  
  timeout: 2700000    # 45 minutos
  maxRetries: 1
  enabled: true

Rutina 2: Agente de soporte 24/7

El agente de soporte L1 necesita estar siempre disponible. No puede depender de un cron que se dispare cada hora porque los tickets de soporte tienen expectativa de respuesta rápida.

La estrategia correcta es un cron frecuente combinado con eventos:

# Polling frecuente: revisa si hay tickets nuevos
heartbeat:
  id: hb_support_poll
  agentId: agent_support_bot
  type: cron
  schedule: "*/10 * * * *"    # Cada 10 minutos
  
  payload: |
    Revisión de tickets pendientes.
    
    Procesa todos los tickets en estado "new" o "waiting_agent" 
    asignados a ti. Para cada ticket:
    1. Lee el problema del cliente
    2. Consulta tu FAQ y procedures
    3. Si puedes resolverlo: responde y cierra el ticket
    4. Si no puedes: escala al Head of Support con resumen del problema
    
    Límite: procesa máximo 5 tickets en esta ejecución.
  
  timeout: 600000     # 10 minutos
  enabled: true

---

# Evento: reacción inmediata a ticket de alta prioridad
heartbeat:
  id: hb_support_urgent
  agentId: agent_support_bot
  type: event
  triggers:
    - event: task_assigned
      filter:
        priority: critical
  
  payload: |
    ALERTA: Ticket crítico asignado.
    Procesa este ticket con máxima urgencia. Si no puedes resolverlo
    en 5 minutos, escala inmediatamente al Head of Support.
  
  debounceMs: 0       # Sin debounce para críticos
  timeout: 300000     # 5 minutos máximo
  enabled: true

Rutina 3: Reporte semanal automatizado

Al final de cada semana laboral, el CEO genera un reporte ejecutivo para el Board. Este reporte no requiere intervención: se genera solo, se crea como una tarea completada, y el Board recibe una notificación.

heartbeat:
  id: hb_ceo_weekly_report
  agentId: agent_ceo_felipe
  type: cron
  schedule: "0 17 * * 5"    # Viernes a las 17:00
  
  payload: |
    ## Weekly Executive Report
    
    Es el fin de semana. Genera el reporte ejecutivo semanal para el Board.
    
    ### Estructura del reporte (usa esta plantilla exacta):
    
    # DevCo Weekly Report - Semana {{ week_number }}
    
    ## Resumen ejecutivo
    [2-3 frases sobre el estado general de la empresa esta semana]
    
    ## Progreso por iniciativa
    [Para cada iniciativa activa: % completado, bloqueantes, ETA]
    
    ## Métricas clave
    - Tareas completadas esta semana: X
    - Tareas abiertas: X
    - Presupuesto consumido: $X de $200 (X%)
    - Incidencias de soporte: X tickets, X% resueltos en <2h
    
    ## Decisiones tomadas esta semana
    [Lista de decisiones significativas con su justificación]
    
    ## Semana próxima
    [Top 3 prioridades para la semana que viene]
    
    ## Solicitudes al Board
    [Si necesitas autorización, presupuesto adicional, o input del Board]
    
    ### Instrucciones:
    1. Consulta el historial de tareas de esta semana
    2. Consulta el estado actual de todas las iniciativas
    3. Consulta el resumen de costos de la semana
    4. Genera el reporte completo
    5. Crea una tarea completada con título "Weekly Report Semana X"
       y tag "board-report"
    
    El Board recibirá notificación automática cuando el reporte esté listo.
  
  timeout: 3600000    # 1 hora
  enabled: true

Rutina 4: Monitoreo de infraestructura

El ingeniero senior puede tener un heartbeat de monitoreo que revise la salud del sistema y cree tickets automáticamente cuando encuentra problemas:

heartbeat:
  id: hb_infra_monitor
  agentId: agent_eng_rafa
  type: cron
  schedule: "*/30 * * * *"    # Cada 30 minutos
  
  payload: |
    Revisión de infraestructura rutinaria.
    
    Verifica:
    1. Estado de los servicios críticos (API, DB, workers)
    2. Tiempos de respuesta de los endpoints clave
    3. Errores en los logs de las últimas 30 minutos
    4. Uso de recursos (CPU, memoria, disco)
    
    Si encuentras anomalías:
    - CRÍTICO (servicio caído, error rate > 5%): 
      Crea ticket de prioridad critical y escala al CTO inmediatamente
    - ADVERTENCIA (tiempo de respuesta degradado, disco > 80%):
      Crea ticket de prioridad high y asígnate a ti mismo
    - OK: Registra log corto, sin ticket
    
    Herramientas disponibles: curl, pg_isready, df, free, tail
  
  timeout: 300000     # 5 minutos
  runOnlyIf:
    budgetRemainingUsd: 1.00
  enabled: true

Heartbeats vs agentes continuos

Una distinción conceptual importante: los heartbeats despiertan al agente, hacen trabajo, y luego el agente “duerme” hasta el próximo heartbeat. No es un agente que corre permanentemente en background.

graph LR
    subgraph "Heartbeat (Paperclip)"
    H1[Duerme] -->|cron trigger| H2[Despierta]
    H2 --> H3[Trabaja]
    H3 --> H4[Termina]
    H4 -->|hasta próximo trigger| H1
    end
    
    subgraph "Agente continuo (no Paperclip)"
    C1[Corre siempre] -->|nuevo input| C2[Procesa]
    C2 --> C1
    end

Los agentes continuos (como un servidor que está siempre escuchando) son más difíciles de gestionar, costosos de mantener, y problemáticos para el control de presupuesto. Los heartbeats son la forma que Paperclip tiene de hacer que los agentes sean activos pero controlados.

Para casos donde necesitas baja latencia de respuesta (ej: soporte), la solución es un cron muy frecuente (cada 1-2 minutos) en lugar de un agente continuo. Es funcionalmente equivalente para la mayoría de casos de uso, con la ventaja de que cada ejecución es independiente, trazada, y dentro del modelo de presupuesto.

Debugging de heartbeats

Cuando un heartbeat no funciona como esperas, hay varias herramientas de diagnóstico:

Ver el historial de ejecuciones:

Company → Agents → [Agente] → Heartbeats → [Heartbeat] → Execution History

Cada ejecución muestra:

Trigger manual de un heartbeat: Desde la misma pantalla, el botón Trigger Now ejecuta el heartbeat inmediatamente, ignorando el schedule. Útil para probar la configuración sin esperar al próximo trigger programado.

Modo debug: Activa el modo debug para ver exactamente qué contexto se le envía al agente:

Company → Agents → [Agente] → Heartbeats → [Heartbeat] → Debug Mode: ON

Con debug activo, la próxima ejecución registra el payload completo enviado al agente (incluyendo todas las skills inyectadas), lo cual permite verificar que el agente recibe el contexto correcto.

Logs del sistema:

# Logs de heartbeats del servidor
tail -f ~/.paperclip/logs/agents.log | grep heartbeat

# Filtrar por agente específico
tail -f ~/.paperclip/logs/agents.log | grep "agent_ceo_felipe"

# Ver errores de los últimos 30 minutos
grep "ERROR" ~/.paperclip/logs/agents.log | tail -50

Problemas comunes y soluciones:

graph TD
    P1[Heartbeat no se dispara] --> S1{Schedule correcto?}
    S1 -->|no| Fix1[Verificar cron syntax con validator]
    S1 -->|sí| S2{Agente enabled?}
    S2 -->|no| Fix2[Board → Agents → Enable]
    S2 -->|sí| S3{Budget agotado?}
    S3 -->|sí| Fix3[Board → Budget → Reset o ajustar]
    S3 -->|no| Fix4[Ver logs del sistema]
    
    P2[Heartbeat se dispara pero falla] --> E1{Timeout?}
    E1 -->|sí| Fix5[Aumentar timeout o simplificar payload]
    E1 -->|no| E2{Error del adapter?}
    E2 -->|sí| Fix6[Verificar configuración del adapter]
    E2 -->|no| Fix7[Revisar output del agente]

Heartbeat que se saltea (skipped): Si ves muchos skipped en el historial, significa que el agente todavía estaba corriendo cuando el siguiente heartbeat se intentó disparar. Soluciones:

Gestión del ciclo de vida de los heartbeats

Los heartbeats son configuración dinámica: puedes habilitarlos, deshabilitarlos, y modificarlos sin reiniciar el servidor.

# Via API directamente
# Deshabilitar temporalmente (ej: durante mantenimiento)
curl -X PATCH http://localhost:3100/api/heartbeats/hb_ceo_daily_review \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

# Habilitar de nuevo
curl -X PATCH http://localhost:3100/api/heartbeats/hb_ceo_daily_review \
  -d '{"enabled": true}'

# Trigger manual
curl -X POST http://localhost:3100/api/heartbeats/hb_ceo_daily_review/trigger \
  -d '{"reason": "manual_test"}'

# Ver estado de todos los heartbeats
curl http://localhost:3100/api/heartbeats?companyId=company_devco

Cuando pausas un agente desde el Board, todos sus heartbeats se deshabilitan automáticamente. Cuando lo reactivas, los heartbeats vuelven a su estado previo.

Esta interacción entre el control del Board y los heartbeats es fundamental: el Board siempre tiene el poder de parar cualquier agente instantáneamente, y ese poder se refleja automáticamente en todos sus mecanismos de ejecución.

Con los heartbeats configurados, tu empresa de agentes está operando de forma autónoma. El siguiente paso es entender el sistema de tickets con más profundidad: cómo fluye el trabajo desde la asignación hasta el cierre, y cómo el audit log te da visibilidad completa de lo que está pasando.