AI Automation: automate real processes with AI
Automate real processes with AI, no data science degree required. Each module combines applied theory, annotated n8n flows and exercises grounded in a real business. When you finish, all the deliverables come together into an end-to-end automation system ready to hand over to a client.
- modules
- 10
- deliverables
- 10
- final project
- 1
- estimated duration
- ~8 wks
Final project · FlowBot: an automation agent for a small business
A complete automation system for a real business. End-to-end: WhatsApp bot, RAG over the catalog, automated sales pipeline, content generation, support with escalation and a metrics dashboard.
Architecture
| Layer | Components |
|---|---|
| Input | WhatsApp API · HTTP Webhook · Email / Form |
| Orchestration | n8n Workflows · AI Agent Node · Router Logic |
| Intelligence | Claude / GPT API · RAG (pgvector) · Tool Calling |
| Memory | Supabase DB · Redis Session · Vector Store |
| Output channels | WhatsApp/Telegram · Email/CRM · Social media |
| Observability | n8n Logs · Error alerts · Cost tracker |
What each module contributes
- M1 → StackSetup
- M2 → LLMWrapper
- M3 → AgentFlow
- M4 → RAGPipeline
- M5 → WhatsAppBot
- M6 → SalesPipeline
- M7 → ContentEngine
- M8 → SupportAgent
- M9 → ResilienceLayer
- M10 → ProductionDeploy
Suggested schedule
| Weeks | Phase | Modules |
|---|---|---|
| Weeks 1–2 | Foundations | Stack + LLMs |
| Weeks 3–4 | Architecture | Agents + RAG |
| Week 5 | Channels | WhatsApp + bots |
| Weeks 6–7 | Real use cases | Sales + Content + Support |
| Week 8 | Production | Resilience + Deploy |
Module 1 · Phase 1 · Foundations: the stack and LLMs as tools
The automator's stack
n8n, Make, APIs, webhooks — when to use what
Why n8n and not just Python?
80% of business automations don't need code. n8n lets you build complex flows with visual logic, connect 400+ services with one click, and deploy self-hosted without depending on a vendor. The automation developer doesn't replace the engineer — they have a market of their own: small businesses that need results today, not in six months.
n8n is like Lego Technic: the pieces are the nodes (HTTP, Supabase, OpenAI, Slack), and you decide how to put them together. Code only comes in where the Lego falls short — and with n8n, that limit is further away than it looks.
The most important architecture decision: n8n vs Make vs Zapier
- n8n (self-hosted): full control, no operation limits, JavaScript code in nodes, ideal for sensitive data or complex flows. Requires a VPS (~$5/month).
- Make (formerly Integromat): advanced visual builder, better for non-linear data flows, priced per operation. Good for clients who don't want to self-host.
- Zapier: the simplest, and the most expensive per operation. Only for simple 2–3 step integrations where setup speed matters more than cost.
Using Zapier for flows with more than 5 steps or more than 1,000 tasks/month. The cost spikes and debugging becomes impossible. Migrate to n8n before the client sees the bill.
Anatomy of an n8n flow in production
| Component | Description | When to use it |
|---|---|---|
| Trigger | Webhook, Cron, or an event from an external app | Always — every flow starts here |
| HTTP Request | A call to any REST API | When there's no native node |
| AI Agent | LLM with tools and native memory in n8n | Reasoning and dynamic decisions |
| Code (JS) | JavaScript for data transformation | Logic the nodes don't cover |
| If / Switch | Conditional routing of the flow | Multiple paths by input type |
| Error Trigger | Catches errors from the whole flow | Always in production flows |
n8n flow: stack-setup.json (n8n workflow)
{
"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"
}
}
]
}
Go deeper: n8n docs · Supabase quickstart · Anthropic pricing
Spin up your local stack in 30 minutes
Before you automate anything, you need a working environment. Without it, none of the following modules make sense.
- Install n8n locally with Docker:
docker run -it --rm --name n8n -p 5678:5678 n8nio/n8n - Create a Supabase account and set up an
automation_logstable with the fields: id, trace_id, message, response, channel, created_at - Get your Anthropic (or OpenAI) API key and set it up as a credential in n8n
- Build the base code flow: Webhook → Code (validation) → AI → Supabase → Respond
- Send it a POST with curl and check that the log lands in Supabase with the correct trace_id
Compare the cost of 1,000 requests
Before choosing a model, calculate how much it will cost in production.
- Write a ~300-word prompt (system + user) that represents your use case
- Use Anthropic's tokenizer to count input tokens and estimated output tokens
- Calculate the cost of 1,000 requests with Haiku vs Sonnet vs GPT-4o-mini
- How much does using Haiku for simple classifications save? Write down the number
- Decide which model each node in the project will use and justify it in a 1-page ADR
Module deliverable
Goes into the final project: The docker-compose.yml and the base flow are FlowBot's infrastructure layer. Every following module adds nodes to this base flow — none of them builds a new one from scratch.
Module 2 · Phase 1 · Foundations: the stack and LLMs as tools
LLMs as business tools
Prompts that work in production, with no surprises
The prompt is the contract with the model
In business automations, the LLM's output isn't read by a human — it's processed by the next node in the flow. That completely changes how you write a prompt. You're not looking for "a good answer", you're looking for parseable JSON, a boolean, or a category from an enum. Ambiguity in the prompt is a production bug.
The LLM in an n8n flow is like a function: predictable input → predictable output. If your prompt can produce two different formats, you have a bug. Always specify the exact output format and validate it before passing it to the next node.
Prompt structure for automations (4 sections)
- ROLE + TASK: who the model is and exactly what it must do. No ambiguity.
- DYNAMIC CONTEXT: variables that change per request (user data, history, catalog). Injected at runtime.
- CONSTRAINTS: what it can NOT do. Just as important as what it can do.
- OUTPUT FORMAT: the exact format of the response. For flows: always valid JSON with an explicit schema.
Structured output — the most important technique for n8n
| Technique | When to use it | Risk |
|---|---|---|
| Plain JSON | Classification, data extraction, routing | The model may add text before the JSON |
| XML tags (<output>) | When you need to separate reasoning from the answer | You have to parse the XML |
| Structured Outputs API | Claude/OpenAI support native JSON schema | Only works with certain models |
| Few-shot + format | When the format is complex and the model fails | Adds tokens and cost |
n8n flow: llm-wrapper.json (n8n workflow)
// 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) }];
Go deeper: Anthropic tool use · JSON schema validation · n8n Code node
Build an intent classifier
The classifier is the most critical node of any bot. If it fails here, the whole flow takes the wrong path.
- Write the classification prompt with 5 categories for your use case (e.g. sales, support, pricing, location, other)
- Test it with 20 varied messages — how many does it get the intent right on?
- Find the 3 cases where it fails. Is it a prompt problem or a model problem?
- Add few-shot examples for the failing cases. Does it improve?
- Implement the wrapper with retry and fallback. Check that it never breaks the flow, even when the JSON is invalid.
Extract structured data from natural language
Turning free text into structured data is the most valuable use case for an LLM in automations.
- Take 10 real (or simulated) order emails from a hypothetical client
- Write a prompt that extracts: name, product, quantity, required date, urgency (high/medium/low)
- Check that the JSON output is parseable in all 10 cases
- Add a "Validate & Store" node in n8n that saves the extracted object to Supabase
- What happens if the email mixes Spanish and English? Does it still work?
Module deliverable
Goes into the final project: The LLMWrapper is FlowBot's first intelligent node. In M3 it will be extended to support Tool Calling. In M8, the classifier will decide which agent each conversation is routed to.
Module 3 · Phase 2 · Architecture: agents, RAG and channels
Agents in n8n
AI Agent node, tool calling, memory and controlled loops
What is n8n's AI Agent node?
n8n's AI Agent node natively implements the ReAct pattern (Reason + Act) without any Python code. The agent can use tools (other n8n nodes), keep memory across turns, and decide when it has enough information to answer. The difference from a plain LLM node is that the agent can take multiple steps before answering.
A plain LLM node is like asking someone for an answer without letting them look anything up. The AI Agent is like giving them access to Google, a calculator, and your database — they can look things up before answering. The magic is that it decides on its own when to search and when it already knows enough.
Tools available in n8n for the AI Agent
- HTTP Request Tool: any external API. The agent decides when to call it and with which parameters.
- Supabase Tool: database reads and writes. The agent can look up customer information without you doing it explicitly.
- Vector Store Tool: semantic search over documents. The basis of the RAG pattern.
- Code Tool: executable JavaScript. For calculations or transformations the LLM would get wrong.
- Think Tool: lets the agent reason out loud before acting. Improves quality in complex cases.
The most critical risk: infinite loops
Without the right configuration, an agent can call the same tool in a loop if the output doesn't meet its internal criteria. n8n doesn't prevent this by default.
Setting up the AI Agent without an iteration limit (maxIterations) in production. A 50-iteration loop with Claude Sonnet costs ~$1.50 per conversation. With 1,000 users, that's $1,500 in a day. Always set maxIterations between 5 and 10.
n8n flow: agent-flow.json (AI Agent node configuration)
// 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"
}
]
}
}
Go deeper: n8n AI Agent docs · ReAct paper · Anthropic tool calling
Build the ReAct loop visually in n8n
Before using the AI Agent node, understand the pattern by building it by hand so you can see every step.
- Create a manual flow: Webhook → Code (parse intent) → If (needs a tool?) → HTTP Tool → Code (format response)
- Test it with: "how much does product X cost?" — the flow should search the catalog
- Test it with: "hi, good afternoon" — the flow should answer directly without searching
- Now replace all that logic with the AI Agent node. Is it simpler? What control did you lose?
- Force the loop: make the tool always return an error. Does maxIterations kick in?
Measure the cost impact of maxIterations
Understand empirically how much each extra iteration costs.
- Set the agent to maxIterations=10 and record the cost of 20 varied conversations
- How many conversations used more than 5 iterations? How much did they cost on average?
- Change it to maxIterations=5. Which conversations no longer get resolved correctly?
- Document the optimal balance for your specific use case
- Implement a fallback: if maxIterations is reached, escalate to a human automatically
Module deliverable
Goes into the final project: The AgentFlow is the core of FlowBot. In M4 it will connect to the RAGPipeline as a tool. In M5 it will receive messages from WhatsApp. In M8 it will be specialized by conversation type.
Module 4 · Phase 2 · Architecture: agents, RAG and channels
No-code RAG — the business's knowledge
Supabase pgvector, embeddings and real retrieval in n8n
RAG in business terms
RAG (Retrieval-Augmented Generation) is the technique that lets the bot answer questions using your client's specific knowledge — catalog, FAQs, policies — without any fine-tuning. The flow is simple: the user asks a question → the system finds the most relevant documents → the LLM answers using those documents as context.
Imagine handing the LLM a box of notes with the business's information. Before answering, the LLM looks through the box for the notes that are relevant to the question, reads them, and answers based on them. You control what goes into the box — that's RAG.
The 4 steps of the RAG pipeline in n8n
- Ingestion (offline): document → split into chunks (400-600 tokens) → embedding (OpenAI or Anthropic) → store in Supabase pgvector with metadata.
- Retrieval (online): user query → embedding → cosine similarity search → top-5 most relevant chunks.
- Augmentation: retrieved chunks → injected as context into the agent's prompt with the instruction "Use only this information to answer".
- Citation check: is the LLM's answer backed by the chunks? If there are no relevant chunks, the agent must admit it instead of hallucinating.
Chunks that are too small (<200 tokens) or too large (>1200 tokens). Small ones lose context. Large ones add noise that confuses the LLM. The sweet spot for product catalogs and FAQs is 400–600 tokens with 10% overlap.
n8n flow: rag-pipeline.sql + n8n workflow
-- 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)
}}];
Go deeper: pgvector docs · n8n Vector Store node · OpenAI embeddings
Index a real client's catalog
RAG quality depends 80% on how you index the documents, not on the LLM.
- Take 20-30 products from a real catalog (or make one up) — name, description, price, category
- Design the chunking strategy: one chunk per product? Per category? Justify it
- Build the ingestion flow in n8n: CSV/Sheet → Code (format) → OpenAI Embeddings → Supabase upsert
- Run 10 questions about the catalog. Does retrieval return the right products?
- Tune match_threshold until irrelevant questions return 0 chunks
Connect RAG to the AI Agent as a tool
The real power of RAG shows when the agent decides when to search — not when you force it on every request.
- Set up the "Vector Store Tool" node in the AI Agent pointing to your knowledge_base table
- Test: "What's the price of product X?" — does the agent call the tool or answer from memory?
- Test: "hi, how are you?" — does the agent avoid calling the tool unnecessarily?
- Add the instruction "If you can't find the information in the catalog, say so" to the system prompt
- Check: ask about something that is NOT in the catalog. Does the agent hallucinate or admit it doesn't know?
Module deliverable
Goes into the final project: The RAGPipeline turns the client's catalog into searchable memory. In M6 (sales), the agent will use it to recommend products. In M8 (support), to answer questions about policies and FAQs.
Module 5 · Phase 3 · Production: channels, business cases and resilience
WhatsApp & messaging channels
Evolution API, Chatwoot, Telegram — bots that do real things
WhatsApp as the main channel in Latin America
In Latin America, WhatsApp is the default communication channel for small businesses. 90%+ of customers would rather solve problems over WhatsApp than by email or a web form. A WhatsApp bot that works well delivers immediate, visible ROI: the business owner sees it in the drop in messages they have to answer by hand.
Evolution API uses the WhatsApp Web session (unofficial, free, easier to implement). Meta's official API requires business verification and charges per message. For testing and small clients: Evolution. For scale and regulatory compliance: the official API.
The 3 states of a WhatsApp conversation
- Automated: the bot handles everything. Applies to the 70% of repetitive questions (price, hours, order status).
- Assisted (HITL): the bot proposes, a human approves before sending. For quotes or order changes.
- Escalated: the bot detects it can't resolve the issue and hands off to a human in Chatwoot. For complaints or complex cases.
Escalating to a human without context. The customer doesn't want to repeat their problem. The escalation flow must include: the full conversation history, the problem's classification, and what the bot already tried. Chatwoot receives all of this via n8n before the human agent is notified.
n8n flow: whatsapp-flow.json (Evolution API → n8n → Chatwoot)
// 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 }}];
Go deeper: Evolution API docs · Chatwoot API · n8n WhatsApp node
Get a WhatsApp bot running in 60 minutes
The goal is a working end-to-end bot, even a simple one. The first bot that works in production is the most important one.
- Install Evolution API on your VPS with Docker. Scan the QR code to connect WhatsApp.
- Point the Evolution webhook at your n8n
- Build the basic flow: Webhook → Code (parse WA message) → AI Agent → HTTP (send response via Evolution)
- Send yourself a WhatsApp message. Does the bot reply?
- Add the Supabase node to save the conversation history
Implement escalation to Chatwoot with context
Escalation without context frustrates the human agent as much as the customer. This exercise makes sure the handoff is smooth.
- Connect Chatwoot to n8n via the API (you need the API key and the inbox_id)
- Implement the escalation trigger: confidence < 0.6 OR "I want to talk to a person" OR 3rd failed attempt
- When escalating, create the conversation in Chatwoot with the formatted history
- Send the customer the handoff message + estimated wait time
- Check: the human agent in Chatwoot sees the full history without having to ask the customer anything
Module deliverable
Goes into the final project: The WhatsAppBot is FlowBot's input layer. M6 adds the lead qualification flow. In M8, the support agent answers from this same channel.
Module 6 · Phase 3 · Production: channels, business cases and resilience
Automated sales pipeline
Lead enrichment, outreach, CRM sync and automatic follow-up
The automated sales pipeline
A lead comes in through WhatsApp or a form → the system qualifies it automatically (BANT: Budget, Authority, Need, Timeline) → enriches the profile with public information → schedules a follow-up → updates the CRM. The salesperson only touches qualified leads.
- Qualification with an LLM: the agent extracts BANT from the conversation text. Score 0-10. If <5, automatic nurturing. If ≥5, assigned to a salesperson.
- Lead enrichment: with the email or phone number, it looks up public information (LinkedIn, Google) using HTTP Request nodes.
- CRM sync: n8n has native nodes for HubSpot, Pipedrive, Salesforce, and Twenty CRM (self-hosted). A qualified lead is created automatically with all its properties.
- Follow-up scheduler: if there's no reply within 24h, n8n sends a follow-up message. It stops automatically when the lead replies.
In Brazil (LGPD) and Europe (GDPR), automating outreach messages without explicit consent is illegal. Always include an opt-in in the first message and store the consent timestamp in Supabase. The flow must have a "check_consent" node before any automated message.
Module deliverable
Goes into the final project: The SalesPipeline is fed by the WhatsAppBot from M5. When the classifier detects purchase intent, it triggers this flow. The lead score decides whether it goes to automation or to a human salesperson.
Module 7 · Phase 3 · Production: channels, business cases and resilience
Automated content engine
Generation pipelines, human approval and multi-channel publishing
Generated content with human approval — the right pattern
Publishing AI-generated content directly without human review is the most common and most expensive anti-pattern. The right pattern is: automatic generation → 1-click human review → scheduled publishing. n8n implements this natively with the "Wait for Webhook" node, which pauses the flow until approval comes in.
- Generation: from a brief, keywords or product data → the LLM generates post variants for Instagram, LinkedIn, WhatsApp.
- Review (HITL): n8n sends the variants by email or Slack with Approve/Reject/Edit buttons. The flow waits (max 24h).
- Scheduled publishing: on approval, n8n uses each social network's native APIs (or Buffer/Later as a proxy) to publish at the optimal time.
- Recycling: posts with good engagement are saved as few-shot examples to improve future generation.
Module deliverable
Goes into the final project: The ContentEngine is triggered by cron (e.g. Monday 9am, Wednesday 9am, Friday 9am) or manually. The RAGPipeline from M4 gives it context about the client's products so it generates relevant content.
Module 8 · Phase 3 · Production: channels, business cases and resilience
Specialized support agent
Classification, response, escalation and tickets — a real flow
Automated support that doesn't frustrate the customer
The support bot has to follow one simple rule: if it can solve the problem on the first try, it does. If it can't, it escalates fast and with context. 70% of support questions at a small business are repetitive (order status, hours, prices). Automating those frees the team for the cases that really need human attention.
- Urgency classification: the agent detects whether the request is critical (defective product, payment not processed) and escalates immediately without trying to solve it.
- Resolution with RAG: for questions about products, policies or FAQs, the agent uses the knowledge base from M4 before answering.
- Automatic ticket creation: any request the bot can't resolve creates a ticket in the CRM with the category, priority and a summary of the problem.
- Automatic CSAT: 30 minutes after a conversation is closed, the bot sends a satisfaction question (1-5). The results are stored for analysis.
Module deliverable
Goes into the final project: The SupportAgent brings together the RAGPipeline from M4 and the WhatsAppBot from M5. It's the most complete system in the project — it joins all the previous modules into a real customer service flow.
Module 9 · Phase 4 · Resilience and deploy: it doesn't break on its own and the client can run it
Resilience — when things fail
Logs, alerts, retry, circuit breaker and real error handling
The system must never fail silently
In production, flows fail. The WhatsApp API goes down, Supabase times out, the LLM returns a rate limit. The automator's job isn't to prevent every failure (impossible) — it's to make sure that when things fail, the system responds gracefully and alerts the right person.
Every production flow has exactly 3 layers: (1) Happy path — works fine 95% of the time. (2) Retry — automatically tries again on transient failures. (3) Fallback — if everything fails, the system responds with something useful and alerts the operator. Without layer 3, it isn't ready for production.
The 4 resilience techniques for automators
- Error Trigger node: catches any error in the flow, saves the full context in Supabase, and sends an alert to the operator via WhatsApp/Telegram.
- Retry with backoff: n8n's HTTP Request node has built-in retry. Set 3 attempts with exponential backoff (1s, 2s, 4s) for unstable APIs.
- Static fallback: if the LLM fails after 3 attempts, the flow sends the user a pre-written message and creates a ticket automatically.
- Manual circuit breaker: if an external tool fails more than N times in 1 hour, disable that node automatically and notify the operator before it causes more errors.
n8n flow: resilience-layer.json (Error Trigger + fallback)
// 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 } }];
Go deeper: n8n Error workflows · Supabase functions
Force a failure and check the response chain
The only way to know whether your resilience system works is to break the flow on purpose.
- In the AgentFlow from M3, add a Code node that throws an error 30% of the time
- Send 10 test messages. How many fail? Does the Error Trigger fire?
- Check that the error log lands in Supabase with the full context
- Check that the WhatsApp alert reaches the operator with the error details
- Check that the user gets the fallback message (not an empty 500 error)
Build the error dashboard in Supabase
A simple monitoring system the client can see without needing access to n8n.
- Create a view in Supabase: errors from the last 24h per flow
- Create a Postgres function that returns the health score: (successful_requests / total) * 100
- Build a daily cron flow in n8n that sends the health report to the client via WhatsApp
- Add an automatic alert: if error_rate > 5% within 1h, alert immediately
- Document which errors are "normal" (transient rate limits) vs. critical (API down)
Module deliverable
Goes into the final project: The ResilienceLayer connects to all the previous flows as their "Error Workflow". It's the safety layer of the whole system. Without it, a silent failure can leave 100 customers without a reply for hours.
Module 10 · Phase 4 · Resilience and deploy: it doesn't break on its own and the client can run it
Deploy and monetization
Self-host on a VPS, deliver to clients and charge for automation
From a local flow to a production system for a client
Deploying isn't just uploading the code. It's setting up the client's environment, documenting the system so they can run it without you, and defining the pricing model so the automation stays profitable over the long run.
- Minimum infrastructure: a $10/month VPS (Hetzner, Hostinger, DigitalOcean) + Docker Compose with n8n, Redis and Evolution API. Supabase can start on the free tier.
- Per-client environment variables: never hardcode API keys in the flows. Use n8n's credentials system, separated by workspace per client.
- System documentation: every flow should have an internal note in n8n explaining what it does, what can fail, and how to restart it. The client or you will read it during an incident at 2am.
- Pricing model: one-time setup fee ($500-$3000) + monthly maintenance ($100-$300/month) + LLM cost passed through with a margin (charge 2x the real token cost).
Handing over the system with no documentation and no monthly maintenance. Three months later, the client calls you because "it stopped working" — and since there's no documentation and no support contract, you have to fix it for free. Monthly maintenance is where the real profitability of the business lies.
Go deeper: n8n self-host docs · Docker Compose reference · Hetzner VPS pricing
Module deliverable
Goes into the final project: This module adds no new logic — it packages all the previous deliverables into something you can hand over. The final project starts here: take the complete FlowBot, deploy it on a real VPS, and document it so the client can run it.
Final project
Final project: FlowBot, an end-to-end multi-flow system
FlowBot: an automation system for a small business. An end-to-end multi-flow system: all the deliverables from the 10 modules integrated into a real automation system (WhatsApp bot, sales, content, support, resilience and deploy), ready to hand over to a real client.
Automation
- Message classification by intent
- RAG over the business's catalog and FAQ
- Automatic lead qualification (BANT)
- Content generation with approval
- Automatic sales follow-up
Channels and integrations
- WhatsApp via Evolution API
- Escalation to Chatwoot with history
- CRM sync (HubSpot / Twenty / Pipedrive)
- Multi-channel content publishing
- Operator alerts via WhatsApp
Resilience and operations
- Global error handling with fallback
- Structured logs in Supabase
- Health monitoring with alerts
- Retry with backoff on every API
- Operations documentation for the client
Passing criteria
| Criterion |
|---|
Your progress is saved in this browser.