Módulo 2: Branching y Decisiones Avanzadas

Mini-Proyecto: Árbol de Decisión de 3 Niveles

Descripción de la cápsula

Cierre del módulo. Vas a construir un workflow real que integra todos los patrones de M02: pre-cómputo con Set, filtros en cadena, Switch grandes con agrupación, sub-workflows extraídos, y un fallback robusto. El caso: procesamiento automático de tickets de soporte con árbol de decisión de 3 niveles (categoría → severidad → idioma).

Es un proyecto realista — sistemas de soporte modernos hacen exactamente esto. Al terminar, vas a tener un workflow productivo que demuestra dominio del branching avanzado, y vas a tener experiencia diseñando lógica compleja sin caer en if hell.


Lo que vas a aprender

Al terminar este mini-proyecto serás capaz de:

  • Diseñar un árbol de decisión de 3 niveles antes de implementarlo
  • Aplicar pre-cómputo consistentemente
  • Estructurar Switch jerárquicos sin if hell
  • Extraer ramas a sub-workflows cuando se justifica
  • Validar exhaustivamente con casos por rama

El escenario completo

Lo que recibe el workflow

Tickets de soporte vía Webhook:

{
  "ticket_id": "TKT-12345",
  "subject": "No puedo iniciar sesión",
  "description": "Después de cambiar password no me deja entrar...",
  "customer_email": "cliente@ejemplo.com",
  "language": "es",
  "account_type": "premium",
  "received_at": "2026-05-11T14:30:00Z"
}

Lo que debe hacer

Nivel 1: Categorizar (tipo de problema)

  • auth (login, password, 2FA)
  • billing (cobros, facturas, suscripciones)
  • bug (algo no funciona)
  • general_inquiry (otros)

Nivel 2: Severidad (qué tan urgente)

  • critical — afecta múltiples usuarios o función core (asignar inmediato)
  • high — cliente premium o impacto serio (asignar prioritario)
  • medium — cliente standard, problema único (cola normal)
  • low — consulta general (auto-respuesta + cola)

Nivel 3: Idioma

  • es → equipo español
  • en → equipo inglés
  • other → equipo internacional (con traducción)

Acciones según camino:

  • Asignar al equipo correcto
  • Notificar canal Slack correspondiente
  • Si es crítica: alerta especial
  • Registrar en sistema de tickets (mock con Sheet)

Paso 1: Diseñar antes de construir

Antes de tocar n8n, dibuja el árbol en papel o con Excalidraw.

El árbol

Ticket llega
   │
   ├─ Nivel 1: ¿Categoría?
   │   ├─ "auth" → ...
   │   ├─ "billing" → ...
   │   ├─ "bug" → ...
   │   └─ "general_inquiry" → ...
   │
   ├─ Nivel 2 (dentro de cada rama): ¿Severidad?
   │   ├─ critical/high/medium/low
   │
   └─ Nivel 3 (dentro): ¿Idioma?
       ├─ es/en/other

Combinaciones totales

4 categorías × 4 severidades × 3 idiomas = 48 caminos posibles. Si implementaras todos como ramas anidadas literales: caos.

Estrategia: pre-computar una "full_category" como string concatenado (ej. auth_critical_es) y usar Switch único o sub-workflows para manejar.


Paso 2: Implementación del workflow principal

2.1. Workflow nuevo

Nombre: [PROY-G2M02] Router tickets soporte

2.2. Webhook Trigger

Configurar webhook POST con datos de ejemplo pineados (cápsula 03 de M01 te enseña).

2.3. Set de pre-cómputo (cápsula 04)

Set node después del webhook. Calcula todos los campos derivados:

// Field: category
{{
  $json.body.subject.toLowerCase().includes('login') ||
  $json.body.subject.toLowerCase().includes('password') ||
  $json.body.subject.toLowerCase().includes('2fa')
    ? 'auth' :
  $json.body.subject.toLowerCase().includes('cobro') ||
  $json.body.subject.toLowerCase().includes('factura') ||
  $json.body.subject.toLowerCase().includes('suscripción')
    ? 'billing' :
  $json.body.subject.toLowerCase().includes('error') ||
  $json.body.subject.toLowerCase().includes('bug') ||
  $json.body.subject.toLowerCase().includes('no funciona')
    ? 'bug' :
  'general_inquiry'
}}

