04 ноября 2026 г.
Автор
Рецензент
При масштабировании голосовых ИИ-агентов в продакшене с использованием Twilio Conversation Relay крайне важно поддерживать бесперебойную работу архитектуры. Это особенно актуально во время мероприятий с высоким объемом трафика, таких как Черная пятница или Киберпонедельник, а также при внезапных пиках нагрузки. Высокая нагрузка или неожиданная деградация провайдера могут привести к задержкам, обрывам соединения или сбоям запросов. Чтобы защитить инфраструктуру Conversation Relay от этих рисков, вам необходима стратегия отказоустойчивости на уровне приложения.
Conversation Relay использует двух речевых провайдеров для каждого звонка: провайдера распознавания речи (ASR/STT), который преобразует речь звонящего в текст, и провайдера синтеза речи (TTS), который озвучивает ответы вашего агента. Каждый из них является сторонним сервисом, таким как Deepgram, Google, ElevenLabs или Amazon. Иногда сервис может работать медленно, быть недоступным или отклонять запрос.
В этом руководстве рассматриваются:
- Как сбой провайдера доходит до вашего приложения при запуске и во время разговора.
- Коды ошибок, на которые следует обратить внимание.
- Как вернуть новый TwiML <ConversationRelay> из вашего URL-адреса действия (action URL), который переключается на другого провайдера, чтобы звонящий оставался на линии.
- Как справляться со сбоями в середине разговора путем отправки сообщения об окончании с handoffData, а затем переключения провайдеров в последующем TwiML.
Как до вас доходят сбои
Где именно проявляется сбой, зависит от того, какой провайдер дал сбой и когда это произошло:
Из этой таблицы вытекают два правила:
- В обработторе URL-адреса действия проверяйте ErrorCode, а не только SessionStatus. Некоторые сбои во время звонка сообщают о SessionStatus=ended, но при этом содержат ErrorCode.
- Обрабатывайте сбои TTS на своем WebSocket-сервере. Когда голос агента перестает работать в середине разговора, вызов остается подключенным, и звонящий слышит тишину. Conversation Relay не завершит вызов за вас. Ваш сервер должен замечать сообщения об ошибках и отправлять end (см. раздел «Сбои во время разговора» ниже).
Предварительные требования для реализации отказоустойчивости
Перед внедрением пользовательской логики отказоустойчивости ваше приложение Conversation Relay должно отвечать нескольким базовым лучшим практикам. Эти основы помогут вам создать надежный сервис для продакшена.
Всегда задавайте URL-адрес действия в <Connect>
Отказоустойчивость работает только тогда, когда для <Connect> задан action URL. Когда сеанс Conversation Relay завершается по любой причине, Twilio отправляет запрос на этот URL-адрес, и вызов продолжается с тем TwiML, который вы возвращаете. Без URL-адреса действия вызов переходит к глаголу, следующему за <Connect> в исходном документе, и вы не можете изменять это поведение в зависимости от ошибки.
Пример кода
Явно указывайте имена провайдеров
Всегда задавайте ttsProvider и transcriptionProvider, даже если вы используете значения по умолчанию. Таким образом, каждый документ TwiML точно указывает, какого провайдера он использует, и ваш резервный TwiML сможет переключиться на другого.
Если вы опустите настройки TTS или транскрипции для языка, Conversation Relay заполнит их из значений по умолчанию (ElevenLabs с голосом по умолчанию для TTS; Google или Deepgram для транскрипции). Значение по умолчанию — это не то, с чего или на что можно намеренно переключиться. Устанавливайте ttsProvider рядом с voice, а не позволяйте провайдеру определяться по имени голоса.
Отслеживайте номер попытки
Указывайте номер попытки и провайдеров, которых вы уже попробовали, в строке запроса URL-адреса действия (например, ?attempt=2&tts=google). Тогда ваш обработчик будет знать свое положение в цепочке отказоустойчивости и не попадет в бесконечный цикл (подробнее см. в разделе «Избежание циклов отказоустойчивости»).
Следите за параметрами URL-адреса действия
Когда сеанс завершается, Twilio отправляет стандартные параметры голосового вызова (CallSid, AccountSid, From, To, CallStatus и т. д.) плюс следующие параметры Conversation Relay:
Коды ошибок, за которыми стоит следить
Некоторые коды ошибок, возвращаемые веб-хуком, намекают на то, что пора переключаться на другого провайдера. В этом разделе приводится обзор типов кодов, с которыми вы можете столкнуться, а также конкретные коды ошибок.
Сбои провайдеров: кандидаты на переключение
Обновляете существующий обработчик? Более ранние версии Conversation Relay сообщали о многих сбоях провайдеров как о 64103, а об отклонениях голоса Google или Amazon — как о 64106. Обработчики, которые повторяют попытку при 64103 один раз, продолжают работать, но теперь для отлова сбоев провайдеров достаточно проверять 64111, 64112 и 64114.
Другие коды, которые можно увидеть в том же обработчике
Сбои при запуске
Сбой при запуске означает, что сеанс завершился до того, как разговор успел начаться. Обычно вызывающий абонент еще ничего не слышал или слышал лишь часть приветствия. Conversation Relay вызывает ваш action URL со статусом SessionStatus=failed и ErrorCode, и звонящий остается на линии, пока вы возвращаете новый TwiML.
Исходный TwiML (основные провайдеры)
Пример кода
Экранируйте символ & как & внутри значений атрибутов XML.
Сбой транскрипции (ASR) при запуске: ErrorCode=64114
Сохраните провайдера TTS и смените провайдера транскрипции:
Пример кода
При переключении провайдеров транскрипции также измените speechModel на модель, поддерживаемую новым провайдером. Имя модели Deepgram, отправленное в Google, или наоборот, приведет к сбою с кодом 64106.
Сбой TTS при запуске: ErrorCode=64111 или 64112
Сохраните провайдера транскрипции и смените провайдера TTS и голос:
Пример кода
Голоса принадлежат конкретному провайдеру. При изменении ttsProvider выберите голос из каталога нового провайдера. Выберите резервный голос заранее, чтобы голос агента звучал как можно ближе к основному.
Резервный провайдер также должен поддерживать ваш язык. Провайдеры поддерживают не все языки, и резервный вариант, который не поддерживает язык (например, Amazon с zh-TW или he-IL), отклоняется с ошибкой 64101, что означает сбой и вашего резервного TwiML. Протестируйте каждый резервный голос для каждого поддерживаемого вами языка.
Элементы <Parameter> передаются на ваш WebSocket-сервер в сообщении настройки в разделе customParameters. Таким образом, ваш агент знает, что он запущен в резервном сеансе, и может, например, сделать стиль ответов более коротким или записать событие в лог.
Пример обработчика URL-адреса действия
Вот минимальный обработчик на Node.js (Express). Он выбирает следующего провайдера, ограничивает количество попыток и переключает на оператора-человека, когда ничто другое не помогает:
Пример кода
В продакшене экранируйте каждое значение, помещаемое в XML, и по возможности используйте вспомогательную библиотеку Twilio или построитель TwiML вместо строковых шаблонов. Проверяйте заголовок X-Twilio-Signature для каждого запроса к вашему URL-адресу действия.
Сбои во время разговора
Иногда вам нужно реагировать на сбой в середине звонка. В следующих разделах подробно описаны режимы сбоев, с которыми вы можете столкнуться во время живого звонка, а также указано, следует ли предпринимать какие-либо действия.
Сбой транскрипции во время разговора: дополнительных действий на WebSocket-сервере не требуется
Если провайдер транскрипции дает сбой во время разговора, Conversation Relay завершает сеанс и вызывает ваш action URL с ErrorCode=64114 (или ErrorCode=64103, если сбой произошел внутри Twilio). В зависимости от того, в какой момент разговора произошел сбой, SessionStatus может иметь значение failed или ended. Ваше WebSocket-соединение закрывается.
Обработчик URL-адреса действия из раздела «Пример обработчика URL-адреса действия» выше уже справляется с этим: он распознает код ошибки ASR и возвращает TwiML с другим transcriptionProvider. Чтобы продолжить разговор вместо начала заново, сохраняйте состояние разговора на стороне сервера (с ключом CallSid) и запрашивайте его снова при поступлении сообщения настройки нового сеанса. setup всегда включает callSid.
Сбой TTS во время вызова: ваш WebSocket-сервер должен действовать
Сбой TTS во время вызова не завершает сеанс. Conversation Relay отправляет сообщение об ошибке на ваш WebSocket-сервер, не озвучивает этот ответ и поддерживает соединение активным. Если провайдер не работает, каждый последующий ответ завершается с тем же сбоем, и звонящий слышит тишину, пока не повесит трубку.
Сообщение об ошибке приходит в одной из двух форм, в зависимости от провайдера:
Copy code
Copy code
Первая форма используется большинством провайдеров, включая ElevenLabs и Deepgram. Вторая используется голосами Google и Amazon и не содержит непроизнесенный текст. Обе формы включают код ошибки (code: ...). Когда первая форма также включает текст, который не удалось озвучить (tokens: ...), вы можете передать его в новый сеанс, чтобы звонящий услышал пропущенный ответ.
Рекомендуемая обработка:
- Прочитайте код из description. Считайте 64111 и 64112 сбоями TTS, независимо от формы сообщения. Пропустите 64112 с input_timeout_exceeded (см. раздел «Коды ошибок, за которыми стоит следить»). Другие коды, такие как 64106 для медиа-URL, который не удалось воспроизвести, не являются сбоями провайдера.
- Решите, когда переключаться на резервный вариант. Одиночная ошибка 64111 может быть случайной. Два сбоя подряд или любой сбой во время первого хода (приветствия) означают, что на провайдера нельзя полагаться, поэтому выполните переключение.
- Отправьте сообщение end с параметром handoffData, который описывает причину завершения и то, что требуется для следующего сеанса. handoffData должна быть строкой, поэтому вызовите JSON.stringify для вашего объекта.
- Conversation Relay завершает сеанс и вызывает URL-адрес действия с SessionStatus=ended и HandoffData, установленным в виде вашей строки. Ваш обработчик возвращает TwiML, в котором используется другой ttsProvider.
Сообщение о завершении:
Copy code
Пример логики WebSocket-сервера (Node.js, ws)
Copy code
Обработка передачи управления в URL-адресе действия
Обработчик выше уже считывает HandoffData. Когда reasonCode имеет значение tts-failure, он переходит к следующему провайдеру TTS. Он также передает conversationId через элемент <Parameter>, чтобы сообщение настройки нового сеанса возобновляло тот же разговор. Вот TwiML для передачи управления при сбое TTS во время вызова, которая также воспроизводит непроизнесенный текст:
Copy code
Размещение unspokenText в welcomeGreeting означает, что звонящий услышит ответ, который завершился сбоем. Если вы предпочитаете этого избежать, используйте короткое приветствие «на чем мы остановились?» или опустите welcomeGreeting и позвольте вашему агенту заговорить первыми после получения setup.
Завершение вызова по другим причинам во время разговора
Вы можете использовать тот же паттерн end plus handoffData для любой проблемы во время вызова, обнаруженной вашим сервером — например, когда провайдер LLM не работает, вызов инструмента продолжает завершаться сбоем или вызывающий просит соединить с человеком. Установите другой reasonCode (llm-failure, live-agent, ...) и делайте ветвление по нему в обработчике URL-адреса действия. Всегда предпочитайте end закрытию WebSocket. Если вы закроете WebSocket, сеанс завершится с ошибкой 64105, и вы потеряете HandoffData.
Избежание циклов переключения на резерв
Добавляя переключения на резервные варианты в приложение Conversation Relay, необходимо соблюдать осторожность, чтобы случайно не создать цикл, который циклически перебирает резервные провайдеры и никогда из него не выходит. Этот список содержит наши лучшие практики по предотвращению цикла переключения.
- Ограничьте количество попыток. Передавайте attempt в URL-адресе действия и останавливайтесь после 2 или 3 попыток.
- Меняйте что-нибудь при каждой попытке. Повторяйте идентичный TwiML только для 64103 и только один раза.
- Не переключайтесь на резерв при ошибках конфигурации (64101, 64106). Они завершаются ошибкой одинаково при каждой попытке.
- Всегда имейте окончательный резервный вариант, который не использует Conversation Relay, например <Say> с <Dial> на живого агента, <Enqueue>, <Record> для голосовой почты или вежливое <Hangup>. <Say> использует собственный TTS от Twilio, поэтому он не зависит от провайдера, который только что дал сбой.
- Возвращайте <Response/> при SessionStatus=completed, так как звонящий уже повесил трубку.
Контрольный список
Ищете памятку о том, как обрабатывать переключения на резерв в вашем производственном приложении Conversation Relay? Этот список содержит краткую версию наших рекомендаций из этой статьи, чтобы вы могли проверить, правильно ли ваше приложение обрабатывает возможные сценарии сбоев.
- ☐ Каждые <Connect> имеет URL-адрес действия, который передает attempt и текущих провайдеров.
- ☐ ttsProvider, voice, transcriptionProvider и speechModel заданы явно.
- ☐ Резервный голос и резервная модель распознавания речи выбраны и протестированы для каждого поддерживаемого вами языка. Резервный вариант, который не обслуживает язык, завершается ошибкой 64101.
- ☐ Обработчик URL-адреса действия делает ветвление по ErrorCode (а не только по SessionStatus) и анализирует HandoffData.
- ☐ 64114 переключает распознавание речи на резерв. 64111 и 64112 переключают TTS. 64103 повторяет попытку один раз. 64101 и 64106 перенаправляют на резервный вариант и отправляют оповещение.
- ☐ Ваш WebSocket-сервер отслеживает сообщения об ошибках с кодом 64111 или 64112 (в обеих формах сообщений) и отправляет end с handoffData.
- ☐ Состояние разговора сохраняется на стороне сервера и возобновляется через <Parameter name="conversationId">.
- ☐ Окончательный резервный вариант не зависит от Conversation Relay.
- ☐ ErrorCode, ErrorMessage и CallSid регистрируются в журналах для каждого переключения на резерв, чтобы вы могли обратиться в службу поддержки Twilio.
Заключение
Реализовав эти стратегии переключения на резерв, ваши голосовые ИИ-агенты Conversation Relay станут более устойчивыми к сбоям провайдеров речи, всплескам трафика и временным ухудшениям связи. Создание стратегии резервного копирования с использованием нескольких провайдеров помогает обеспечить непрерывный поток разговоров с высокой доступностью — независимо от того, имеете ли вы дело с событиями с высоким объемом трафика, такими как Черная пятница, или трафиком в случайный будний вечер.
Благодаря этим передовым практикам ваша голосовая инфраструктура может быть подготовлена к масштабам предприятия. Мы с нетерпением ждем возможности увидеть и услышать, что вы создадите!
Рекомендуемые ресурсы
- Обзор и документация по Twilio Conversation Relay
- Справочник элементов TwiML для Conversation Relay
- Ресурс голосового вызова Twilio и параметры обратного вызова состояния
Дэниел Янссон — технический руководитель в Twilio, где он работает с 2017 года и помогал создавать Conversation Relay. Он тратит много времени на то, чтобы голосовые вызовы ИИ продолжали работать, когда провайдер преобразования речи в текст или текста в речь на другом конце не работает. С ним можно связаться по адресу djansson [at] twilio.com.









