# Telephony Provider Implementation This module implements the telephony provider abstraction for Dograh AI. For user-facing documentation, see the [Mintlify docs](https://docs.dograh.com/integrations/telephony/overview). ## Architecture ``` Business Logic → TelephonyProvider (Interface) → Concrete Provider (Twilio, Vonage, etc.) ``` ## Developer Quick Reference ### Using the Provider in Code ```python from api.services.telephony.factory import ( get_default_telephony_provider, get_telephony_provider_by_id, ) # Get the org's default outbound provider provider = await get_default_telephony_provider(organization_id) # Or resolve a specific telephony configuration row provider = await get_telephony_provider_by_id(config_id, organization_id) # Initiate a call result = await provider.initiate_call( to_number="+1987654321", webhook_url="https://your-app.com/webhook", workflow_run_id=123 ) ``` ## File Structure ``` telephony/ ├── __init__.py ├── base.py # Abstract TelephonyProvider interface ├── factory.py # Provider creation and config loading ├── providers/ │ ├── __init__.py │ ├── twilio_provider.py # Twilio implementation │ └── vonage_provider.py # Vonage implementation ├── twilio.py # Legacy (removed, use factory instead) └── README.md # This file ``` ## Implementing a New Provider See the [Custom Provider Guide](https://docs.dograh.com/integrations/telephony/custom) in the documentation for detailed implementation instructions. Quick checklist: 1. Create `providers/your_provider.py` implementing `TelephonyProvider` 2. Register the package in `providers/__init__.py` and add its schemas to `api/schemas/telephony_config.py` 3. Write unit tests 4. Update documentation ## Key Interfaces ```python class TelephonyProvider(ABC): @abstractmethod async def initiate_call(self, to_number: str, webhook_url: str, workflow_run_id: Optional[int] = None, **kwargs: Any) -> Dict[str, Any] @abstractmethod async def get_call_status(self, call_id: str) -> Dict[str, Any] @abstractmethod async def get_available_phone_numbers(self) -> List[str] @abstractmethod def validate_config(self) -> bool @abstractmethod async def verify_webhook_signature(self, url: str, params: Dict[str, Any], signature: str) -> bool @abstractmethod async def get_webhook_response(self, workflow_id: int, user_id: int, workflow_run_id: int) -> str ``` ## Configuration Loading The `factory.py` loads configuration from the database: **Both Saas and OSS Modes**: Database configuration via UI ```python # Loaded from organization_configuration table key: "TELEPHONY_CONFIGURATION" value: { "provider": "twilio", # or "vonage" "account_sid": "xxx", # for Twilio "auth_token": "xxx", # for Twilio "application_id": "xxx", # for Vonage "private_key": "xxx", # for Vonage "from_numbers": [...] } ``` ## Testing ### Unit Testing with Mock Provider ```python class MockProvider(TelephonyProvider): async def initiate_call(self, to_number, webhook_url, **kwargs): return {"call_id": "mock_123", "status": "initiated"} async def get_call_status(self, call_id): return {"call_id": call_id, "status": "completed"} # Implement other required methods... # In tests @patch('api.services.telephony.factory.get_default_telephony_provider') async def test_call_initiation(mock_get_provider): mock_get_provider.return_value = MockProvider() # Test your business logic ``` ### Integration Testing Run against actual providers in development: 1. Configure your provider through the UI: - Navigate to Settings → Integrations → Telephony - Select your provider (Twilio or Vonage) - Enter test credentials - Save configuration 2. Run integration tests: ```bash pytest tests/integration/test_telephony.py ``` ## Migration Notes ### From Direct TwilioService Usage Old code: ```python from api.services.telephony.twilio import TwilioService service = TwilioService(org_id) await service.initiate_call(...) ``` New code: ```python from api.services.telephony.factory import get_default_telephony_provider provider = await get_default_telephony_provider(org_id) await provider.initiate_call(...) ``` ### Backward Compatibility - Old `/api/v1/twilio/*` endpoints still work (redirect to `/api/v1/telephony/*`) - `TwilioService` class remains for legacy code - Database configuration key `TWILIO_CONFIGURATION` unchanged ## Common Issues 1. **Import Error**: Always import from `factory`, not directly from providers 2. **Config Not Found**: Check database configuration via UI 3. **Signature Verification**: Ensure auth tokens match between provider and config 4. **WebSocket Issues**: Verify audio format compatibility (MULAW for Twilio) ## Related Documentation - [User Documentation](https://docs.dograh.com/integrations/telephony/overview) - [Twilio Integration](https://docs.dograh.com/integrations/telephony/twilio) - [Custom Providers](https://docs.dograh.com/integrations/telephony/custom) - [Webhooks Guide](https://docs.dograh.com/integrations/telephony/webhooks)