Integrating a Custom TTS Provider
The provider documentation is: $documentation
Use the documentation as the source of truth for the provider protocol. If it is
missing, ask for the provider's TTS API documentation before implementing. Follow links
from it only when needed to resolve authentication, request/response messages, audio
formats, streaming behavior, interruption, or limits.
Workflow
- Inspect the assistant's installed Rasa version and the actual
TTSEngine,
TTSEngineConfig, and RasaAudioBytes APIs. Follow those signatures when they
differ from examples.
- Review existing custom speech components and project conventions before choosing a
module path. Default to
addons/custom_tts.py only when no convention exists.
- Read the provider documentation and complete the protocol analysis in
references/integration-framework.md.
- Choose streaming or non-streaming input from documented provider behavior. Do not
mark an engine as streaming merely because its response audio arrives in chunks.
- Design the configuration and audio conversion, then implement the custom
TTSEngine.
- Configure its fully qualified class path under the voice channel's
tts key in
credentials.yml. Keep secrets in environment variables.
- Add focused tests for configuration, request messages, audio conversion, lifecycle,
and provider errors.
- Run the project's relevant tests, lint/type checks, and Rasa configuration
validation. Report any validation that could not be run.
Select the synthesis mode
Use non-streaming input when the provider requires the complete text before synthesis:
- keep
streaming_input false;
- implement
synthesize() as the complete text-to-audio lifecycle;
- yield
RasaAudioBytes as provider audio becomes available.
Use streaming input only when the provider accepts multiple incremental text chunks in
one synthesis session:
- set
streaming_input = True;
- implement the installed contract's connection, text-chunk, text-done, and audio
streaming methods;
- preserve ordering and flush semantics documented by the provider.
Streaming audio output and streaming text input are different capabilities. A provider
that accepts one full text request and streams audio back still uses non-streaming
input.
Implementation contract
- Subclass the installed version's
TTSEngine and use its matching configuration type.
- Implement every abstract/required method in that installed version. This commonly
includes
synthesize, audio conversion, config construction, and default config.
- Convert every provider audio chunk to the channel-compatible
RasaAudioBytes format.
Account for encoding, sample rate, channel count, and container headers.
- Implement connection and streaming methods only when the selected mode needs them.
- Implement
signal_interrupt only when the provider documents an in-band cancel,
clear, or equivalent operation. Otherwise retain the base no-op and report the
limitation; do not invent socket-close/reconnect behavior.
- Close WebSockets and HTTP sessions reliably on completion, cancellation, and errors.
- Translate provider failures into the installed engine's expected TTS error type while
preserving actionable context and excluding secrets.
- Declare
required_env_vars and required_packages when supported by the installed
base class. Prefer existing project dependencies when they fit the documented API.
- Keep provider-specific settings in the config type. Prefer
language_map for
multilingual assistants when supported by the installed Rasa version.
- Do not edit Rasa's built-in engine registry for a project-level integration.
Configuration
Reference the custom class by module path:
# credentials.yml
browser_audio:
# ... channel configuration
tts:
name: addons.custom_tts.MyTTS
endpoint: wss://api.example.com/v1/speak
language: en-US
voice: example-voice
The module must be importable from the process that starts Rasa. Put secret values in
environment variables, document the required variable names, and never commit them to
credentials.yml.
For multilingual assistants, ensure every language_map key matches language or
additional_languages in config.yml.
Done criteria
- The selected synthesis mode matches documented provider behavior.
- Audio encoding, sample rate, and channel expectations are compatible.
- Resource cleanup and provider error handling are explicit.
- Interrupt support exists only when backed by a documented provider operation.
- The custom class imports and is referenced correctly from
credentials.yml.
- Secrets stay outside source-controlled configuration.
- Tests and available project validation pass.
1---2name: rasa-integrating-tts3description: Integrates a custom text-to-speech (TTS) provider with Rasa voice channels from provider documentation. Use when implementing a TTSEngine, adding streaming or non-streaming speech synthesis, converting provider audio to RasaAudioBytes, or configuring custom TTS credentials.4license: Apache-2.05---67# Integrating a Custom TTS Provider89The provider documentation is: **$documentation**1011Use the documentation as the source of truth for the provider protocol. If it is12missing, ask for the provider's TTS API documentation before implementing. Follow links13from it only when needed to resolve authentication, request/response messages, audio14formats, streaming behavior, interruption, or limits.1516## Workflow17181. Inspect the assistant's installed Rasa version and the actual `TTSEngine`,19 `TTSEngineConfig`, and `RasaAudioBytes` APIs. Follow those signatures when they20 differ from examples.212. Review existing custom speech components and project conventions before choosing a22 module path. Default to `addons/custom_tts.py` only when no convention exists.233. Read the provider documentation and complete the protocol analysis in24 [references/integration-framework.md](references/integration-framework.md).254. Choose streaming or non-streaming input from documented provider behavior. Do not26 mark an engine as streaming merely because its response audio arrives in chunks.275. Design the configuration and audio conversion, then implement the custom28 `TTSEngine`.296. Configure its fully qualified class path under the voice channel's `tts` key in30 `credentials.yml`. Keep secrets in environment variables.317. Add focused tests for configuration, request messages, audio conversion, lifecycle,32 and provider errors.338. Run the project's relevant tests, lint/type checks, and Rasa configuration34 validation. Report any validation that could not be run.3536## Select the synthesis mode3738Use non-streaming input when the provider requires the complete text before synthesis:3940- keep `streaming_input` false;41- implement `synthesize()` as the complete text-to-audio lifecycle;42- yield `RasaAudioBytes` as provider audio becomes available.4344Use streaming input only when the provider accepts multiple incremental text chunks in45one synthesis session:4647- set `streaming_input = True`;48- implement the installed contract's connection, text-chunk, text-done, and audio49 streaming methods;50- preserve ordering and flush semantics documented by the provider.5152Streaming audio output and streaming text input are different capabilities. A provider53that accepts one full text request and streams audio back still uses non-streaming54input.5556## Implementation contract5758- Subclass the installed version's `TTSEngine` and use its matching configuration type.59- Implement every abstract/required method in that installed version. This commonly60 includes `synthesize`, audio conversion, config construction, and default config.61- Convert every provider audio chunk to the channel-compatible `RasaAudioBytes` format.62 Account for encoding, sample rate, channel count, and container headers.63- Implement connection and streaming methods only when the selected mode needs them.64- Implement `signal_interrupt` only when the provider documents an in-band cancel,65 clear, or equivalent operation. Otherwise retain the base no-op and report the66 limitation; do not invent socket-close/reconnect behavior.67- Close WebSockets and HTTP sessions reliably on completion, cancellation, and errors.68- Translate provider failures into the installed engine's expected TTS error type while69 preserving actionable context and excluding secrets.70- Declare `required_env_vars` and `required_packages` when supported by the installed71 base class. Prefer existing project dependencies when they fit the documented API.72- Keep provider-specific settings in the config type. Prefer `language_map` for73 multilingual assistants when supported by the installed Rasa version.74- Do not edit Rasa's built-in engine registry for a project-level integration.7576## Configuration7778Reference the custom class by module path:7980```yaml81# credentials.yml82browser_audio:83 # ... channel configuration84 tts:85 name: addons.custom_tts.MyTTS86 endpoint: wss://api.example.com/v1/speak87 language: en-US88 voice: example-voice89```9091The module must be importable from the process that starts Rasa. Put secret values in92environment variables, document the required variable names, and never commit them to93`credentials.yml`.9495For multilingual assistants, ensure every `language_map` key matches `language` or96`additional_languages` in `config.yml`.9798## Done criteria99100- The selected synthesis mode matches documented provider behavior.101- Audio encoding, sample rate, and channel expectations are compatible.102- Resource cleanup and provider error handling are explicit.103- Interrupt support exists only when backed by a documented provider operation.104- The custom class imports and is referenced correctly from `credentials.yml`.105- Secrets stay outside source-controlled configuration.106- Tests and available project validation pass.