WhatsApp AI Agent: Stop Duplicate Messages
Ack instantly, dedup the retries, merge the bursts.
- A 4s LLM call misses the ack window — WhatsApp resends while you think.
- Dedup by
idcatches true retries but not bursts (different ids, one intent). - Instant ack + id dedup + burst merge = 1 run per person.
The problem
- WhatsApp doesn't promise exactly-once — on a slow ack it retries the webhook.
- A four-second LLM call misses the window, so WhatsApp resends while you're still thinking.
- Your agent answers one human message two or three times — and bursts each fire a run.
The solution
Two shapes of duplicate need two moves — a true retry (same id) and a burst (different ids, one thought).
- Ack with 200 before you call the agent, so WhatsApp stops resending.
- Dedup on the message
idto drop true retries. - Merge a burst of fragments into one message before forwarding.
Dedup stops the retries; merging stops the fragments. You need both to answer each person exactly once.
Result: one real intent → one agent run.
WhatsApp does not promise to deliver each webhook exactly once. On a slow response or a timeout, the WhatsApp Cloud API retries — so your AI agent receives the same message two or three times and answers it two or three times. Here is why it happens and how to stop it.
Why WhatsApp sends the same message twice
Two things make it worse:
- Slow agents. An LLM call that takes four seconds can miss the ack window, so WhatsApp resends while the first run is still going.
- Bursts. A user sends “hi”, “are you there”, “I need help” as three messages in a few seconds — each a separate webhook, each a separate agent run for one intent.
The symptom is the same every time: your agent replies more than once to a single human message. And the two causes aren’t the same duplicate — a true retry carries the identical message id; burst fragments are different messages that are really one thought.
The manual fix (Option 1)
Two defenses, layered — each one yours to build.
Fix 1: ack fast, then dedup on the message id
Return 200 the instant the webhook lands, before any LLM call, so WhatsApp stops resending. Then store the ids you’ve already handled (a cache, a KV store, a SETNX in Redis) and ignore any id you’ve seen. Every WhatsApp webhook carries a unique messages[0].id.
On a gateway, the instant ack and the id store are built in.
Fix 2: merge the burst into one message
A burst isn’t a retry — it’s several real messages that together form one intent. Hold them for a short window and merge them in order into a single payload, so the agent runs once and sees the whole question. The mechanics are in message unification.
On a gateway, burst merging is a window setting, not stateful code in your handler.
The catch: you have to keep it running
Acking fast, hosting the id store, and buffering bursts per sender turns a simple webhook into a stateful service you own — and you rebuild it for every channel you add beyond WhatsApp. For one bot it’s doable; across a fleet it’s a system to maintain.
Place a gateway layer (Option 2) — faster
A message gateway sits between WhatsApp and your agent’s URL. It acks WhatsApp instantly so retries never start, deduplicates true resends by id, and merges a burst into one message before forwarding. Your agent receives one clean event per real intent and runs once.
Option 1 (DIY) vs Option 2 (gateway)
| Do it yourself | Use a gateway | |
|---|---|---|
| True retry (same id) | ✓Dedup on id | ✓Dropped at the edge |
| Burst fragments (different ids) | ~Needs stateful buffering | ✓Merged into one |
| Fast 200 ack | ~Wire async per handler | ✓Instant, built in |
| Id store & buffer | ✕You build & host | ✓Built in |
| Every channel | ~Repeat setup each time | ✓One layer, all channels |
| Control of internals | ✓Full | ~Abstracted away |
This is the WhatsApp-specific case of a general problem — see how to stop duplicate messages across any channel for the platform-agnostic version. It’s one piece of message quality for AI agents.
If option 2 sounds more like you, here’s the short version of how to set it up: let a gateway ack WhatsApp and dedup →.
Either way — go make your agent answer each person once.
Thanks for reading. 👋
Orlando. -
Orlando Quijada
Technologist with 15+ years of experience. Developer, SaaS tester, and AI collaboration & optimization specialist. Currently contributing at portarus.com.
Written on