A sales agent that stays up
WhatsApp in, AI reply out — with memory, lead scoring, human handoff and a VPS that keeps running
Not a chatbot script — a small production system with separate jobs for messaging, reasoning, memory, lead state, deployment and optional voice. The separation is the whole point: it makes the thing debuggable, and it means a front-end change cannot take down your customer messaging. Ten steps from a local clone to a worker that survives you closing the laptop.
The instinct is to write one script that listens and replies. That version works in a demo and falls over the moment you need to know why it said something. This splits the work: a webhook that receives, a model that drafts, a database that remembers, a scorer that tracks intent, a host that stays up, and a voice layer you can ignore until you need it. Each piece can be debugged and replaced on its own.
Six jobs, six components
It talks to the official Cloud API directly rather than driving WhatsApp Web through browser automation. The popular automation libraries are genuinely good and widely used, but they drive the consumer web client, and their own documentation warns that accounts can be blocked. For something a business depends on, the official transport is the one that does not put the number at risk.
What the design borrows from, and what it does not
Star counts re-checked against GitHub on 16 September 2026 rather than carried over. Five of the six matched the source; the customer-desk figure had drifted and is corrected here.
Get it running locally
Node 20+, TypeScript, Express. The worker listens on port 8080 by default — confirm the process is alive before wiring anything external to it.
Change one module at a time, and keep the webhook, database, model client and voice layer separate in your instructions. The separation is not academic: it is what stops a cosmetic UI change from breaking live customer messaging. Also — do not commit the .env file.
The memory layer
Run the schema in a fresh database project. The starter creates two tables — contacts and messages. Every inbound and outbound message is stored, and the worker reloads recent history for that contact before the model drafts anything. That is what gives it short-term memory without stuffing an ever-growing conversation into one prompt.
It bypasses row-level security by design. It belongs in the worker and nowhere else — never in a browser app, never in the front-end, never in anything shipped to a client. Growing past the starter means conversation summaries, embeddings for product knowledge, staff authentication and a real handoff queue; none of that changes where this key lives.
Connect WhatsApp properly
Create a Meta developer app, add the WhatsApp product, connect a business number, and point the webhook at https://YOUR_PUBLIC_DOMAIN/webhooks/whatsapp.
How the webhook behaves
The AI brain
The model needs exactly three things: a strong system instruction, verified business context, and recent history. Everything else is decoration.
The system instruction explicitly forbids inventing stock, prices, delivery dates, discounts, policies or guarantees. When the data is missing, the correct behaviour is to say so and offer a human. An agent that confidently makes up a delivery date is worse than no agent, because a customer will hold you to it. Put product facts in structured data or a retrieval layer rather than a sprawling “remember everything about my company” prompt.
Lead scoring — deliberately simple
A sales agent should do more than answer questions; it should preserve intent. This is transparent on purpose so you can replace it once you know which signals actually correlate with revenue.
Funnel stages and handoff
Voice, only if you need it
Telephony streams PCMU audio to your VPS over WebSocket, the realtime model returns audio, the worker streams it back to the caller. Point your voice number at https://YOUR_DOMAIN/voice/incoming.
This gives the business a normal phone channel. WhatsApp messaging stays on the Cloud API — the two are separate integrations. If your account has access to WhatsApp calling features, treat that as its own piece of work with its own eligibility rules, not as something this turns on.
Put the worker online 24/7
A webhook worker must not depend on your laptop being open. This is the step that separates a demo from something a business can point a phone number at.
Deployment rules that matter
Where a web host fits
Good for an optional page or a future dashboard. Not required for the messaging agent at all, and not the persistent worker. Add real staff authentication before any browser page displays customer data.
Acceptance test before you show anyone
“It deployed” and “it works” are different claims. Run the eight.
Production guardrails — do not skip these
Adaptation prompt
Use it after cloning, with the bracketed details filled in. The important constraint is the last one — do not ask it to rewrite everything at once.
One complete sales loop, end to end
The goal is not “make the bot reply”. Anyone can get a reply.
Troubleshooting
This is deliberately small enough to read and understand in an afternoon, which is exactly why it is useful. Real production scale needs authentication, observability, queues, retries, access controls, compliance work and business-specific tooling. Knowing which of those you still owe is the difference between shipping and being surprised.
Commands, environment variable names and the acceptance tests are as given in the source guide. The star counts for every referenced project were re-checked against GitHub on 16 September 2026: five of six matched, and the customer-desk figure was corrected upward. Model and voice identifiers are left as placeholders rather than pinned, since those move faster than anything else here.