← Case studies

Production AI agent · n8n

How I built a WhatsApp ordering agent in n8n

By Kushal Sapkota · Panauti, Nepal ·

I'm Kushal Sapkota, a Django developer and AI-automation engineer from Panauti, Nepal, and the founder of Affaiai. This is how I built an AI ordering agent in n8n for a cake shop, a client project that has been running in production, and what I learned shipping it.

The problem

The shop takes orders on WhatsApp and through its website chat. Customers write in Nepali, Roman Nepali and English, often in the same message. Orders arrive as text, voice notes, photos and payment screenshots. The owner is not technical and needs to change the bot's behaviour without calling me. And because money is involved, the AI must never decide that something has been paid. Failures have to be loud, not silent.

98workflow nodes
5n8n workflows
2channels
3languages

The architecture: one message, seven stages

Channels   WhatsApp (360dialog API) · website chat
Ingest     webhook · dedupe · voice-to-text · image fetch
Gate       chat paused for staff? · owner settings · debounce
Agent      LLM · memory · 5 SQL tools · structured output
Guards     feature flags · items valid? · date valid? · fee calculation (code)
Actions    reply + photos · payment QR · save order · Telegram alert
State      PostgreSQL · admin panel · shared inbox
The n8n canvas of the ordering agent, organised into colour-coded sections from message intake to saving the order
The real n8n canvas, tidied into colour-coded sections.

The decisions that mattered

  1. The model proposes. Code decides. The owner's feature switches are re-checked in code after the model answers, so "off" really means off. Totals and delivery fees are computed in SQL, never by the model.
  2. Structured output, not free text. The agent returns one reply for the customer plus machine-readable fields. A parser fixes the shape before anything downstream runs, and the agent never writes to the database itself.
  3. Tools instead of memorised facts. Five SQL tools (cakes, occasions, delivery zones, time slots, payment methods) mean a price changed in the admin panel is used on the very next message.
  4. Reading payment proofs, carefully. A vision model reads the paid amount, and a backup model tries if the first cannot. The result only flags the order for the owner to confirm. The AI cannot mark an order as paid.
  5. Behaviour as data. The owner flips switches, edits FAQs and adds holiday notices in an admin panel, and a Postgres function composes them into the prompt.
  6. Humans stay in the loop. One inbox holds WhatsApp and website chats. A staff reply pauses the bot for that customer, and the owner is alerted on Telegram when it needs help.
  7. Test on a copy, never the live shop. Tests run on a copy of the workflow with every send node disabled and fake phone numbers, and each deploy is diffed node by node.

What broke in production

A prompt is a request, not a security boundary. Anything that must be true, such as "never mark an order paid", belongs in code that runs after the model.

Tools used

n8n, PostgreSQL, OpenRouter (language and vision models), the 360dialog WhatsApp API, Telegram for owner alerts, and Docker.

See more

The full case study, with the architecture and more screens, is on my portfolio: kushal.aafaiai.com/#case. I'm also on GitHub and LinkedIn.