Skip to content

feat: Add native WhatsApp Cloud API serving with SQLite persistence (#133) - #135

Open
amitbhakt wants to merge 1 commit into
idiap:mainfrom
amitbhakt:feature/whatsapp-support
Open

amitbhakt wants to merge 1 commit into
idiap:mainfrom
amitbhakt:feature/whatsapp-support

Conversation

@amitbhakt

Copy link
Copy Markdown

Summary

Adds native Meta WhatsApp Cloud API serving capabilities to SDialog agents via Agent.serve_whatsapp() and Server.serve_whatsapp(), as requested in #133.

This implementation allows users to deploy and converse with SDialog agents directly over WhatsApp with production-grade reliability, multi-user session isolation, and zero-friction automated onboarding.

Closes #133


Key Features & Architecture

1. Developer Interface

Mirrors SDialog's existing Agent.serve() idiom:

from sdialog.agents import Agent

agent = Agent(name="SupportBot", persona=...)

# 1-Click serving: auto-discovers phone ID, spawns tunnel, syncs Meta webhooks
agent.serve_whatsapp(tunnel=True)

Parameters fall back to standard environment variables (WHATSAPP_PHONE_NUMBER_ID, WHATSAPP_ACCESS_TOKEN, WHATSAPP_APP_SECRET, WHATSAPP_VERIFY_TOKEN).

2. Multi-User Session Isolation via SQLite

  • Per-User Memory: Each sender phone number (wa_id) has isolated state stored in a local SQLite database (whatsapp_sessions.db).
  • Resilient Concurrency: Operates in SQLite WAL mode (PRAGMA journal_mode = WAL;) with a 5000ms busy timeout to prevent database locks under concurrent traffic.
  • Session Lifecycle: Automatic session expiration after inactivity (session_timeout, default 30 mins) or manual reset via slash commands (/reset, /clear, /restart).
  • State Bridge: Integrates with the proposed Agent.get_state() / Agent.set_state() API contract, with an internal message history bridge for immediate use.

3. Webhook Architecture & Meta SLA Compliance

  • Instant 200 OK ACK: Meta requires an HTTP 200 response within 3 seconds. The webhook handler verifies and acknowledges immediately, delegating agent inference and outbound messaging to a FastAPI BackgroundTask + asyncio.to_thread.
  • Per-User Queueing: Uses per-sender async locks (_user_locks[wa_id]) so messages from the same user are processed in chronological order (handling "double-texting"), while different users run concurrently.

4. Security & Edge Case Handling

  • HMAC-SHA256 Verification: Validates X-Hub-Signature-256 using constant-time comparison (hmac.compare_digest) on raw payload bytes; rejects spoofed requests with HTTP 401.
  • Webhook Idempotency: Tracks wamid (WhatsApp Message ID) in a processed_messages table to safely suppress duplicate webhook retries from Meta without re-invoking the LLM.
  • Event Polymorphism: Filters status receipts (sent, delivered, read) safely without crashing.
  • Non-Text Media Safeguard: Gracefully replies with an informative notice if an image, audio note, or sticker is sent.
  • Text Chunking: Splits messages exceeding WhatsApp's 4096-character limit across natural paragraph/word boundaries.

5. Automated Onboarding (Adapted from WAVoice)

  • Automatically inspects the access token (debug_token) to discover app_id and waba_id.
  • Auto-discovers the primary phone_number_id so users don't need to look up internal Meta IDs manually.
  • Programmatically configures all 3 webhook tiers (App-level subscription, WABA-level override, and Phone-level override) on startup when tunnel=True.

Provenance & Attribution

The auto-discovery and 3-tier webhook synchronization logic is adapted from WAVoice (Bhakt, 2026, DOI: 10.5281/zenodo.23537489), released under the MIT License, with full SPDX attribution headers included in src/sdialog/whatsapp/discovery.py.


Verification & Testing

  • Unit & Integration Tests: Added tests/test_whatsapp.py with 17 tests covering config validation, SQLite session persistence, TTL expiration, idempotency, HMAC validation, multi-user isolation, text chunking, and auto-discovery.
  • Regression Testing: All 30 existing tests in tests/test_server.py continue to pass (47/47 tests total).
  • Style & Linting: 100% compliant with Flake8 (0 errors).
  • Live Verification: Validated end-to-end with a live Meta WhatsApp Cloud API test account, ngrok tunnel, and real WhatsApp mobile chat.

…stence

- Add Agent.serve_whatsapp() and Server.serve_whatsapp()
- Implement SQLiteSessionStore with WAL mode, session timeout, and message idempotency
- Implement WhatsAppServer with HMAC-SHA256 signature verification and background task processing
- Implement MetaWhatsAppClient with message chunking and read receipts
- Implement MetaDiscoveryClient for automated Phone Number ID discovery and 3-tier webhook sync (adapted from WAVoice)
- Add 17 unit and integration tests covering security, idempotency, session isolation, and auto-discovery
@amitbhakt

amitbhakt commented Oct 23, 2026 •

Copy link
Copy Markdown
Author

Hi @sergioburdisso

LMK if you need any help in testing the PR via Meta a/c. Happy to hop on a call as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Whatsapp support

1 participant