// Field: severity
{{
  $json.body.description.toLowerCase().includes('todos los usuarios') ||
  $json.body.description.toLowerCase().includes('caído')
    ? 'critical' :
  $json.body.account_type === 'premium' ? 'high' :
  $json.body.account_type === 'standard' ? 'medium' :
  'low'
}}

// Field: language (puede venir o detectarse)
{{ $json.body.language || 'es' }}

// Field: full_category (la clave para routing)
{{ $json.category + '_' + $json.severity + '_' + $json.language }}

Nota: la detección de categoría aquí es simple (keyword matching). En producción real usarías AI/LLM (cubierto en G6/G7).

2.4. Switch principal

Como tenemos 48 caminos posibles, no listamos los 48 en el Switch. Estrategia:

Opción A: Switch sobre primer nivel + sub-Switches

[Switch sobre category]
├─→ "auth" → [Switch sobre severity] → [Switch sobre language] → ...
├─→ "billing" → ...
├─→ "bug" → ...
└─→ "general_inquiry" → [Send Email autorespuesta]

3 Switches anidados pero estructurados, no if hell.

Opción B: Switch único con menos categorías, lógica adicional en sub-workflows

[Switch sobre category]
├─→ "auth"            → [Execute Workflow: [BRANCH] handle-auth]
├─→ "billing"         → [Execute Workflow: [BRANCH] handle-billing]
├─→ "bug"             → [Execute Workflow: [BRANCH] handle-bug]
└─→ "general_inquiry" → [Execute Workflow: [BRANCH] handle-general]

Cada sub-workflow recibe full_category y maneja la lógica de severidad + idioma internamente.

Para este proyecto: Opción B (más limpio, escalable).


Paso 3: Crear los sub-workflows

Sub-workflow: [BRANCH] handle-auth

Recibe el ticket. Maneja:

[Execute Workflow Trigger]
   │
