Módulo 7: Wait Nodes y Flujos Asíncronos
Human-in-the-Loop (intervención humana)
Descripción de la cápsula
Algunos workflows no deberían automatizarse 100%: requieren juicio humano. Ejemplos: aprobar refunds grandes, validar contenido antes de publicar, decidir entre opciones complejas. Human-in-the-loop (HITL) es el patrón que pausa el workflow para que un humano decida, después continúa.
En esta cápsula vas a aprender los 3 patterns de HITL (Slack actionable, email con links, formularios), cuándo aplicar, y cómo evitar las trampas.
Lo que vas a aprender
- ✅ Diseñar HITL efectivos
- ✅ 3 patterns: Slack interactivo, email con links, form
- ✅ Manejar timeouts y respuestas no recibidas
- ✅ Trade-offs vs automatización completa
El concepto
[Procesamiento automático]
│
[Wait for human decision]
│
[Procesamiento continúa según decisión humana]
El "Wait for human" usa Wait for Webhook (cápsula 05). El humano interactúa con algún medio (Slack, email, form) que dispara el resume.
Pattern 1: Slack interactivo
Slack tiene Block Kit con botones que pueden disparar webhooks.
Implementación simplificada
[Trigger]
│
[Slack: send message con botones]
Blocks con buttons que tienen URLs:
- Approve: $resumeUrl?action=approve
- Reject: $resumeUrl?action=reject
│
[Wait for Webhook: 24h timeout]
│
[Switch: $json.body.action]
├─→ "approve" → procesar
├─→ "reject" → notificar y descartar
└─→ timeout → escalar
Block Kit con buttons que abren URL
[
{
"type": "section",
"text": { "type": "mrkdwn", "text": "¿Aprobar refund de ${{ $json.amount }}?" }
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "✅ Aprobar" },
"url": "{{ $resumeUrl }}?action=approve",
"style": "primary"
},
{
"type": "button",
"text": { "type": "plain_text", "text": "❌ Rechazar" },
"url": "{{ $resumeUrl }}?action=reject",
"style": "danger"
}
]
}
]
Click en botón → GET request al URL → reanuda workflow.
Pattern 2: Email con links
Similar pero por email.
[Send Email]
HTML:
<p>Decidir sobre refund de ${{ $json.amount }}:</p>
<a href="{{ $resumeUrl }}?action=approve">✅ Aprobar</a> |
<a href="{{ $resumeUrl }}?action=reject">❌ Rechazar</a>
│
[Wait for Webhook]
│
[Switch action]
Pros
- Funciona sin instalar nada
- Email es más async-friendly (admin responde cuando puede)
Contras
- Click accidental difícil de revertir
- Sin contexto rich (vs Slack threads)
Pattern 3: Form de aprobación
Para decisiones que requieren input adicional del humano (no solo botón):
[Send Email/Slack con link a form]
El link incluye execution_id que identifica este workflow
│
[Wait for Webhook]
El form (Tally, Typeform) tiene campos:
- Action: approve/reject
- Comentarios
- Otros campos relevantes
Cuando el humano submit el form, su webhook resume el workflow con todos los datos.
Cuándo usar HITL
Sí
- Decisiones con consecuencias significativas
- Casos edge que no son frecuentes (no vale automatizar)
- Compliance requiere human review
- Validación final antes de acción irreversible
No
- Decisiones de alto volumen (cuello de botella)
- Decisiones simples que pueden automatizarse
- Cuando humanos no están disponibles 24/7
Diseño defensivo de HITL
Timeout explícito
Humanos olvidan. Olvidan responder en vacaciones. Siempre timeout:
[Wait for Webhook: 24h timeout]
│
[IF: timeout?]
├─ TRUE → [escalación: notificar manager + fallback]
└─ FALSE → procesar decisión
Idempotencia (botones)
Si humano hace click 2 veces, ¿pasa algo?
- Primer click: workflow reanuda
- Segundo click: URL ya inválida (n8n no reanuda 2x)
Pero si quieres confirmación al humano del primer click, el resume URL podría devolver una página HTML "Aprobado, gracias".
Auditoría
Loggear cada decisión:
[Set: log decision]
- decided_by: extraído del webhook si está disponible
- decided_at: $now
- decision: action
│
[Sheet append 'decisions_log']
Multi-aprobador
A veces necesitas N aprobadores: "monto > $5000 requiere 2 aprobaciones".
[Wait for Webhook 1] → first approval
│
[Send to approver 2]
│
[Wait for Webhook 2] → second approval
│
[procesar]
Cada aprobación pausa workflow.
Trade-offs vs automatización
Automatización completa
Pros: rápida, escala, sin cuello de botella. Contras: errores caros, sin contexto humano para edge cases.
HITL
Pros: control humano, edge cases manejados. Contras: cuello de botella, depende de disponibilidad humana.
Híbrido recomendado
[Reglas automáticas para casos comunes]
│
[IF: caso normal]
├─ TRUE → automatizado
└─ FALSE → [HITL: human decide]
90% automático, 10% HITL para casos no obvios.
Trampas comunes
Trampa 1: HITL sin timeout
Qué pasa: Aprobador renuncia, va de vacaciones, ignora email. Workflow espera para siempre.
Cómo evitar: Timeout + escalación.
Trampa 2: Botones sin confirmación
Qué pasa: Botón "Reject" en email. Click accidental. Sin forma de deshacer.
Cómo evitar: Botones llevan a página de confirmación antes del POST final.
Trampa 3: Resume URL filtrada en archives
Qué pasa: Email con resume URL queda en archive accesible públicamente. Alguien externo "aprueba".
Cómo evitar: Auth en el resume webhook + verificar identidad del clicker (cookie, header, etc.).
Trampa 4: Demasiado HITL
Qué pasa: Pides aprobación humana para cada cosa. Equipo abrumado. Decisiones tardan días.
Cómo evitar: Reglas claras de cuándo HITL: solo casos donde realmente vale la pena.
Resumen
- HITL: pausa workflow para que humano decida
- 3 patterns: Slack interactivo, email con links, form
- Cuándo usar: decisiones críticas, baja frecuencia, edge cases
- Defensa: timeout, idempotencia, auditoría, multi-aprobador
- Híbrido: automático para común, HITL para edge cases
- 4 trampas: sin timeout, botones sin confirm, URL filtrada, demasiado HITL
Lo que sigue: Long-running workflows — consideraciones para flows de duración extensa.
Creado: Mayo 11, 2026 Versión: 1.0