Published on June 28, 2026
n8n + AI Agents in 2026: real workflows that survive production
Most n8n + AI agent tutorials die in week two. Build a Telegram lead bot and a lead-scoring digest with retries, error branches, and handoff. Copy-paste JSON.
You connect n8n to an LLM with the AI Agent node (@n8n/n8n-nodes-langchain.agent). A trigger hands it a message, you attach a chat model, a memory store, and one or more tools, and the node runs the tool-use loop for you. The whole bot fits on one canvas and imports as JSON.
The wiring is the easy part. Self-host n8n with Docker in five minutes, point the AI Agent node at a cheap model, give it a tool that writes to your CRM, and you have a Telegram bot that answers pre-sales questions and captures leads. A full qualifying chat costs a fraction of a cent on gpt-4o-mini.
The hard part is the second week. The model returns text the next node cannot parse. The CRM API times out. A customer sends something the demo never handled, and the workflow fails at 2 AM with nobody watching. Most n8n + AI content stops at the demo. This guide does the wiring, then spends more time on what keeps a workflow alive: retries, error branches, idempotency, a human-approval step, and alerting. Two real workflows below with copy-paste JSON, plus an honest section on when you should pick Make, Zapier, or plain Python instead.
Why most n8n + AI tutorials die in week two
You have seen the tweets. Build 47 agents with n8n and Claude, comment "agent" and I will DM you the template. Thousands of bookmarks, the workflow never touches a real customer. A practitioner on X put it plainly in May: every n8n AI Agent video has one flaw, they are built for content, not to be integrated into a business day to day.
A thread on r/AiAutomations from June 2026 says why. A year ago, connecting tools with n8n, Make, or Zapier felt impressive. Now it is the easy part. Clients do not buy the tool stack. They buy fewer mistakes and less manual drag. Another thread the same week put it even sharper: AI automation is not saturated. Weak automation is.
So this guide does the wiring, then assumes you want the thing to stay up. Every workflow below includes the parts the demo omits: retries when an API flakes, an error branch that alerts you on failure instead of dying silent, an idempotency guard so a retry does not double-charge a customer, and a human-approval step for the actions you do not want to automate blind.
Run n8n on your own server in five minutes
n8n is source-available under the Sustainable Use License, not open source in the OSI sense. Read that correctly: you can run it, change it, and self-host it for free, including for a paying client. The license only stops you from packaging n8n itself as a hosted product that competes with n8n Cloud. For almost everyone reading this, it behaves like free software.
The fastest way to try it is one container:
# Quick test — single container, data in a volume:
docker volume create n8n_data
docker run -d --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8nOpen http://localhost:5678 and you have the editor. That is enough to build everything in this guide. For anything real, run it with a database and an encryption key so executions survive a restart:
# docker-compose.yml — n8n + Postgres, behind your own reverse proxy (nginx / Caddy / Traefik)
services:
postgres:
image: postgres:16
restart: always
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: change-me
POSTGRES_DB: n8n
volumes:
- pg_data:/var/lib/postgresql/data
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
depends_on: [postgres]
ports:
- "5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: change-me
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
N8N_ENCRYPTION_KEY: replace-with-a-long-random-string
GENERIC_TIMEZONE: Europe/Berlin
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
pg_data:Set WEBHOOK_URL to your real https domain, or webhooks (Telegram, forms) will call the wrong address and your triggers will look broken for no obvious reason. I run this stack on a Hetzner CX22 with 4 GB of RAM for about €5 a month, Postgres included, and it serves dozens of executions an hour on a single core.
The AI Agent node, in one picture
Every n8n AI workflow is the same shape. A trigger fires. The AI Agent node receives the message. Three things attach to the agent from below: a model, a memory, and at least one tool. The agent decides what to do, calls tools as needed, and hands back a result.
- Trigger starts the run: Telegram, a chat widget, a webhook, a schedule.
- Agent is the brain. One of the LangChain node types n8n ships, like
@n8n/n8n-nodes-langchain.agent. You write a system prompt and set a max-iteration cap. - Model is the LLM. Drop in OpenAI, Anthropic, Google, or a local Ollama model. Same slot, swap the node.
- Memory is what the agent remembers between turns. Window Buffer Memory keeps the last N messages. Give each user their own session id, or everyone shares one brain.
- Tools are the actions. A tool is a node the agent can call: an HTTP request, your CRM, a calculator, a sub-workflow.
The agent does not run your code itself. It returns a tool call, n8n runs the tool, the result goes back, and the loop repeats until the agent answers or hits your cap. That is the same loop I build by hand in pure Python over here. n8n just draws it as boxes.
Build one: a Telegram lead bot that qualifies and replies
A working Telegram bot in one importable workflow. It answers pre-sales questions from memory, and when a visitor looks like a real lead it calls a tool that posts the lead to your CRM with the company name and the chat id.
Create a bot with @BotFather on Telegram, copy the token into an n8n Telegram credential, then import this JSON (paste it on the canvas, or use Import from URL/file):
{
"name": "Telegram lead bot",
"nodes": [
{
"parameters": { "updates": ["message"] },
"id": "a1f00000-0000-4000-8000-000000000001",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.1,
"position": [220, 300]
},
{
"parameters": {
"promptType": "define",
"text": "={{ $json.message.text }}",
"options": {
"systemMessage": "You are the pre-sales bot for Acme. Answer questions about pricing and features in under 3 sentences. If the visitor names a company and a real need, call the qualify tool with those details. Never invent prices."
}
},
"id": "a1f00000-0000-4000-8000-000000000002",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.7,
"position": [460, 300]
},
{
"parameters": {
"model": { "__rl": true, "mode": "list", "value": "gpt-4o-mini" },
"options": {}
},
"id": "a1f00000-0000-4000-8000-000000000003",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [340, 520]
},
{
"parameters": {
"sessionId": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
},
"id": "a1f00000-0000-4000-8000-000000000004",
"name": "Window Buffer Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [520, 520]
},
{
"parameters": {
"name": "qualify",
"description": "Call when a visitor is a qualified lead. Posts company, need, and Telegram chat id to the CRM.",
"method": "POST",
"url": "https://crm.example.com/api/leads",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"company\": \"{{ $fromAI('company', 'the visitor company name') }}\",\n \"need\": \"{{ $fromAI('need', 'what they want to buy') }}\",\n \"chat_id\": \"{{ $('Telegram Trigger').item.json.message.chat.id }}\"\n}"
},
"id": "a1f00000-0000-4000-8000-000000000005",
"name": "qualify (HTTP tool)",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"typeVersion": 1.1,
"position": [700, 520]
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
"text": "={{ $json.output }}",
"additionalFields": {}
},
"id": "a1f00000-0000-4000-8000-000000000006",
"name": "Telegram (reply)",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [720, 300]
}
],
"connections": {
"Telegram Trigger": {
"main": [[{ "node": "AI Agent", "type": "main", "index": 0 }]]
},
"AI Agent": {
"main": [[{ "node": "Telegram (reply)", "type": "main", "index": 0 }]]
},
"OpenAI Chat Model": {
"ai_languageModel": [[{ "node": "AI Agent", "type": "ai_languageModel", "index": 0 }]]
},
"Window Buffer Memory": {
"ai_memory": [[{ "node": "AI Agent", "type": "ai_memory", "index": 0 }]]
},
"qualify (HTTP tool)": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
}
},
"settings": { "executionOrder": "v1" }
}A few things are not obvious from the boxes. The memory node has a sessionId set to the Telegram chat id, so two customers talking at once keep separate histories. The tool uses n8n's $fromAI() expression to pull arguments the model chose out of its response and into the HTTP body. The reply node reads $json.output, which is where the agent puts its final text.
One line in that system prompt does most of the work: "If the visitor names a company and a real need, call the qualify tool." Without it the agent will chat forever and never capture anything.
Make it survive production
The bot above works on the happy path. Production is every other path. Five changes turn a demo into something you can leave running.
- Retry the flaky calls. Turn on Retry On Fail on any node that hits a network: the CRM tool, the Telegram reply, any HTTP request. Set three tries with a few seconds between them. Most transient failures (a 502, a rate limit) clear on the second attempt and never reach you.
- Add an error workflow. n8n ships an Error Trigger node. Point a workflow at it, and when any execution fails it fires with the full error context. Send that to a Telegram channel or Slack. Now you learn a job broke from your phone, not from an angry customer a week later.
- Guard against double-runs. Webhooks fire twice sometimes. Telegram retries a message it thinks you did not acknowledge. If your tool charges money or sends an email, idempotency is not optional. Store the incoming message id before you act, and skip it if you have seen it. A cheap pattern: write the id to a Postgres table with a unique constraint and let the duplicate error out.
- Put a human in the loop for irreversible actions. n8n's Wait node can pause a run and resume on a webhook. Use it for an approval step: the agent drafts a refund, the workflow waits, a person clicks approve in Slack, the run continues. Automate the draft, not the trigger pull.
- Watch it. n8n's executions list shows every run and its status. For a dashboard across many instances, projects like n8n-dashboard sync your workflows and score their health. Make a daily check on failed executions and you catch drift before it costs you.
Debugging tip from n8n's own team: run a tool node by itself, without the agent, to see its raw output. It saves tokens and tells you whether the tool or the model is the problem.
Build two: a lead-scoring digest on a schedule
Not every workflow needs a chat. This one runs on a schedule: every morning it pulls new rows from a Google Sheet, scores the leads with the AI Agent, and posts a ranked digest to a Telegram channel. The r/AiAutomations CRM thread from June runs exactly this pattern for a real-estate agent who was losing deals to slow follow-up.
{
"name": "Daily lead digest",
"nodes": [
{
"parameters": {
"rule": { "interval": [{ "field": "cronExpression", "expression": "0 9 * * *" }] }
},
"id": "b2f00000-0000-4000-8000-000000000001",
"name": "Every morning 9am",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [220, 300]
},
{
"parameters": {
"operation": "read",
"documentId": { "__rl": true, "value": "YOUR_SHEET_ID" }
},
"id": "b2f00000-0000-4000-8000-000000000002",
"name": "Read new leads",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [440, 300]
},
{
"parameters": {
"promptType": "define",
"text": "={{ JSON.stringify($json.all) }}",
"options": {
"systemMessage": "You are a lead-scoring analyst. Rank these leads by likelihood to close this quarter. Return a short digest: rank, company, one-line reason. Top 5 only."
}
},
"id": "b2f00000-0000-4000-8000-000000000003",
"name": "AI Agent (score)",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.7,
"position": [660, 300]
},
{
"parameters": {
"chatId": "@your-leads-channel",
"text": "={{ 'Daily lead digest\n\n' + $json.output }}",
"additionalFields": {}
},
"id": "b2f00000-0000-4000-8000-000000000004",
"name": "Post to channel",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [880, 300]
}
],
"connections": {
"Every morning 9am": { "main": [[{ "node": "Read new leads", "type": "main", "index": 0 }]] },
"Read new leads": { "main": [[{ "node": "AI Agent (score)", "type": "main", "index": 0 }]] },
"AI Agent (score)": { "main": [[{ "node": "Post to channel", "type": "main", "index": 0 }]] }
},
"settings": { "executionOrder": "v1" }
}The pattern to steal: deterministic trigger, AI in the middle to judge and enrich, deterministic action at the end. The model only decides the score. The sheet and the channel are ordinary nodes. To score each row individually instead of the whole sheet at once, drop a Split In Batches node between the read and the agent. Keep the model on a short leash and your workflow gets far less weird.
The numbers that actually matter
Running this costs less than you think, if you self-host.
| Self-host (Docker) | n8n Cloud Starter | Zapier | |
|---|---|---|---|
| Software license | Sustainable Use, $0 | included | included |
| Monthly cost | ~€5 VPS, unlimited | €24, ~2,500 executions | $20–100+, per task |
| Where data lives | your server | n8n's servers | Zapier's servers |
| Executions | unlimited | metered | metered per task |
| Can run a local model | yes | no | no |
The big number is executions. Zapier and n8n Cloud charge per run. Self-hosted does not. If your webhook fires 50,000 times a month, that gap pays for a lot of VPS.
The LLM is the other line item, and it is small. A qualifying chat is maybe 2,000 tokens in and out. At gpt-4o-mini's price that is well under one cent per conversation (check OpenAI's page for the current rate, it moves). For a bot doing hundreds of chats a day the model bill is a rounding error next to a single employee.
When n8n is the wrong tool (use Make, Zapier, or Python instead)
n8n is not always the answer, and pretending it is makes you less trustworthy, not more. Use it when you want visual orchestration, self-hosting, and AI in the same place. Use something else when:
- You hate visual builders. If boxes and wires slow you down, write the agent loop in Python or TypeScript. You give up the drag-and-drop integrations and get full control and a real debugger. (I wrote that loop in 60 lines here.)
- The client wants zero ops. n8n Cloud, Zapier, and Make host everything. The client pays a monthly bill and never SSHs into anything. For a non-technical small business that is the right trade.
- The workflow is two steps and never changes. A Google Form to a Google Sheet does not need n8n. Use the native integration.
- You need sub-second latency at high volume. n8n adds overhead per execution. A hand-written worker will be faster, and at tens of thousands of events a second n8n is the wrong shape.
The r/AiAutomations crowd had it right. Businesses do not care if it is n8n or Make or Python. They care that it saves time, stops mistakes, survives the edge case, and still works after you hand it over. Pick the tool that gets them that.
Four reasons your workflow breaks (and the fix)
- The agent loops until it burns your token budget. Cause: no max-iteration cap, or a tool that always errors so the agent retries forever. Fix: set
maxIterationson the agent (10 is plenty), and make tool errors return a message the agent can recover from instead of throwing. - Memory leaks across users. Cause: the memory node has no
sessionId, so every user writes into one conversation. Fix: setsessionIdto a per-user value like the Telegram chat id. - The webhook works in the editor and nowhere else. Cause:
WEBHOOK_URLpoints at localhost or http while you serve over https. Fix: setWEBHOOK_URLto the production https URL and the test URL in the node will match. - Retries double your side effects. Cause: Retry On Fail re-runs a node that sends an email or charges a card. Fix: idempotency on anything irreversible, before you enable retries.
What's next (and when to walk away)
You now have two workflows that do real work and the hardening to keep them running. The next move is to wire the lead bot to your actual CRM and let it run for a week. Watch the executions list. The failures tell you what to fix next.
If you want the agent loop without a GUI, I built the same pattern in pure Python. For running many agents in production, I wrote up the monitoring and alerting stack I use to keep them alive at 3 AM.
Sources
-
n8n Sustainable Use License — what the license permits and the uses it restricts (you can self-host and modify freely; you cannot rehost n8n as a competing paid platform). https://docs.n8n.io/privacy-and-security/sustainable-use-license
-
n8n Docs — Advanced AI / AI Agent node — the agent node and its model, memory, and tool attachment slots; the workflow JSON structure and connection types (
ai_languageModel,ai_memory,ai_tool) used throughout. https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/agent/ -
n8n Docs — Self-host with Docker — the docker-compose template,
WEBHOOK_URL,N8N_ENCRYPTION_KEY, and Postgres backend configuration. https://docs.n8n.io/hosting/installation/docker/ -
n8n pricing — Cloud tiers (Starter from €24 with ~2,500 executions, scaling toward €800 for high-volume plans), as of June 2026. Prices change; check the live page. https://n8n.io/pricing/ Retrieved June 28, 2026.
-
n8n Docs — Error handling — the Error Trigger node, Retry On Fail, and Continue On Fail used in the production-hardening section. https://docs.n8n.io/flow-logic/error-handling/
-
OpenAI pricing — gpt-4o-mini per-token rate, basis for the per-conversation cost estimate. https://platform.openai.com/docs/pricing Retrieved June 28, 2026.
I build and maintain n8n + AI automations for clients, on your server or mine. Start a project and I will keep the workflows alive after I hand them over.