You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add WhatsApp as a channel adapter for Trinity agents via Twilio's WhatsApp Business API, reusing the ChannelAdapter abstraction proven by Slack (SLACK-002) and Telegram (TGRAM-001). Each agent binds to its own Twilio account + WhatsApp sender number, enabling per-agent WhatsApp presence without platform-level WhatsApp Business verification.
Provider Choice: Twilio (vs Meta Cloud API Direct)
Decision: Use Twilio as the WhatsApp provider for v1. Meta's Cloud API direct remains a valid future alternative but is not the starting point.
Why Twilio for Trinity's per-agent, open-source model:
Fast onboarding — Twilio Sandbox works in 5 minutes (keyword-based opt-in). No Meta Business verification blocker for dev/test.
Per-agent credentials fit naturally — users bring their own AccountSid + AuthToken + whatsapp:+E164 sender, matching the Telegram bot-token pattern.
Programmatic number management — Twilio has real REST APIs for phone-number provisioning and sender registration.
No Meta Tech Provider program required — Meta Cloud API direct would force either one-WABA-for-all-agents (brand conflict) or enrollment in Meta's Tech Provider / Embedded Signup program (weeks-to-months of approval).
Optional future SMS — the same Twilio binding can serve SMS; a Phase 3 follow-up can add SMS with minimal extra work.
Twilio constraints noted:
One WABA per Twilio account (multiple senders/numbers per WABA). Multi-tenancy achieved by each agent owner using their own Twilio account, not a shared platform-level account.
Twilio WhatsApp does not support group chats — Phase 2 from the original spec is removed (see "Explicitly out of scope" below).
24-hour customer-service window applies; outside it, only pre-approved templates can be sent. Template management deferred to Phase 3.
Motivation
WhatsApp is the most widely used messaging platform globally (2B+ users). Enabling agents to participate in WhatsApp conversations opens Trinity to a massive user base, particularly for:
Rate limiting keyed on twilio:{account_sid}:{from_phone}
Session ID built from {account_sid}:{from_phone} (consistent with Telegram)
Access request flow for open_access agents
Phase 3: Advanced (deferred)
SMS support on the same TwilioAdapter (same binding, drops whatsapp: prefix)
Message templates for initiating conversations outside the 24-hour window (Twilio Content Builder)
Interactive buttons and list messages (Twilio Content API)
Voice-note transcription (Whisper API)
Outbound file sharing
Explicitly out of scope
Group chats — Twilio's WhatsApp API does not support group conversations. If needed later, would require Meta Cloud API direct or a different BSP. The previous "Phase 2: Group Chat Support" is therefore removed.
Meta Cloud API direct provider — tracked as a potential future alternative; not implemented here. Revisit if free-tier conversation volume matters more than programmatic onboarding speed.
Database Schema
CREATETABLEwhatsapp_bindings (
id INTEGERPRIMARY KEY AUTOINCREMENT,
agent_name TEXTNOT NULL UNIQUE,
account_sid TEXTNOT NULL, -- Twilio AccountSid
auth_token_encrypted TEXTNOT NULL, -- Encrypted AuthToken (AES-256-GCM)
from_number TEXTNOT NULL, -- e.g., 'whatsapp:+14155238886'
messaging_service_sid TEXT, -- Optional, preferred over from_number
display_name TEXT, -- Sender display name from Twilio
is_sandbox INTEGER DEFAULT 0, -- 1 if using Twilio Sandbox
webhook_secret TEXTNOT NULL, -- Random token in webhook URL path
webhook_url TEXT, -- Stored after user configures in Twilio Console
enabled INTEGER DEFAULT 1,
created_by TEXT,
created_at TEXTNOT NULL,
updated_at TEXT
);
CREATEINDEXidx_whatsapp_bindings_agentON whatsapp_bindings(agent_name);
CREATEINDEXidx_whatsapp_bindings_webhookON whatsapp_bindings(webhook_secret);
CREATETABLEwhatsapp_chat_links (
id INTEGERPRIMARY KEY AUTOINCREMENT,
binding_id INTEGERNOT NULLREFERENCES whatsapp_bindings(id),
wa_user_phone TEXTNOT NULL, -- E.164 phone number of WhatsApp user
wa_user_name TEXT, -- Twilio ProfileName
session_id TEXT,
verified_email TEXT, -- Unified access control (#311)
verified_at TEXT,
message_count INTEGER DEFAULT 0,
last_active TEXT,
created_at TEXTNOT NULL,
UNIQUE(binding_id, wa_user_phone)
);
CREATEINDEXidx_whatsapp_chat_links_bindingON whatsapp_chat_links(binding_id);
Security
AuthTokens AES-256-GCM encrypted at rest (same CredentialEncryptionService as Slack/Telegram)
Webhook signature verification via HMAC-SHA1 with X-Twilio-Signature header (Twilio spec: auth token as HMAC key, URL + alphabetically-sorted form params as base string)
SSRF prevention: media downloads restricted to api.twilio.com and *.twilio.com
Restricted tools for WhatsApp users (WebSearch, WebFetch — same as Slack/Telegram)
AuthToken values never logged
Rate limiting per recipient phone number to prevent abuse
Twilio Setup (User Responsibility)
For development (Sandbox):
Create a Twilio account → Messaging → Try WhatsApp
Copy AccountSid + AuthToken from Console
Sandbox sender is whatsapp:+14155238886 (shared across Twilio users)
Users opt in by sending join <your-sandbox-keyword> from their phone
Summary
Add WhatsApp as a channel adapter for Trinity agents via Twilio's WhatsApp Business API, reusing the
ChannelAdapterabstraction proven by Slack (SLACK-002) and Telegram (TGRAM-001). Each agent binds to its own Twilio account + WhatsApp sender number, enabling per-agent WhatsApp presence without platform-level WhatsApp Business verification.Provider Choice: Twilio (vs Meta Cloud API Direct)
Decision: Use Twilio as the WhatsApp provider for v1. Meta's Cloud API direct remains a valid future alternative but is not the starting point.
Why Twilio for Trinity's per-agent, open-source model:
whatsapp:+E164sender, matching the Telegram bot-token pattern.Twilio constraints noted:
Motivation
WhatsApp is the most widely used messaging platform globally (2B+ users). Enabling agents to participate in WhatsApp conversations opens Trinity to a massive user base, particularly for:
Architecture
Mirrors the existing Telegram/Slack transport pattern:
POST /api/whatsapp/webhook/{webhook_secret}(secret routes to the right agent binding).X-Twilio-SignatureHMAC-SHA1 overURL + alphabetically-sorted form paramsusing the agent's Twilio AuthToken.<Response/>) immediately, processes asynchronously viaasyncio.create_task— same shape astransports/telegram_webhook.py:81.Requirements
Phase 1: Direct Messages (MVP)
Backend
WhatsAppAdapterimplementingChannelAdapterABC (adapters/whatsapp_adapter.py)TwilioWebhookTransportinadapters/transports/twilio_webhook.py(HMAC-SHA1 signature verification)POST /api/whatsapp/webhook/{webhook_secret}(form-encoded body, returns empty TwiML, processes async)db/whatsapp_channels.py— DB operations for bindings and chat linkswhatsapp_bindingstable —agent_name,account_sid,auth_token_encrypted,from_number,messaging_service_sid(optional),webhook_secret,is_sandboxwhatsapp_chat_linkstable — maps WhatsApp phone numbers to chat sessions (includesverified_emailfor feat: Unified channel access control — verified-email identity, per-agent allow-list, access requests (web / Telegram / Slack) #311)CredentialEncryptionService)POST /2010-04-01/Accounts/{sid}/Messages.json) usinghttpxStatusCallbackparameter)MediaUrl0..N(up to 16MB per message; Twilio-hosted URLs)main.py(mirror Telegram webhook reconciliation, ~lines 483–513)Frontend
WhatsAppChannelPanel.vuein Agent Detail → Sharing tabGET /2010-04-01/Accounts/{sid}.json)join <keyword>to+14155238886)API Endpoints
GET /api/agents/{name}/whatsapp— binding statusPUT /api/agents/{name}/whatsapp— configure Twilio credentialsDELETE /api/agents/{name}/whatsapp— remove bindingPOST /api/agents/{name}/whatsapp/test— send test message to a numberPOST /api/whatsapp/webhook/{webhook_secret}— receive incoming messages + status callbacks (public, HMAC-verified)Phase 2: Access Control & Session Management
resolve_verified_emailvia phone number → verified email mapping/login <email>command pattern matching Telegram adaptertwilio:{account_sid}:{from_phone}{account_sid}:{from_phone}(consistent with Telegram)open_accessagentsPhase 3: Advanced (deferred)
TwilioAdapter(same binding, dropswhatsapp:prefix)Explicitly out of scope
Database Schema
Security
CredentialEncryptionServiceas Slack/Telegram)X-Twilio-Signatureheader (Twilio spec: auth token as HMAC key, URL + alphabetically-sorted form params as base string)api.twilio.comand*.twilio.comTwilio Setup (User Responsibility)
For development (Sandbox):
whatsapp:+14155238886(shared across Twilio users)join <your-sandbox-keyword>from their phoneFor production:
Relationship to Existing Work
ChannelAdapterABC from SLACK-002 (adapters/base.py)ChannelMessageRouterfor rate limiting, agent resolution, execution pipeline, access control (feat: Unified channel access control — verified-email identity, per-agent allow-list, access requests (web / Telegram / Slack) #311)TelegramAdapter+TelegramWebhookTransport— new adapter + new transport + DB module + router + frontend panelsrc/backend/adapters/whatsapp_adapter.pysrc/backend/adapters/transports/twilio_webhook.pysrc/backend/db/whatsapp_channels.pysrc/backend/routers/whatsapp.pysrc/frontend/src/components/agent-detail/WhatsAppChannelPanel.vuesrc/backend/db/migrations.pysrc/backend/main.py— lifespan integration (mirror Telegram at ~line 483)Acceptance Criteria