The WhatsApp broadcast that started talking to itself: Eliminating auto-responder loops
Out-of-office auto-responders and BSP system error messages trigger infinite bot ping-pong loops on WhatsApp campaigns. Meta Cloud API provides no is_bot header, so standard CRMs either loop indefinitely or mute real customers. Here is how we engineered deterministic correspondent triage, context-aware thresholding, and prompt refusal gates in Klaros.
The Incident: A mass promotional broadcast triggers out-of-office responses from recipient handsets. Naive CRMs (like WATI, AiSensy, or Interakt) treat machine text as human engagement, generating automated AI replies that trigger another machine response—locking both systems into a loop that degrades WABA Quality Ratings and drains messaging credits.
The Architectural Fix: We added dynamic thresholding (15s gap, 60-character threshold for broadcast responses), multilingual auto-responder pattern matching (isAutoResponderPattern), and prompt guard refusal rails (canAnswer: false). Quick-reply button taps and WhatsApp Flow submissions retain 100% unconditional priority.
The Absence of `Auto-Submitted` Headers on WhatsApp
In conventional messaging protocols, machine-generated traffic carries explicit structural headers:
- SMTP Email: RFC 3834
Auto-Submitted: auto-replied,Precedence: bulk. - Slack API:
bot_idparameter present on message payload. - Telegram Bot API:
User.is_bot: true.
The Meta WhatsApp Cloud API provides no such header. An inbound webhook payload delivers identical fields (from, wa_id, text) whether written by a human typing on a keyboard or generated by an Android out-of-office auto-reply app:
{
"object": "whatsapp_business_account",
"entry": [{
"changes": [{
"value": {
"messaging_product": "whatsapp",
"contacts": [{ "profile": { "name": "Customer" }, "wa_id": "34600000001" }],
"messages": [{
"from": "34600000001",
"id": "wamid.HBgL...",
"timestamp": "1717584000",
"text": { "body": "Thank you for reaching out! We are currently unavailable." },
"type": "text"
}]
}
}]
}]
}
const AUTOREPLY_PATTERNS = [
/unknown\s+input\s+type\s+received/i,
/kindly\s+reply\s+with/i,
/thank\s+you\s+for\s+(reaching\s+out|contacting|messaging)/i,
/gracias\s+por\s+(escribirnos|contactarnos|tu\s+mensaje)/i,
/shukriya|dhanyawad/i,
/we\s*['’]?\s*re\s+unavailable/i,
/out\s+of\s+office/i,
/fuera\s+de\s+oficina/i,
/auto-reply|auto\s+reply|automated\s-response/i,
];
export function isAutoResponderPattern(text) {
const norm = String(text || '').trim();
if (!norm) return false;
return AUTOREPLY_PATTERNS.some((pattern) => pattern.test(norm));
}
Broadcast Attribution & Interactive Immunity
A major trap in WhatsApp CRM architecture is treating standard 1-on-1 operational templates (OTPs, appointment reminders) as mass broadcasts. Klaros inspects origin_campaign_id and is_broadcast flags on the outbound record before applying campaign-level threshold rules.
Crucially, interactive button taps and WhatsApp Flow completions take unconditional priority (isInteractive = true). No matter how fast an interactive payload arrives, a button press is treated as HUMAN 100% of the time.
Generative LLM Prompt Refusal Guards
Even if an automated text bypasses regex matching, generative AI models must be restrained from entering conversational loops. Klaros injects an explicit AUTO-RESPONDER GUARD into the model context when broadcast metadata is present:
const AUTO_RESPONDER_GUARD = `
AUTO-RESPONDER GUARD:
If the user's message appears to be an out-of-office auto-reply, automated acknowledgment, or system error (e.g., "Thank you for messaging us", "We are currently unavailable", "Unknown input type"):
1. Set "canAnswer": false
2. Set "handoff": false
3. Do NOT generate a conversational reply.
`;
Competitive Analysis & Technical Benchmark
| Platform | Broadcast Loop Triage | Per-Message Markup | Interactive Tap Protection |
|---|---|---|---|
| Klaros | Deterministic Refusal State Machine | $0 Zero Markup | 100% Unconditional Priority |
| vs WATI | None (Loops or Silences) | Per-message Markup Added | Best-effort |
| vs AiSensy | None (Generative Loop Risk) | Per-message Convenience Fee | Best-effort |
| vs Interakt | Basic Static Regex | Markup Added on Base Rates | Best-effort |
| vs Respond.io | Manual Workflow Required | Plan Fee + Markup | Workflow-dependent |
| vs SleekFlow | Basic Static Keyword | Per-User Fee + Markup | Workflow-dependent |
| vs Twilio | Raw API (Developer builds) | Per-message Fee | Custom Code Required |
Empirical Verification & Test Proofs
Every assertion in this note is backed by automated test suites running against real SQLite harnesses and Cloudflare D1 mocks:
# Run broadcast autoresponder loop triage test suite
npx mocha test/uni-cloud-broadcast-autoresponder.test.mjs
# Run correspondent self-match verification
npx mocha test/uni-cloud-correspondent-self-match.test.mjs
# Run full project test suite (9,411 passing tests)
npm test
Run WhatsApp campaigns without bot loop panic
Connect your own WhatsApp Business Account with zero per-message markup, full consent ledgers, and deterministic loop protection.
Questions people ask about broadcast auto-responder loop suppression
Why do WhatsApp broadcasts trigger auto-responder loops?
When a mass promotional broadcast is sent to thousands of contacts, handsets with out-of-office auto-reply enabled respond automatically. Naive CRMs treat these inbound texts as human messages and trigger auto-replies or AI model responses, starting an infinite messaging loop.
Does Meta WhatsApp Cloud API supply an is_bot header?
No. Unlike email (RFC 3834 Auto-Submitted) or Slack/Telegram APIs, Meta's Cloud API webhook delivers identical message structures regardless of whether the sender is a human or an auto-reply app.
How does Klaros prevent auto-responder loops without silencing human replies?
Klaros uses a 3-tier state machine (HUMAN, SUSPECTED_AUTOMATED, AUTOMATED) with dynamic gap thresholding (15s gap, 60-character threshold for broadcast context) and multilingual pattern matching, while granting 100% unconditional immunity to quick-reply button taps and WhatsApp Flow submissions.
How does zero-markup messaging save costs during mass broadcasts?
Traditional BSPs (WATI, AiSensy, Interakt) charge per-message markups or convenience fees on top of Meta rates, profiting from runaway bot loops. Klaros is a zero-markup BYO-WABA platform, meaning you pay Meta direct rates with zero per-message fee and zero wasted loop credits.
Written 23 September 2026. Klaros — Built to Remember Your Story. Related: our philosophy, reliability notes, all build notes.