¿Por qué n8n y no solo Python?
El 80% de las automatizaciones de negocio no necesitan código. n8n permite construir flujos complejos con lógica visual, conectar 400+ servicios con un clic, y desplegar en self-hosted sin depender de un vendor. El desarrollador de automatizaciones no reemplaza al ingeniero — tiene un mercado propio: las PyMEs que necesitan resultados hoy, no en seis meses.
La decisión de arquitectura más importante: n8n vs Make vs Zapier
- n8n (self-hosted): control total, sin límites de operaciones, código JavaScript en nodos, ideal para datos sensibles o flujos complejos. Requiere un VPS (~$5/mes).
- Make (antes Integromat): visual avanzado, mejor para flujos de datos no lineales, pricing por operaciones. Bueno para clientes que no quieren self-host.
- Zapier: el más simple, el más caro por operación. Solo para integraciones simples de 2–3 pasos donde la velocidad de setup importa más que el costo.
Anatomía de un flujo n8n en producción
| Componente | Descripción | Cuándo usarlo |
|---|---|---|
| Trigger | Webhook, Cron, o evento de app externa | Siempre — todo flujo empieza aquí |
| HTTP Request | Llamada a cualquier API REST | Cuando no existe nodo nativo |
| AI Agent | LLM con tools y memoria nativa en n8n | Razonamiento y decisiones dinámicas |
| Code (JS) | JavaScript para transformación de datos | Lógica que los nodos no cubren |
| If / Switch | Routing condicional del flujo | Múltiples caminos por tipo de input |
| Error Trigger | Captura errores del flujo completo | Siempre en flujos de producción |
{
"name": "M1 · StackSetup — Webhook → AI → Supabase",
// Patrón base que todos los flujos del proyecto usarán
"nodes": [
{
"type": "n8n-nodes-base.webhook",
"name": "Webhook Entry",
// Recibe POST desde WhatsApp, formularios, o cualquier fuente
"parameters": {
"httpMethod": "POST",
"path": "flowbot-entry",
"responseMode": "responseNode"
}
},
{
"type": "n8n-nodes-base.code",
"name": "Validate & Normalize",
// Siempre valida el input antes de pasar al LLM
"parameters": {
"jsCode": "
const { body } = $input.first().json;
// Regla de oro: nunca confíes en el input sin validar
if (!body?.message || typeof body.message !== 'string') {
throw new Error('INPUT_INVALID: campo message requerido');
}
return [{
json: {
message: body.message.trim().slice(0, 2000),
user_id: body.user_id || 'anonymous',
channel: body.channel || 'webhook',
timestamp: new Date().toISOString(),
trace_id: crypto.randomUUID()
}
}];"
}
},
{
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"name": "Claude (STANDARD)",
"parameters": {
"model": "claude-3-5-sonnet-20241022",
"options": { "temperature": 0.3 }
}
},
{
"type": "n8n-nodes-base.supabase",
"name": "Log to Supabase",
// Todo flujo de prod logea inputs y outputs
"parameters": {
"operation": "insert",
"tableId": "automation_logs"
}
}
]
}
- Instala n8n en local con Docker:
docker run -it --rm --name n8n -p 5678:5678 n8nio/n8n - Crea una cuenta en Supabase y genera una tabla
automation_logscon campos: id, trace_id, message, response, channel, created_at - Obtén tu API key de Anthropic (o OpenAI) y configúrala como credential en n8n
- Crea el flujo del código base: Webhook → Code (validación) → AI → Supabase → Respond
- Envíale un POST con curl y verifica que el log quede en Supabase con el trace_id correcto
- Escribe un prompt de ~300 palabras (system + user) representativo de tu caso de uso
- Usa el tokenizer de Anthropic para contar tokens de input y output estimado
- Calcula el costo para 1000 requests con Haiku vs Sonnet vs GPT-4o-mini
- ¿Cuánto ahorra usar Haiku para clasificaciones simples? Documenta el número
- Decide qué modelo usará cada nodo del proyecto y justifícalo en un ADR de 1 página
docker-compose.yml y el flujo base son la capa de infraestructura de FlowBot. Todos los módulos siguientes añaden nodos a este flujo base — nunca crean uno nuevo desde cero.
El prompt es el contrato con el modelo
En automatizaciones de negocio, el output del LLM no lo lee un humano — lo procesa el siguiente nodo del flujo. Esto cambia completamente cómo se escribe un prompt. No buscas "una respuesta buena", buscas un JSON parseable, un booleano, o una categoría de un enum. La ambigüedad en el prompt es un bug de producción.
Estructura de prompt para automatizaciones (4 secciones)
- ROL + TAREA: quién es el modelo y exactamente qué debe hacer. Sin ambigüedad.
- CONTEXTO DINÁMICO: variables que cambian por request (datos del usuario, historial, catálogo). Inyectadas en tiempo de ejecución.
- RESTRICCIONES: qué NO puede hacer. Tan importante como lo que sí puede.
- OUTPUT FORMAT: el formato exacto de la respuesta. Para flujos: siempre JSON válido con schema explícito.
Output estructurado — la técnica más importante para n8n
| Técnica | Cuándo usarla | Riesgo |
|---|---|---|
| JSON directo | Clasificación, extracción de datos, routing | El modelo puede añadir texto antes del JSON |
| XML tags (<output>) | Cuando necesitas separar razonamiento de respuesta | Hay que hacer parse del XML |
| Structured Outputs API | Claude/OpenAI soportan JSON schema nativo | Solo funciona con ciertos modelos |
| Few-shot + formato | Cuando el formato es complejo y el modelo falla | Añade tokens y costo |
// Nodo Code en n8n: LLM wrapper con output estructurado garantizado const systemPrompt = ` ROL: Eres un clasificador de intenciones para un bot de soporte de PyME. TAREA: Analiza el mensaje del usuario y devuelve una clasificación. CATEGORÍAS DISPONIBLES: - "product_inquiry": pregunta sobre producto, precio, disponibilidad - "order_status": consulta sobre estado de pedido - "complaint": queja o problema con producto/servicio - "general": saludo, despedida, o conversación fuera de scope RESTRICCIONES: - Devuelve SOLO el JSON especificado. Sin texto adicional. - No inventes categorías fuera de las 4 definidas. - confidence debe ser un número entre 0.0 y 1.0. OUTPUT FORMAT (devuelve EXACTAMENTE este JSON): { "intent": "product_inquiry|order_status|complaint|general", "confidence": 0.0-1.0, "key_entities": ["entidad1", "entidad2"], "requires_human": true|false } `; // Llamada con retry automático y validación de output async function classifyWithRetry(message, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { const response = await $node["Claude API"].call({ messages: [{ role: "user", content: message }], system: systemPrompt, max_tokens: 150 // output pequeño = más rápido y barato }); try { // Limpia posibles decoradores del modelo antes de parsear const clean = response.text .replace(/```json\n?/g, '') .replace(/```/g, '') .trim(); const parsed = JSON.parse(clean); // Valida que el schema sea correcto antes de continuar const validIntents = ['product_inquiry','order_status','complaint','general']; if (!validIntents.includes(parsed.intent)) throw new Error('INVALID_INTENT'); if (typeof parsed.confidence !== 'number') throw new Error('INVALID_CONFIDENCE'); return parsed; } catch (e) { if (attempt === maxRetries - 1) { // Último intento: devuelve fallback seguro en vez de romper el flujo return { intent: 'general', confidence: 0.5, key_entities: [], requires_human: true }; } } } } return [{ json: await classifyWithRetry($json.message) }];
- Crea el prompt de clasificación con 5 categorías para tu caso de uso (ej: ventas, soporte, precios, ubicación, otro)
- Pruébalo con 20 mensajes variados — ¿en cuántos acierta el intent?
- Identifica los 3 casos donde falla. ¿Es un problema del prompt o del modelo?
- Agrega ejemplos few-shot para los casos que fallan. ¿Mejora?
- Implementa el wrapper con retry y fallback. Verifica que nunca rompa el flujo, aunque el JSON sea inválido.
- Toma 10 emails de pedidos reales (o simulados) de un cliente hipotético
- Escribe un prompt que extraiga: nombre, producto, cantidad, fecha requerida, urgencia (alta/media/baja)
- Verifica que el JSON output sea parseable en los 10 casos
- Añade el nodo "Validate & Store" en n8n que guarda el objeto extraído en Supabase
- ¿Qué pasa si el email está en mezcla de español e inglés? ¿Sigue funcionando?
LLMWrapper es el primer nodo inteligente del FlowBot. En M3 se extenderá para soportar Tool Calling. En M8, el clasificador determinará el agente al que se enruta cada conversación.
¿Qué es el nodo AI Agent de n8n?
El nodo AI Agent de n8n implementa nativamente el patrón ReAct (Reason + Act) sin necesitar código Python. El agente puede usar herramientas (otros nodos de n8n), mantener memoria entre turnos, y decidir cuándo ya tiene suficiente información para responder. La diferencia con un simple nodo LLM es que el agente puede tomar múltiples pasos antes de responder.
Tools disponibles en n8n para el AI Agent
- HTTP Request Tool: cualquier API externa. El agente decide cuándo llamarla y con qué parámetros.
- Supabase Tool: búsqueda y escritura en base de datos. El agente puede consultar información del cliente sin que tú lo hagas explícitamente.
- Vector Store Tool: búsqueda semántica en documentos. Base del patrón RAG.
- Code Tool: JavaScript ejecutable. Para cálculos o transformaciones que el LLM haría mal.
- Think Tool: permite al agente razonar en voz alta antes de actuar. Mejora la calidad en casos complejos.
El riesgo más crítico: loops infinitos
Sin configuración correcta, un agente puede llamar a la misma herramienta en ciclo si el output no satisface sus criterios internos. n8n no previene esto por defecto.
maxIterations) en producción. Un loop de 50 iteraciones con Claude Sonnet cuesta ~$1.50 por conversación. Con 1000 usuarios, son $1500 en un día. Siempre setea maxIterations entre 5 y 10.// Configuración del nodo AI Agent en n8n (parámetros clave) { "type": "@n8n/n8n-nodes-langchain.agent", "parameters": { "agentType": "toolsAgent", // ReAct nativo "maxIterations": 6, // CRÍTICO: previene loops infinitos "returnIntermediateSteps": false, // true solo para debugging "systemMessage": " Eres FlowBot, asistente de soporte de {{company_name}}. CAPACIDADES: ✓ Consultar estado de pedidos (usa search_orders) ✓ Buscar información de productos (usa search_catalog) ✓ Crear tickets de soporte (usa create_ticket) ✗ NO puedes: modificar pedidos, aplicar descuentos, acceder a datos de pago REGLAS DE COMPORTAMIENTO: - Responde siempre en el idioma en que te hablan - Si la confianza es menor a 0.7, pide clarificación antes de actuar - Si el problema requiere acción humana, escala sin intentar resolver tú ESCALACIÓN INMEDIATA cuando: - El cliente está molesto después de 2 intentos de resolución - La consulta es sobre devolución de dinero - El cliente pregunta explícitamente por un humano OUTPUT: Siempre respuestas cortas (máx 3 oraciones para chat) ", "tools": [ { "name": "search_orders", "description": "Busca pedidos del cliente. Usa order_id o email del cliente.", "node": "Supabase - Orders" }, { "name": "search_catalog", "description": "Busca información de productos en el catálogo. Usa el nombre o descripción del producto.", "node": "Vector Store - Catalog" }, { "name": "create_ticket", "description": "Crea un ticket de soporte. Úsalo cuando no puedas resolver el problema directamente.", "node": "HTTP - CRM Create Ticket" } ] } }
- Crea un flujo manual: Webhook → Code (parse intent) → If (¿necesita tool?) → HTTP Tool → Code (format response)
- Prueba con: "¿cuánto cuesta el producto X?" — el flujo debe buscar en catálogo
- Prueba con: "hola buenas tardes" — el flujo debe responder directo sin buscar
- Ahora reemplaza toda esa lógica con el nodo AI Agent. ¿Es más simple? ¿Qué control perdiste?
- Fuerza el loop: haz que la herramienta siempre devuelva error. ¿El maxIterations se activa?
- Configura el agente con maxIterations=10 y registra el costo de 20 conversaciones variadas
- ¿Cuántas conversaciones usaron más de 5 iteraciones? ¿Cuánto costaron en promedio?
- Ajusta maxIterations=5. ¿Qué conversaciones ahora no se resuelven correctamente?
- Documenta el balance óptimo para tu caso de uso específico
- Implementa un fallback: si se alcanza maxIterations, escala a humano automáticamente
AgentFlow es el núcleo del FlowBot. En M4 se conectará al RAGPipeline como tool. En M5 recibirá mensajes desde WhatsApp. En M8 se especializará por tipo de conversación.
RAG en términos de negocio
RAG (Retrieval-Augmented Generation) es la técnica que permite al bot responder preguntas usando el conocimiento específico de tu cliente — catálogo, FAQs, políticas — sin necesitar fine-tuning. El flujo es simple: el usuario hace una pregunta → el sistema busca los documentos más relevantes → el LLM responde usando esos documentos como contexto.
Los 4 pasos del pipeline RAG en n8n
- Ingesta (offline): documento → split en chunks (400-600 tokens) → embedding (OpenAI o Anthropic) → guardar en Supabase pgvector con metadata.
- Retrieval (online): query del usuario → embedding → búsqueda por similaridad coseno → top-5 chunks más relevantes.
- Augmentation: chunks recuperados → inyectar como contexto en el prompt del agente con instrucción "Usa solo esta información para responder".
- Citation check: ¿la respuesta del LLM está respaldada por los chunks? Si no hay chunks relevantes, el agente debe admitirlo en vez de alucinar.
-- 1. Tabla de documentos con vector en Supabase CREATE TABLE knowledge_base ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, content text NOT NULL, embedding vector(1536), -- OpenAI ada-002 / text-3-small source text, -- "catalog", "faq", "policy" metadata jsonb, -- producto_id, categoria, etc. created_at timestamptz DEFAULT now() ); -- 2. Función de búsqueda semántica (llama desde n8n HTTP Request) CREATE OR REPLACE FUNCTION search_knowledge( query_embedding vector(1536), match_threshold float DEFAULT 0.78, match_count int DEFAULT 5 ) RETURNS TABLE(content text, similarity float, source text) LANGUAGE sql STABLE AS $$ SELECT content, 1 - (embedding <=> query_embedding) AS similarity, source FROM knowledge_base WHERE 1 - (embedding <=> query_embedding) > match_threshold ORDER BY similarity DESC LIMIT match_count; $$; -- 3. En n8n: nodo Code para preparar el contexto RAG const chunks = $json.chunks; // resultado de search_knowledge if (chunks.length === 0) { return [{ json: { context: "", has_context: false } }]; } const context = chunks .map((c, i) => `[Fuente ${i+1}]: ${c.content}`) .join('\n\n'); return [{ json: { context, has_context: true, sources: chunks.map(c => c.source) }}];
- Toma 20-30 productos de un catálogo real (o invéntalo) — nombre, descripción, precio, categoría
- Diseña la estrategia de chunking: ¿un chunk por producto? ¿por categoría? Justifica
- Crea el flujo de ingesta en n8n: CSV/Sheet → Code (format) → OpenAI Embeddings → Supabase upsert
- Ejecuta 10 preguntas sobre el catálogo. ¿El retrieval devuelve los productos correctos?
- Ajusta el match_threshold hasta lograr que las preguntas irrelevantes devuelvan 0 chunks
- Configura el nodo "Vector Store Tool" en el AI Agent apuntando a tu tabla knowledge_base
- Prueba: "¿Cuál es el precio del producto X?" — ¿el agente llama la tool o responde de memoria?
- Prueba: "hola, ¿cómo estás?" — ¿el agente evita llamar la tool innecesariamente?
- Agrega la instrucción "Si no encuentras la información en el catálogo, admítelo" al system prompt
- Verifica: pregunta sobre algo que NO está en el catálogo. ¿El agente alucina o admite que no sabe?
RAGPipeline convierte el catálogo del cliente en memoria consultable. En M6 (ventas), el agente lo usará para recomendar productos. En M8 (soporte), para responder sobre políticas y FAQ.
WhatsApp como canal principal en LATAM
En América Latina, WhatsApp es el canal de comunicación por defecto de las PyMEs. El 90%+ de los clientes prefiere resolver problemas por WhatsApp antes que por email o formulario web. Un bot de WhatsApp que funciona bien genera ROI inmediato y visible: el dueño del negocio lo ve en la reducción de mensajes que tiene que responder manualmente.
Los 3 estados de una conversación en WhatsApp
- Automatizada: el bot maneja todo. Aplica para el 70% de las consultas repetitivas (precio, horarios, estado de pedido).
- Asistida (HITL): el bot propone, el humano aprueba antes de enviar. Para cotizaciones o cambios de pedido.
- Escalada: el bot detecta que no puede resolver y transfiere a un humano en Chatwoot. Para quejas o casos complejos.
// Flujo: mensaje WhatsApp → bot → respuesta automática o escalación // PASO 1: Webhook de Evolution API (entrada) // POST /webhook → { data: { key: { remoteJid }, message: { conversation } } } const phone = $json.data.key.remoteJid.replace('@s.whatsapp.net', ''); const message = $json.data.message?.conversation || $json.data.message?.extendedTextMessage?.text || ''; // PASO 2: Recuperar o crear sesión del usuario const session = await $node["Supabase - Get Session"].run({ phone, create_if_missing: true }); // PASO 3: Pasar al AI Agent con contexto completo return [{ json: { phone, message, session_id: session.id, history: session.messages.slice(-10), // últimos 10 mensajes channel: 'whatsapp' }}]; // ───────────────────────────────────────── // PASO 5: Enviar respuesta via Evolution API const agentResponse = $json.output; const shouldEscalate = $json.escalate === true; if (shouldEscalate) { // Crear conversación en Chatwoot con contexto completo await $node["HTTP - Chatwoot Create Conv"].run({ phone, initial_message: `[BOT escaló] Razón: ${$json.escalation_reason}\n\nHistorial:\n${session.history_text}` }); // Notificar al cliente return [{ json: { text: "Te conecto con un asesor ahora mismo, espera un momento 🙏" }}]; } return [{ json: { text: agentResponse }}];
- Instala Evolution API en tu VPS con Docker. Escanea el QR para conectar WhatsApp.
- Configura el webhook de Evolution apuntando a tu n8n
- Crea el flujo básico: Webhook → Code (parse WA message) → AI Agent → HTTP (send response via Evolution)
- Envíate un mensaje de WhatsApp. ¿Responde el bot?
- Agrega el nodo Supabase para guardar el historial de la conversación
- Conecta Chatwoot a n8n via API (necesitas el API key y el inbox_id)
- Implementa el trigger de escalación: confianza < 0.6 OR "quiero hablar con persona" OR 3er intento fallido
- Cuando se escala, crea la conversación en Chatwoot con el historial formateado
- Envía al cliente el mensaje de transferencia + tiempo estimado de espera
- Verifica: el agente humano en Chatwoot ve el historial completo sin tener que preguntar nada al cliente
WhatsAppBot es la capa de entrada del FlowBot. En M6 se añade el flujo de calificación de leads. En M8, el agente de soporte responde desde este mismo canal.
El pipeline de ventas automatizado
Un lead entra por WhatsApp o formulario → el sistema califica automáticamente (BANT: Budget, Authority, Need, Timeline) → enriquece el perfil con información pública → agenda follow-up → actualiza el CRM. El vendedor solo toca los leads calificados.
- Calificación con LLM: el agente extrae BANT del texto de la conversación. Score 0-10. Si <5, nurturing automático. Si ≥5, asigna a vendedor.
- Lead enrichment: con el email o teléfono, busca información pública (LinkedIn, Google) usando HTTP Request nodes.
- CRM sync: n8n tiene nodos nativos para HubSpot, Pipedrive, Salesforce, y Twenty CRM (self-hosted). Un lead calificado se crea automáticamente con todas sus propiedades.
- Follow-up scheduler: si no hay respuesta en 24h, n8n envía un mensaje de seguimiento. Se detiene automáticamente cuando el lead responde.
SalesPipeline se alimenta del WhatsAppBot del M5. Cuando el clasificador detecta intent de compra, activa este flujo. El score del lead determina si va a automatización o a vendedor humano.
Contenido generado con aprobación humana — el patrón correcto
Publicar contenido generado por IA directamente sin revisión humana es el antipatrón más común y más costoso. El patrón correcto es: generación automática → revisión humana en 1 clic → publicación programada. n8n implementa esto nativamente con el nodo "Wait for Webhook" que pausa el flujo hasta recibir aprobación.
- Generación: a partir de brief, keywords o datos del producto → LLM genera variantes de post para Instagram, LinkedIn, WhatsApp.
- Revisión (HITL): n8n envía las variantes por email o Slack con botones Aprobar/Rechazar/Editar. El flujo espera (máx 24h).
- Publicación programada: al aprobar, n8n usa las APIs nativas de cada red social (o Buffer/Later como proxy) para publicar en el horario óptimo.
- Reciclado: posts con buen engagement se guardan como few-shot examples para mejorar la generación futura.
ContentEngine se dispara por cron (ej: lunes 9am, miércoles 9am, viernes 9am) o manualmente. El RAGPipeline del M4 le da contexto sobre los productos del cliente para generar contenido relevante.
Soporte automatizado que no frustra al cliente
El bot de soporte tiene que cumplir una regla simple: si puede resolver el problema en el primer intento, lo hace. Si no puede, escala rápido y con contexto. El 70% de las consultas de soporte en una PyME son repetitivas (estado de pedido, horarios, precios). Automatizar esas libera al equipo para los casos que sí necesitan atención humana.
- Clasificación de urgencia: el agente detecta si la consulta es crítica (producto defectuoso, pago no procesado) y escala inmediatamente sin intentar resolver.
- Resolución con RAG: para preguntas sobre productos, políticas o FAQ, el agente usa el knowledge base del M4 antes de responder.
- Creación automática de tickets: cualquier consulta que el bot no pueda resolver genera un ticket en el CRM con la categoría, prioridad y resumen del problema.
- CSAT automático: 30 minutos después de cerrar una conversación, el bot envía una pregunta de satisfacción (1-5). Los resultados se guardan para análisis.
SupportAgent integra el RAGPipeline del M4 y el WhatsAppBot del M5. Es el sistema más completo del proyecto — une todos los módulos anteriores en un flujo de atención real.
El sistema nunca debe romper en silencio
En producción, los flujos fallan. La API de WhatsApp se cae, Supabase tiene timeout, el LLM devuelve un rate limit. El trabajo del automatizador no es prevenir todos los fallos (imposible) — es asegurarse de que cuando fallan, el sistema responde con gracia y alerta a la persona correcta.
Las 4 técnicas de resiliencia para automatizadores
- Error Trigger node: captura cualquier error en el flujo, guarda el contexto completo en Supabase, y envía alerta por WhatsApp/Telegram al operador.
- Retry con backoff: el nodo HTTP Request de n8n tiene retry nativo. Configura 3 intentos con backoff exponencial (1s, 2s, 4s) para APIs inestables.
- Fallback estático: si el LLM falla después de 3 intentos, el flujo envía un mensaje pre-escrito al usuario y crea un ticket automáticamente.
- Circuit breaker manual: si una herramienta externa falla más de N veces en 1 hora, desactivar ese nodo automáticamente y notificar al operador antes de seguir causando errores.
// Error Trigger — nodo especial que captura fallos de cualquier flujo // Se configura como "Error Workflow" en los settings del flujo principal { "type": "n8n-nodes-base.errorTrigger", "name": "FlowBot Error Catcher" } // Al activarse, recibe: execution, workflowData, error // Nodo Code a continuación: const { execution, error } = $json; // 1. Log completo en Supabase para debugging const errorLog = { execution_id: execution.id, workflow_name: execution.workflowData.name, error_message: error.message, error_node: error.node, input_data: JSON.stringify(execution.data.resultData?.lastNodeExecuted), timestamp: new Date().toISOString() }; // → Supabase insert en tabla error_logs // 2. Alerta inmediata por WhatsApp al operador const alertMessage = `🚨 FlowBot Error Flujo: ${execution.workflowData.name} Error: ${error.message} Nodo: ${error.node} ID: ${execution.id}`; // → HTTP Request POST a Evolution API // 3. Si el error fue en conversación de usuario, enviar fallback const userPhone = execution.data?.startData?.destinationNode?.phone; if (userPhone) { // → Respuesta al usuario: "Lo siento, estamos teniendo problemas técnicos..." // → Crear ticket automático en CRM para dar seguimiento } return [{ json: { logged: true, alerted: true } }];
- En el flujo del AgentFlow del M3, añade un nodo Code que lanza un error con 30% de probabilidad
- Envía 10 mensajes de prueba. ¿Cuántos fallan? ¿Se activa el Error Trigger?
- Verifica que el error log quede en Supabase con el contexto completo
- Verifica que llegue la alerta de WhatsApp al operador con el detalle del error
- Verifica que el usuario reciba el mensaje de fallback (no un error 500 vacío)
- Crea una vista en Supabase: errores de las últimas 24h por flujo
- Crea una función Postgres que retorna el health score: (requests_exitosos / total) * 100
- Construye un flujo n8n de cron diario que envía el reporte de salud por WhatsApp al cliente
- Agrega una alerta automática: si error_rate > 5% en 1h, alerta inmediata
- Documenta qué errores son "normales" (rate limits transitorios) vs. críticos (API caída)
ResilienceLayer se conecta a todos los flujos anteriores como "Error Workflow". Es la capa de seguridad del sistema completo. Sin ella, un fallo silencioso puede dejar a 100 clientes sin respuesta durante horas.
De flujo local a sistema en producción para un cliente
El deploy no es solo subir el código. Es configurar el ambiente del cliente, documentar el sistema para que lo puedan operar sin ti, y establecer el modelo de precios para que la automatización sea rentable a largo plazo.
- Infraestructura mínima: VPS de $10/mes (Hetzner, Hostinger, DigitalOcean) + Docker Compose con n8n, Redis y Evolution API. Supabase puede ser el tier gratuito para empezar.
- Variables de entorno por cliente: nunca hardcodear API keys en los flujos. Usar el sistema de credenciales de n8n, separado por workspace por cliente.
- Documentación del sistema: cada flujo debe tener una nota interna en n8n explicando qué hace, qué puede fallar, y cómo reiniciarlo. El cliente o tú lo leerán en un incidente a las 2am.
- Modelo de precios: setup fee único ($500-$3000) + mantenimiento mensual ($100-$300/mes) + costo de LLM pass-through con margen (cobrar 2x el costo real de tokens).
Cronograma sugerido
Sistema multi-flujo end-to-end
Todos los entregables de los 10 módulos integrados en un sistema de automatización real: WhatsApp bot, ventas, contenido, soporte, resiliencia y deploy — listo para entregar a un cliente real.
- Clasificación de mensajes por intención
- RAG sobre catálogo y FAQ del negocio
- Calificación automática de leads (BANT)
- Generación de contenido con aprobación
- Follow-up automático de ventas
- WhatsApp via Evolution API
- Escalación a Chatwoot con historial
- CRM sync (HubSpot / Twenty / Pipedrive)
- Publicación multi-canal de contenido
- Alertas al operador via WhatsApp
- Error handling global con fallback
- Logs estructurados en Supabase
- Health monitoring con alertas
- Retry con backoff en todas las APIs
- Documentación operativa para cliente