AI agent on WhatsApp with n8n: a complete step-by-step guide
To build an AI agent on WhatsApp with n8n, use a Webhook node to receive the message, a Code node to normalize and filter, the AI Agent node with per-contact memory and an HTTP Request node calling POST /send/text to reply. The community package n8n-nodes-zapzap (version 0.1.3 on npm on 10/27/2026) is an alternative to HTTP Request, but it only runs on self-hosted n8n. The whole flow is below.
Published on · 7 min read
How the flow works end to end
The design has six nodes. Webhook (trigger) receives the instance's messages event. A Code node extracts number, text and id and drops your own messages. An IF or the Code node itself cuts duplicates and conversations already with a human. The AI Agent node takes the text, uses that contact's memory and, if needed, calls tools. Finally, an HTTP Request (or the community node) sends the reply through send/text.
Before building, understand what n8n delivers and what it does not: it orchestrates, but the AI model belongs to the provider you set in the node's credential, and that provider's cost is separate. The n8n integration page and the guide to integrating WhatsApp with n8n cover the basics; here the focus is the agent.
What you need before starting
A ZapZap instance connected by QR code, the API key and secret, an n8n reachable from the internet (self-hosted with HTTPS or n8n Cloud) and a credential for an AI model provider. For local tests, n8n needs a public URL; a tunnel works for development, not for production.
In n8n, create a Header Auth credential or use fixed header fields for x-api-key and x-api-secret. That way the secret lives in the credential, not written into every node. If you prefer to start from something ready, there are templates in n8n templates for WhatsApp.
Step 1: receive the message with the Webhook node
Add a Webhook node, POST method, and copy the Production URL (the test URL only works while the flow is listening). Register that URL on the instance with POST /webhook, enabling the messages event. Activate the flow before using the production URL.
Test with POST /instances/{id}/webhook/test: it fires a test event and returns your endpoint's HTTP status and response time. If something fails, GET /instances/{id}/webhook/deliveries shows the latest deliveries and GET /webhook/errors the failures.
cURL (registrar o webhook do n8n)
curl -X POST https://api.zapzapapi.com/api/v1/SEU_INSTANCE_ID/webhook \
-H "Content-Type: application/json" \
-H "x-api-key: SUA_API_KEY" \
-H "x-api-secret: SEU_API_SECRET" \
-d '{"url":"https://SEU-N8N.com/webhook/whatsapp-agente","enabled":true,"events":["messages"]}'Step 2: normalize and filter with a Code node
This is the node that prevents the three most common bugs: the agent replying to its own message (fromMe), replying twice to the same event and replying in groups by accident. Check the exact event structure in the Webhook's execution tab with a real message; the code reads defensively and you adjust the names.
The node returns one item with numero, texto and id. If the message should not be handled, it returns an empty list, which ends the flow on that branch. Deduplication uses the workflow's static storage, enough for a single n8n; with several n8n instances, use a database or Redis.
n8n (nó Code, JavaScript)
const evento = $input.first().json.body ?? $input.first().json;
const msg = evento.message ?? evento.data ?? evento;
if (msg.fromMe) return [];
const id = msg.messageid ?? msg.id;
const numero = msg.sender ?? msg.from;
const texto = msg.text ?? msg.body ?? "";
const grupo = String(msg.chatid ?? msg.chatId ?? "").endsWith("@g.us");
if (!numero || !texto || grupo) return [];
const estado = $getWorkflowStaticData("global");
estado.vistos = estado.vistos ?? [];
if (id && estado.vistos.includes(id)) return [];
if (id) estado.vistos = [...estado.vistos.slice(-500), id];
return [{ json: { numero: String(numero).replace(/\D/g, ""), texto, id } }];Step 3: configure the AI Agent node with per-contact memory
Add the AI Agent node. Configure three things. Chat model: pick the provider and model in the credential (the model name lives in your configuration, not in this guide). Memory: use a window memory with the session key equal to the contact's number, so each customer has their own conversation. System prompt: role, tone, limits and the rule for handing off to a human.
A working system prompt, in a few lines: who the assistant is and which company it is for; reply in short messages, in a WhatsApp tone; use only the information provided; if you do not know or the customer asks for a person, reply with exactly the agreed handoff sentence. That fixed sentence lets the flow detect the handoff right after, with an IF node.
If the agent needs to look up data (schedule, order, stock), add tools: an HTTP Request as a tool pointing to your system, with a clear description of what it does. Keep tools few and well described; models make more mistakes when they have many options.
Step 4: send the reply through the API
After the agent, add an HTTP Request. Method POST; URL https://api.zapzapapi.com/api/v1/YOUR_INSTANCE_ID/send/text; headers x-api-key and x-api-secret; JSON body with number and text. The text field comes from the agent's output, and number comes from the Code node.
The delay field on send/text and the typing presence (message/presence) make the reply feel more natural, and a small delay keeps it from looking like a machine. Use them moderately: what weighs most for the number is overall behavior, not a sending trick.
n8n (HTTP Request, corpo JSON)
{
"number": "{{ $('Normalizar').item.json.numero }}",
"text": "{{ $json.output }}",
"delay": 2000
}cURL equivalente
curl -X POST https://api.zapzapapi.com/api/v1/SEU_INSTANCE_ID/send/text \
-H "Content-Type: application/json" \
-H "x-api-key: SUA_API_KEY" \
-H "x-api-secret: SEU_API_SECRET" \
-d '{"number":"5511999999999","text":"Resposta do agente","delay":2000}'Using the n8n-nodes-zapzap package instead of HTTP Request
There is a community node package, n8n-nodes-zapzap, published on npm (version 0.1.3 checked on 10/27/2026), covering message and media sending, polls, buttons and lists, reactions, instance management and real-time event reception. It simplifies setup because the node already knows the fields.
One important limit: according to n8n's documentation (read on 10/27/2026), unverified community nodes are not available on n8n Cloud and require self-hosted n8n. Since this is a community package and we do not have n8n's verified badge, the guaranteed path on n8n Cloud is HTTP Request. Both work with the same API and the same credentials.
Instalação (n8n self-hosted)
n8n-nodes-zapzapStep 5: detect the human handoff and pause the agent
After the agent, an IF node checks whether the reply is the handoff sentence. If it is, the flow marks the contact as with a human (in an n8n table, Redis or your CRM), notifies the team and sends the customer a short message. Before the agent, another IF checks that mark and ends the flow if the contact is with a human.
The mark needs an expiry or a release button, otherwise the contact never goes back to the bot. The same design appears in the guide to the WhatsApp AI chatbot, with handoff rules and cost.
Common errors and how to fix them
| Symptom | Likely cause | Fix |
|---|---|---|
| The flow does not fire | Webhook in test mode or flow inactive | Activate the flow and use the Production URL |
| The agent replies twice | Duplicate event | Deduplicate by message id |
| The bot talks to itself in a loop | fromMe messages not filtered | Drop fromMe in the Code node |
| All customers share one conversation | Fixed memory session key | Use the contact's number as the key |
| Error 401 or 403 on send | Wrong authentication headers | Check x-api-key and x-api-secret |
| Reply arrives but out of context | Generic prompt or no material | Strengthen the prompt and provide company content |
For day to day, keep n8n's execution history on for the first few days, review sample conversations and tune the prompt. To see all the API features the agent can use as a tool, open the reference and the OpenAPI file.
Quick summary
- The flow is Webhook, Code node (filter), AI Agent with per-contact memory and HTTP Request to /send/text.
- Filter fromMe, groups and duplicate events before the agent, or it replies to itself.
- Use the contact's number as the memory session key to keep conversations separate.
- The n8n-nodes-zapzap package (0.1.3 on npm on 10/27/2026) only runs on self-hosted n8n; on n8n Cloud use HTTP Request.
- Combine a fixed handoff sentence with an IF to pause the agent when a human takes over.
Keep reading
Also read
Frequently asked questions
How do I connect WhatsApp to an AI agent in n8n?
Register a Webhook node's Production URL as the instance webhook (POST /webhook, messages event), handle the message with a Code node, pass the text to the AI Agent node with per-contact memory and send the reply with an HTTP Request to /send/text.
Does the n8n-nodes-zapzap node work on n8n Cloud?
Not in practice. Per n8n's documentation, unverified community nodes require self-hosted n8n, and this package is a community one without n8n's verified badge. On n8n Cloud, use the HTTP Request node with the same authentication headers.
How do I stop the agent from replying to itself?
Drop, in the first node, events where fromMe is true and deduplicate by message id. Without that filter, the reply the agent sent comes back as an event and the flow loops.
Which AI model should I use in the AI Agent node?
Any model n8n supports and you have a credential for. The choice depends on cost, speed and quality in your case. Test with a few dozen real conversations before deciding, and use a smaller model for simple questions.
Can the agent look things up in my system?
Yes. Add tools to the AI Agent node, such as an HTTP Request pointing to your API, with a clear description of what the tool does. Keep tools few and limit what each can change.
Connect an AI agent to your WhatsApp
Create your account, verify your phone and get the welcome credit, no deposit needed (one per phone, subject to the current campaign). Connect by QR code, register the n8n webhook and test.
