Channel Adapters
Overview
Section titled “Overview”Jina Connect uses a channel adapter pattern to abstract away provider-specific APIs. Each messaging channel (WhatsApp, Telegram, SMS, RCS) has one or more provider adapters that implement a common interface. This lets you swap providers without changing application code.
Channel Registry
Section titled “Channel Registry”The ChannelRegistry (jina_connect/channel_registry.py) is a runtime registry where channel adapters register themselves during Django startup:
# Each app's AppConfig.ready() calls:register_channel(platform, factory_function)
# At runtime, resolve the adapter:adapter = get_channel_adapter(platform, tenant)Platform Choices
Section titled “Platform Choices”All channels map to canonical platform identifiers defined in jina_connect/platform_choices.py:
| Platform | Value | Description |
|---|---|---|
WHATSAPP | "WHATSAPP" | WhatsApp Business API |
TELEGRAM | "TELEGRAM" | Telegram Bot API |
SMS | "SMS" | SMS via provider APIs |
RCS | "RCS" | RCS Business Messaging |
EMAIL | "EMAIL" | Email (planned) |
VOICE | "VOICE" | Voice calls (planned) |
Base Adapter Interface
Section titled “Base Adapter Interface”All channel adapters extend BaseChannelAdapter (wa/adapters/channel_base.py):
class BaseChannelAdapter(ABC): @abstractmethod def send_text(self, chat_id: str, text: str, **kwargs) -> dict: """Send a plain text message."""
@abstractmethod def send_media(self, chat_id: str, media_type: str, media_url: str, caption: str = None, **kwargs) -> dict: """Send a media message (image, video, document, audio)."""
@abstractmethod def send_keyboard(self, chat_id: str, text: str, keyboard: list, **kwargs) -> dict: """Send a message with interactive buttons/keyboard."""
@abstractmethod def get_channel_name(self) -> str: """Return the canonical channel name."""All adapter methods return an AdapterResult dataclass with success, message_id, raw_response, and error.
WhatsApp Adapters
Section titled “WhatsApp Adapters”WhatsApp has a two-level adapter hierarchy:
BaseChannelAdapter └── BaseBSPAdapter # Adds template management ├── MetaDirectAdapter # Meta Graph API └── GupshupAdapter # Gupshup APIBSP Selection
Section titled “BSP Selection”Each tenant’s TenantWAApp has a bsp field (BSPChoices) that determines which adapter to use. The factory function get_bsp_adapter(wa_app) returns the correct adapter.
Meta Direct Adapter
Section titled “Meta Direct Adapter”| Feature | Details |
|---|---|
| API | Meta Graph API v18+ |
| Auth | Permanent access token (META_PERM_TOKEN) |
| Webhook verification | META_APP_SECRET for signature validation |
| Template sync | Direct CRUD via Graph API |
| Media | Upload to Meta, get handle ID |
Gupshup Adapter
Section titled “Gupshup Adapter”| Feature | Details |
|---|---|
| API | Gupshup Enterprise API |
| Auth | Email/password → session token |
| Template sync | Via Gupshup template API |
| Webhook | Gupshup-format webhook events |
Telegram Adapter
Section titled “Telegram Adapter”Telegram uses the Telegram Bot API directly — no multi-provider abstraction needed.
| Component | Location |
|---|---|
| Bot configuration | telegram/models.py → TelegramBotApp |
| Message sending | telegram/services/message_sender.py |
| Webhook handling | telegram/views.py → TelegramWebhookView |
Each tenant registers their own Telegram bot with an encrypted bot_token. Webhooks are set up per-bot with a unique secret.
SMS Providers
Section titled “SMS Providers”SMS uses the same adapter pattern as WhatsApp BSPs:
BaseSMSProvider (sms/providers/base.py) ├── TwilioProvider # Twilio API ├── MSG91Provider # MSG91 API └── Fast2SMSProvider # Fast2SMS APIEach tenant’s SMSApp specifies a provider and stores encrypted provider_credentials (JSON).
| Provider | DLT Support | Sender ID | Webhook Types |
|---|---|---|---|
| Twilio | No | from_number | Inbound + DLR |
| MSG91 | Yes | sender_id | DLR |
| Fast2SMS | Yes | sender_id | DLR |
RCS Providers
Section titled “RCS Providers”RCS follows the same pattern with SMS fallback built in:
BaseRCSProvider (rcs/providers/base.py) ├── GoogleRBMProvider # Google RCS Business Messaging └── MetaRCSProvider # Meta RCS APIEach tenant’s RCSApp can optionally link to an SMSApp via sms_fallback_app FK. When sms_fallback_enabled=True, failed RCS deliveries automatically retry via SMS.
| Provider | Auth | Suggestions | Fallback |
|---|---|---|---|
| Google RBM | Service account JSON | Quick replies, actions | SMS via linked SMSApp |
| Meta RCS | Access token | Quick replies | SMS via linked SMSApp |
Adding a New Provider
Section titled “Adding a New Provider”To add a new provider for an existing channel:
- Create a new provider class extending the base (e.g.,
BaseSMSProvider) - Implement all abstract methods (
send_text,send_media, etc.) - Add the provider to the choices enum (e.g.,
SMSProviderChoices) - Register in the app’s
AppConfig.ready()if using the channel registry
To add an entirely new channel (e.g., Email, Voice):
- Create a new Django app
- Implement
BaseChannelAdapter - Register via
register_channel(platform, factory)inAppConfig.ready() - Add URL patterns, models, serializers, and viewsets
- Add to the
PlatformChoicesenum