Skip to main content
To use a speech provider that is not built in, write your own engine. Custom engines are in beta. You write a Python class that subclasses ASREngine or TTSEngine, and set name to its module path (path.to.module.ClassName). Every other key under asr: or tts: is passed to your class’s from_config_dict as a dictionary.
integrations.yml
Put the code in a package next to agent.yml, here addons/ with an __init__.py, and start rasa from the project root so the module can be imported.

Custom speech recognition

Subclass ASREngine from rasa.core.channels.voice_stream.asr.asr_engine. The engine receives the caller’s audio as RasaAudioBytes, which may need converting to the format your service expects, and turns the service’s messages into ASREvents.
addons/custom_asr.py
engine_event_to_asr_event returns UserIsSpeaking(text) for interim transcripts and NewTranscript(text) for final ones, both from rasa.core.channels.voice_stream.asr.asr_event.

Emit a complete caller turn

Some services mark each recognized word or segment as final before the caller has finished. Do not map each of those segments to NewTranscript: the channel can process each event as a separate user turn. Accumulate the segments and emit a transcript at the provider’s end-of-utterance boundary. The is_final field in the example above assumes the example service finalizes a complete turn. Also handle short turns whose final message contains text but had no interim update. Test that sequence, successive turns, and empty provider messages offline. A missing interim transcript must not discard the words in a final message. See Test the speech path separately.

Custom speech synthesis

Subclass TTSEngine from rasa.core.channels.voice_stream.tts.tts_engine. The engine must produce RasaAudioBytes, in the audio format the channel passes to from_config_dict.
addons/custom_tts.py
synthesize handles whole utterances, such as the greeting. To also start speaking while the model is still writing the reply, set streaming_input = True and implement:

Config and environment variables

Define your own settings as fields on a config class that extends ASREngineConfig or TTSEngineConfig, as MyASRConfig and MyTTSConfig do above. Settings from integrations.yml are validated against it and are available as self.config. The base classes already provide language_map, and timeout for speech synthesis. Set required_env_vars to the environment variables your service needs, and required_packages to the Python packages it imports. The engine fails to start with the missing name if one is absent:
Keys in language_map must be the agent’s language codes, as for the built-in engines. Your engine reads the matching entry for the current language from self.current_language_config, which has engine_language_key (the entry’s language), voice, and model.

Learn from a community adapter

The community voice vendor router contains examples of custom engines, including Speechmatics recognition and audio-format conversion. Its Speechmatics adapter source shows how to assemble final segments when end-of-utterance detection is configured. Read this implementation alongside the Mantle interface above when writing your own adapter. This is community example code, not a built-in Mantle provider or a compatibility guarantee. Read its dependency pins, setup instructions, and per-adapter test status before adapting it. Install only the optional dependencies needed for your chosen provider, then verify the engine against your Rasa version and channel audio format. The examples on this page define the Mantle extension interface; the community package does not change that interface.

See also