Módulo 8: Proyecto — Sistema de Alertas Programadas
Paso 4: Escalación con HITL
Descripción de la cápsula
Las alertas críticas requieren acknowledgement (ack) humano. Si nadie ack en 15 minutos, escalar al manager. Esto requiere 2 workflows adicionales: [ALERTS-ACK] (recibe acks) y [ALERTS-ESCALATE] (chequea pendientes).
Workflow [ALERTS-ACK]
Trigger
Webhook que recibe ack del oncall (desde el botón de Slack o link de email).
Webhook:
- Method: POST
- Path: /alerts-ack
- Auth: Header X-Ack-Secret
Procesamiento
[Webhook]
│
[Set: extraer alert_id del payload]
│
[Sheet: actualizar 'alerts_pending_ack']
- Find row con alert_id
- Set ack_at = $now
- Set ack_by = $json.body.user (si está)
│
[Slack: confirmar al oncall: "Alert {alert_id} ack-eada"]
Link en notificación original
En el Slack message original al canal #alerts-critical (cápsula 05), incluir botón Block Kit:
{
"type": "button",
"text": { "type": "plain_text", "text": "✅ Acknowledge" },
"url": "https://your-n8n/webhook/alerts-ack?alert_id={{ alert_id }}"
}
Click → GET con alert_id → workflow [ALERTS-ACK] recibe → marca como acknowledged.
Para Slack interactive realmente requiere webhook POST con payload, no GET. Implementación simplificada acá; en producción usar Slack interactivity con Request URL.
Workflow [ALERTS-ESCALATE]
Trigger
Schedule cada 5 minutos
Cron: */5 * * * *
TZ: America/Mexico_City
Procesamiento
[Schedule]
│
[Sheet: leer 'alerts_pending_ack']
- Filter: ack_at is empty (sin ack) AND created_at > 15 min ago
│
[IF: hay alertas sin ack > 15 min?]
└─ TRUE → escalar
Escalación
[SplitInBatches batch=1]
│
[Slack: a #manager-alerts]
"🚨 ALERTA SIN ACK - Manager attention required
Alert ID: {alert_id}
Métrica: {metric}
Tiempo sin ack: 15+ minutos
Detalles: ..."
│
[Sheet: actualizar alerts_pending_ack]
- Set escalated_at = $now
│
└─→ loop back
Verificar no escalar 2 veces
Si la escalación corre cada 5 min, podría re-escalar la misma alert. Filter para evitar:
[Sheet: filter 'alerts_pending_ack']
- ack_at is empty
- AND created_at > 15 min ago
- AND escalated_at is empty ← clave
Solo escalar las que aún no se escalaron.
Workflow [ALERTS-MAIN] actualizado
En la rama "crítica" (cápsula 05), después de notificar:
[Slack #alerts-critical, Email, etc. en paralelo]
│
[Sheet append 'alerts_pending_ack']
- alert_id: {{ $now.toMillis() }} + random
- metric
- severity: 'critical'
- created_at: $now
- ack_at: empty
- escalated_at: empty
Cada crítica se trackea para posible escalación.
Lifecycle de una alerta crítica
T+0: Alert detectada
→ Slack notification
→ Email a oncall
→ Sheet 'alerts_pending_ack' append
T+15: [ALERTS-ESCALATE] chequea
→ Si ack_at empty → escalar a manager
→ Sheet update escalated_at
T+30: Manager debería responder
(siguiente escalación si configuras: a director, etc.)
Workflow para "alert resolved"
Opcional pero útil: workflow [ALERTS-RESOLVED] para cerrar alertas cuando el problema se resuelve.
[Webhook /alerts-resolved]
│
[Sheet update: resolved_at = $now]
│
[Slack: "Alert X resuelta"]
Test de la cápsula
Test 1: Crítica con ack rápido
- Disparar alerta crítica
- Verificar Slack llega
- Hacer POST al webhook ack inmediatamente
- Verificar Sheet 'alerts_pending_ack' tiene ack_at
- 15 min después: escalation NO debería disparar
Test 2: Crítica sin ack
- Disparar alerta crítica
- NO hacer ack
- Esperar 15-20 min
[ALERTS-ESCALATE]debería:- Detectar la alert sin ack
- Mandar Slack al manager
- Marcar escalated_at
Test 3: Múltiples críticas
- Generar 3 críticas
- Ack 1, dejar 2 sin ack
- Escalación debería escalar las 2 sin ack
Validación
-
[ALERTS-ACK]recibe webhook y actualiza Sheet -
[ALERTS-ESCALATE]corre cada 5 min y escala correctamente - No escala 2 veces (filter de escalated_at)
- Slack message principal tiene botón ack funcional
- Auditoría completa en Sheet
Lo que sigue: Paso 5 — resilience completo del sistema.
Creado: Mayo 11, 2026 Versión: 1.0