[Switch sobre severity]
├─→ "critical" → [Slack #soporte-urgente-{{language}}] + alert oncall
├─→ "high"     → [Slack #soporte-premium-{{language}}]
├─→ "medium"   → [Slack #soporte-{{language}}]
└─→ "low"      → [Auto-respuesta + Slack #soporte-{{language}}]

(Donde {{language}} se interpola según el campo del ticket.)

Para canales Slack distintos por idioma, podrías:

  • Tener canales #soporte-es, #soporte-en, #soporte-other
  • Set previo: slack_channel: "#soporte-" + language
  • Slack node usa {{ $json.slack_channel }}

Sub-workflow: [BRANCH] handle-billing

Similar estructura, pero los canales son distintos (#billing-...).

Sub-workflow: [BRANCH] handle-bug

[Execute Workflow Trigger]
   │
[Set: agregar contexto técnico]
   │
[Switch sobre severity]
├─→ "critical" → [GitHub: create issue] + Slack [#dev-bugs] + escalar a oncall
├─→ "high"     → GitHub issue + Slack #dev-bugs
├─→ "medium"   → Slack #dev-bugs (sin issue automático)
└─→ "low"      → Solo Slack #bugs-cola

Sub-workflow: [BRANCH] handle-general

Más simple — auto-respuesta + agregar a cola normal:

[Execute Workflow Trigger]
   │
[Send Email: autorespuesta en {{ language }}]
   │
[Sheet: append a "support_queue"]

Paso 4: Registrar todos los tickets

Al final del Workflow principal (después del Switch), siempre registrar el ticket en un Sheet processed_tickets:

[Switch] ...
   ...
   ▼
[Set: completar registro]
- full_category
- assigned_team
- processed_at

[Sheet: append "processed_tickets"]

Para que esto funcione, las ramas del Switch deben converger después del procesamiento específico:

[Switch]
├─→ rama A → [proceso A]
├─→ rama B → [proceso B]
└─→ ...
   ↓ (todas convergen)
[Sheet append: registrar]

O simplemente cada rama hace su Sheet append al final.


Paso 5: Validar con casos

Casos de prueba

Manda al webhook (vía Postman/curl) estos casos:

Caso 1: Auth crítica español

{
  "ticket_id": "TKT-001",
  "subject": "No puedo iniciar sesión - login caído",
  "description": "Todos los usuarios reportan que no pueden entrar",
  "customer_email": "admin@cliente.com",
  "language": "es",
  "account_type": "premium"
}

Esperado:

  • category: auth
  • severity: critical
  • language: es
  • Ruta: handle-auth → Slack #soporte-urgente-es + alert oncall
  • Sheet registra

Caso 2: Billing media inglés

{
  "ticket_id": "TKT-002",
  "subject": "Question about my invoice",
  "description": "I see a charge I don't recognize",
  "customer_email": "user@example.com",
  "language": "en",
  "account_type": "standard"
}

Esperado: handle-billing → Slack #billing-en (medium)

Caso 3: Bug premium inglés

{
  "ticket_id": "TKT-003",
  "subject": "Export feature is broken",
  "description": "When I try to export to CSV, nothing happens",
  "customer_email": "user@example.com",
  "language": "en",
  "account_type": "premium"
}

Esperado: handle-bug → Slack #dev-bugs + GitHub issue (high severidad)

Caso 4: Consulta general otro idioma

{
  "ticket_id": "TKT-004",
  "subject": "How do I add a new user?",
  "description": "...",
  "customer_email": "user@example.com",
  "language": "fr",
  "account_type": "standard"
}

Esperado: handle-general → autorespuesta en fr + cola

Caso 5: Severidad calculada vs explícita

Mismo ticket pero con account_type: "premium" vs standard. Verificar que severidad cambia entre high y medium correctamente.


Paso 6: Documentar con Sticky Notes

En el canvas del workflow principal, agrega Sticky Notes:

[Webhook]
   │
[Set: pre-cómputo]
   │  Sticky Note: "Computa: category, severity, language, full_category.
   │               Categorización por keywords en subject. En producción real,
   │               usaría LLM para categorización más robusta."
   │
[Switch]
   │  Sticky Note: "Switch sobre category.
   │               Cada rama es un sub-workflow [BRANCH] que maneja severity+language."
   │
   ...

3 meses después, tu yo futuro o un colega entiende el workflow en 30 segundos.


Reflexión: lo que aplicaste

Mira cuántos patrones del módulo usaste:

Patrón¿Dónde lo aplicaste?
Pre-cómputo (cápsula 04)Set inicial con category/severity/language
Switch consolidado (cápsula 03)Switch principal sobre category (4 ramas)
Sub-workflows (cápsula 07)4 sub-workflows para cada categoría
Switch dentro de sub (cápsula 03)Cada sub tiene Switch sobre severity
Categorías derivadas (cápsula 04)full_category calculada
Lookup-style (cápsula 04)Canales Slack construidos por concatenación

Todos los patrones del módulo aplicados en un solo workflow real.


Lo que aprendiste en M02 (zoom out)

Antes de M02Después de M02
IF anidados confusosPre-cómputo + Switch consolidado
12 IFs en un canvasSub-workflows extraídos
Condiciones inline complejasBooleans descompuestos con Set
Workflows que rompen al cambiarEstructura mantenible
Sin documentaciónSticky Notes en puntos clave

Más importante: ahora piensas en estructuras, no solo en nodos.


Resumen y siguiente paso

Lo que construiste:

  • Workflow real con árbol de decisión de 3 niveles
  • 1 workflow principal + 4 sub-workflows
  • 48 caminos lógicos posibles, todos manejados sin if hell

Lo que sabes:

  • Pre-cómputo como hábito
  • Switch jerárquico vs flat
  • Sub-workflows para manejar complejidad
  • Tests por rama exhaustivos

Antes de pasar a M03:

  • Workflow [PROY-G2M02] construido y testeado con los 5 casos
  • Sub-workflows con nombres convencionales [BRANCH]
  • Sticky Notes documentando puntos clave
  • Sheet processed_tickets registrando todos los items

Lo que sigue (Módulo 3 — Loops y Iteraciones):

Hasta acá, los workflows procesaban N items con iteración implícita (n8n itera automáticamente). M03 te enseña control explícito sobre iteración:

  • SplitInBatches para procesar de a N items
  • Patrones de loop (procesar todos, hasta cumplir condición, etc.)
  • Rate limiting para no saturar APIs externas
  • Procesamiento secuencial vs paralelo dentro de loops

Esencial cuando procesas listas grandes (1000+ items) o llamas APIs con rate limits.


Recursos adicionales

  1. Decision Tree Patterns - Conceptos generales.
  2. n8n Workflow Templates: Support Ticket Router - Templates similares.

Creado: Mayo 11, 2026 Versión: 1.0