Building an AI assistant for WhatsApp, end to end: what it takes beyond the demo
A demo that answers a WhatsApp message with an AI takes an afternoon. An assistant a hospitality business can trust with its guests takes more: it has to answer only what it knows, act in your systems without surprises, admit when it doesn't know, and get better from your team's replies. This is how I built StillAnswer, the assistant that runs for a surf school and hostel, and the lessons that shaped it.
11 min read
1. The real problem: the same questions, all day
In hospitality most messages are the same twenty questions: when is check-in, is there parking, can I add a lesson, what does the board rental cost. Staff answer them between check-ins and surf lessons, often late, often in a language they half speak. Guests on WhatsApp expect an answer now.
So the goal is not a chatbot that can talk about anything. It is an assistant that answers the questions your team has already answered well, in the guest's language, at any hour, and quietly hands the rest to a person. That framing decides every design choice below.
2. The channel: a business number through a provider
The assistant talks to guests through the WhatsApp Business Platform, which you reach through a provider such as Twilio or Azure Communication Services. Two platform rules shape the whole design. When a guest writes, a customer service window of 24 hours opens in which you may reply freely. Outside that window you may only send pre-approved message templates, for example a booking reminder.
So the assistant must know which mode it is in. Inside the window it answers in free text; outside it, it sends a template or leaves the follow-up to your team. Plan the templates early: they need approval, and approval takes time you don't want to spend in launch week.
3. The webhook: check, acknowledge, bundle
Every message arrives as a webhook. The first thing it does is check the provider's signature; with Twilio that is the X-Twilio-Signature header, an HMAC over the URL and parameters with your auth token. Anything without a valid signature is dropped, because otherwise anyone who finds the URL can talk to your agent and your tools.
Then acknowledge fast and do the work asynchronously, and make processing idempotent by message id, because providers retry. One lesson from production: guests write in bursts. "Hi" — "we are 3" — "can we come Friday?" arrive within seconds. A short pause that bundles those messages into one question gives a much better answer than three answers to three fragments.
import twilio from "twilio";
export async function onMessage(req: Request) {
const params = Object.fromEntries(new URLSearchParams(await req.text()));
const valid = twilio.validateRequest(
process.env.TWILIO_AUTH_TOKEN!,
req.headers.get("x-twilio-signature") ?? "",
"https://assistant.example.com/webhook", // the exact public URL
params,
);
if (!valid) return new Response("forbidden", { status: 403 });
await queue.add({ id: params.MessageSid, from: params.From, text: params.Body }); // idempotent by id
return new Response("<Response/>", { headers: { "content-type": "text/xml" } });
}4. The agent: approved knowledge, the guest's language
The agent gets three things in its context: the rules of the house (tone, what it may never say, when to escalate), the approved knowledge base, and the recent conversation. It answers in the language the guest writes in, which for a hostel can be five languages before lunch. It works with Gemini, ChatGPT or Claude; the model is a setting, not the product.
The most important rule is negative: if the answer isn't in the approved knowledge, it doesn't improvise. A confident wrong answer about prices or availability costs more trust than a short "let me check with the team". I test this with a fixed set of questions, including ones the agent must refuse, every time the knowledge or the model changes.
5. Tools: look things up, change things only with a yes
The difference between a FAQ bot and an assistant is that the assistant can act: look up a booking or an order, check availability, record a change request. It does that through your own tools, defined with function calling, each one narrow and with clear inputs.
Reading is free; changing is not. Before any change the assistant repeats what it will do in plain words and waits for the guest's yes, and the tool itself refuses to write without that confirmation. Payments and refunds stay with your existing systems and your team. An assistant that can move money on a chat message is a liability, not a feature.
6. Knowing its limits: the escalation path
When the assistant can't answer, the guest should never notice a dead end. It tells the guest that the team will check and come back, and at the same moment it alerts your team by email and on WhatsApp with a direct link to the conversation. The person who picks it up sees the whole chat, not a forwarded fragment.
Put a clock on every escalation. If nobody has answered after a set time, the alert goes out again or to someone else. The worst outcome is not that the AI didn't know; it is that the guest was promised an answer and never got one.
7. The learning loop: staff replies become knowledge
Every escalation is a gap in the knowledge base, so it shouldn't end with one answered guest. When a staff member replies, the question becomes a suggestion with their reply pre-filled as the answer, and one click adds it to the knowledge. In the surf school setup, new knowledge only goes live after a manager approves it, so a quick reply written in a hurry doesn't become the official truth.
This loop is what makes the assistant better every week without anyone writing a FAQ. The team keeps doing what it already does, answering guests, and the assistant learns from the answers that someone has signed off.
8. The staff inbox, and running it for real
Staff need one place to read every chat, reply themselves and pause the AI for a single conversation, for example when a guest is upset or a booking needs a human touch. Pausing per chat matters more than an on/off switch for the whole assistant.
For running it there are two ways. With your own accounts you bring the provider and AI keys and I guide the setup. All-inclusive, I provide the number and do the whole setup, including the WhatsApp Business approval and the message templates. Either way, keep the data you store to what the conversation needs, set a retention period, and tell guests in the first message that they are talking to an AI assistant and how to reach a person.
Takeaway
A good assistant for WhatsApp answers only what it knows, acts only with a yes, hands over with the whole chat and learns from the replies your team approves.
Real projects behind this
Try it yourself
Sources and official guides
- Twilio: WhatsApp Business Platform with Twilio
- Twilio: WhatsApp key concepts (customer service window, templates)
- Twilio: Send notifications with message templates
- Twilio: Webhooks security (X-Twilio-Signature)
- Azure Communication Services: Advanced Messaging for WhatsApp
- Gemini API: Function calling
- Claude: Tool use overview
- OpenAI: Function calling
More articles
- 3,025 pull requests in ten months: an AI-assisted delivery process, from the inside
- The EU AI Act for mid-sized companies: what applies to you, and when
- FinOps for AI spend: tokens, caching, routing and budgets that hold
- Making a restaurant network visible in AI answers: a GEO project, step by step
- How this site is built: static where it can be, streaming where it must
- Kubernetes cost on EKS and GKE: the same playbook, different levers
- A landing zone for mid-sized companies, in Terraform or Bicep: the parts that matter
- The legacy migration playbook: waves, parallel runs, and identical row counts and checksums
- MCP security in depth: how to let AI assistants into your product without opening the doors
- Monitoring on business outcomes: green dashboards, empty checkout
- Phone AI agents: the architecture, and the pitfalls nobody shows in the demo
- Restore tests: a backup you have never restored is only a hope
- Streaming AI answers on Azure Static Web Apps: the one header that buffered everything
- Air-gapped systems: running critical software with no internet
- Production AI on AWS: Amazon Bedrock and AgentCore in a private setup
- Production AI on Microsoft Foundry: a private reference setup for agents
- /goal, /loop or routines: stop babysitting your coding agent
- Claude's new plans: Max, Ultra and what they mean for teams
- OpenAI Codex at the end of 2026: goal mode, dots and how to lock it down
- GitHub Copilot, Claude Code or Codex? How I'd choose for a company
- GEO basics: how to show up in AI answers
- Production AI on Google Cloud: from Vertex AI to Gemini Enterprise Agent Platform
- Local LLMs in an air-gapped network: AI for your most sensitive data
- I want to run a local LLM: which server should I buy?
- MiniMax M3: an open frontier model you can run yourself?
- Prompt research at scale with an open model
- SEO and GEO together: a practical audit in 6 steps
- Right-size Kubernetes: the playbook that took a cluster from 7 to 4 nodes
- Private AI for sensitive data: a local LLM setup that passes the security review
- From AI prototype to production: the eight layers I add, in order
