Обзор

Провайдер телефонии реализуется как самостоятельно регистрирующийся пакет в api/services/telephony/providers/<name>/. Пакет предоставляет все, что нужно Агентике для подключения провайдера — класс провайдера, фабрику транспорта, конфигурацию аудио, схемы запроса/ответа, опциональные HTTP-маршруты и метаданные форм, используемые для отрисовки его интерфейса конфигурации, — через единый ProviderSpec, регистрируемый при импорте. Добавление нового провайдера не должно требовать изменений в фабрике, конфигурации аудио, модуле API-маршрутов, модуле пайплайна прогона или во фронтенде. Единственные правки за пределами папки провайдера:
  1. Одна строка импорта в api/services/telephony/providers/__init__.py
  2. Одна строка импорта в api/schemas/telephony_config.py, чтобы добавить классы запроса/ответа в дискриминированное объединение TelephonyConfigRequest

Структура пакета провайдера

Три файла обязательны (__init__.py, config.py, provider.py, transport.py). Остальные опциональны и обнаруживаются автоматически, если присутствуют:
  • routes.py — если модуль существует и экспортирует router: APIRouter, модуль маршрутов импортируется отложенно и монтируется под /api/v1/telephony через api.routes.telephony с помощью importlib. Провайдеры, которые только стримят по WebSocket (например, ARI), могут его не создавать.
  • strategies.py — используется транспортами, которым нужна специфичная для провайдера логика перевода звонка/завершения звонка в сериализаторе фреймов (например, переводы через конференцию).
  • serializers.py — обычно реэкспорт из pipecat. Оставляйте файл, даже если это однострочный реэкспорт, чтобы код транспорта импортировал из .serializers — это дает очевидное место для подкласса под собственную реализацию в будущем.

Интерфейс TelephonyProvider

Создайте подкласс TelephonyProvider в provider.py:
Полные докстринги по каждому методу см. в api/services/telephony/base.py.

Руководство по реализации

1. Схемы конфигурации

Определите Pydantic-модели для полезной нагрузки учётных данных. Дискриминатор provider типа Literal — это то, что заставляет схемы корректно диспетчеризоваться через дискриминированное объединение реестра.

2. Фабрика транспорта

Соберите Pipecat FastAPIWebsocketTransport для принятых WebSocket-соединений. Всегда загружайте учётные данные через load_credentials_for_transport, чтобы выбиралась правильная строка конфигурации, когда прогон воркфлоу несет telephony_configuration_id (организации с несколькими конфигурациями).

3. Маршруты (опционально)

Если ваш провайдер отправляет вебхуки в Агентику POST-запросами (answer URL, колбэки статуса, колбэки завершения звонка), предоставьте их через router на уровне модуля. Маршруты монтируются автоматически под /api/v1/telephony.
Маршруты загружаются отложенно через importlib из api.routes.telephony._mount_provider_routers, поэтому ваш модуль маршрутов может свободно импортировать другие бэкенд-сервисы, не создавая циклы импорта при загрузке класса провайдера.

4. Регистрация ProviderSpec

В __init__.py пакета все собирается воедино:
ProviderSpec покрывает все, что нужно нижестоящему коду:

5. Подключите пакет к цепочке импорта реестра

Добавьте одну строку импорта в api/services/telephony/providers/__init__.py:

6. Добавьте в дискриминированное объединение

Добавьте один блок импорта в api/schemas/telephony_config.py, чтобы классы запроса/ответа участвовали в объединении TelephonyConfigRequest и форме TelephonyConfigurationResponse:
На этом настройка бэкенда завершена.

Фронтенд

Форма конфигурации управляется метаданными. UI вызывает GET /api/v1/organizations/telephony-providers/metadata, получает список провайдеров и определения их ProviderUIField, и отрисовывает каждую форму универсальным способом. Специфичный для провайдера код фронтенда не нужен — форму формирует именно ваше объявление ProviderUIMetadata. Если вы добавляете новый тип поля, который не поддерживается существующим рендерером (например, загрузка файла), расширьте рендерер в ui/src/app/(authenticated)/telephony-configurations/. На сегодня поддерживаются следующие значения ProviderUIField.type: text, password, textarea, string-array и number.

Особенности форматов аудио

Каждый провайдер объявляет свой формат передачи через AudioConfig. Распространенные варианты:
  • Узкополосная телефония: 8 кГц μ-law, JSON-фреймы в кодировке base64
  • Широкополосная телефония: 16 кГц Linear PCM в виде бинарных фреймов
  • Asterisk ARI: 8 кГц Linear PCM через externalMedia
Частота дискретизации пайплайна ограничена 16 кГц для соответствия требованиям VAD; транспорты выполняют передискретизацию между форматом передачи и внутренней частотой пайплайна.

Тестирование

Для end-to-end тестирования сохраните своего провайдера через интерфейс telephony-configurations и инициируйте тестовый звонок из воркфлоу.

Лучшие практики

  1. Доверяйте реестру — никогда не импортируйте класс другого провайдера напрямую; разрешайте зависимость через хелперы фабрики (get_default_telephony_provider, get_telephony_provider_by_id и т. д.).
  2. Чувствительные поля — помечайте каждое поле с учётными данными как sensitive=True в ProviderUIMetadata. Эндпоинт сохранения маскирует их при чтении и сохраняет исходное значение, когда клиент повторно отправляет замаскированное значение.
  3. Проверка подписи входящих вебхуков — всегда проверяйте подписи входящих вебхуков в verify_inbound_signature. Возврат True, когда заголовок подписи отсутствует, допустим; возвращайте False, когда подпись присутствует, но недействительна.
  4. Транспорты загружают учётные данные лениво — вызывайте load_credentials_for_transport с telephony_configuration_id из прогона воркфлоу. Не читайте конфигурацию организации по умолчанию из transport.py.
  5. Логирование — используйте loguru.logger.

Референсные реализации

Используйте ARI как минимально жизнеспособный пример: провайдер только стримит по WebSocket и не предоставляет HTTP-вебхуки. Если у вашего провайдера есть HTTP-вебхуки, добавьте routes.py и реализуйте verify_inbound_signature.