Voice Notes
Transcribe inbound voice messages on Telegram, Slack, WhatsApp, Discord, and Signal automatically
Voice notes sent to your bot on Telegram, Slack, WhatsApp, Discord, or Signal are transcribed and handed to the agent as plain text — on by default, with a visible placeholder when transcription is off or fails.
from praisonaiagents import Agent
from praisonai.bots import TelegramBot
agent = Agent(name="assistant", instructions="Be helpful.")
bot = TelegramBot(token="YOUR_TOKEN", agent=agent)
# STT is on by default — send a voice note to the bot,
# the agent replies to the transcribed text.
import asyncio
asyncio.run(bot.start())The user taps the microphone and sends a voice note; the bot transcribes it with whisper-1 and the agent replies to the recognised text.
Quick Start
- Level 1 — Bool shorthand
STT is on by default. Turn it off per channel with
stt: false.yaml channels: telegram: platform: telegram token: ${TELEGRAM_BOT_TOKEN} stt: true # default; set false to opt out - Level 2 — Dict
Tune behaviour with a dict — echo the transcript, force a language, or override the model.
yaml channels: telegram: platform: telegram token: ${TELEGRAM_BOT_TOKEN} stt: enabled: true echo_transcripts: true language: en model: openai/whisper-1 - Level 3 — SttConfigSchema
Build the channel config in Python with the validated schema.
python from praisonai_bot.bots._config_schema import ( ChannelConfigSchema, SttConfigSchema, ) channel = ChannelConfigSchema( platform="telegram", token="${TELEGRAM_BOT_TOKEN}", stt=SttConfigSchema( enabled=True, echo_transcripts=True, language="en", model="openai/whisper-1", ), )
How It Works
The adapter downloads the voice note, transcribes it, and forwards the transcript — never dropping the turn.
| Step | What happens |
|---|---|
| Download | Adapter caches the audio through the SSRF-safe media cache (kind="audio") |
| Transcribe | transcribe_media_path calls stt_tool → AudioAgent.transcribe (whisper-1 by default) |
| Success | Transcript passed to agent.chat(transcript); echoed back first when echo_transcripts: true |
| Failure / off | The [Voice message received] placeholder reaches the agent — the turn is never silently dropped |
Configuration Options
Fields from SttConfigSchema / SttConfig.
| Option | Type | Default | Description | |
|---|---|---|---|---|
enabled | bool | true | Transcribe inbound audio. On by default. | |
echo_transcripts | bool | false | Echo the recognised text back to the user. | |
language | `str \ | None` | null | Optional forced language code ("en", "es", …). |
model | `str \ | None` | null | Optional STT model override (default: openai/whisper-1). |
The bare shorthand stt: true / stt: false is accepted as {"enabled": <bool>}.
Choosing a configuration
Per-Platform YAML
channels:
telegram:
platform: telegram
token: ${TELEGRAM_BOT_TOKEN}
stt:
enabled: true
echo_transcripts: true
language: en
model: openai/whisper-1channels:
slack:
platform: slack
token: ${SLACK_BOT_TOKEN}
app_token: ${SLACK_APP_TOKEN}
stt:
enabled: true
language: enchannels:
whatsapp:
platform: whatsapp
token: ${WHATSAPP_TOKEN}
stt:
enabled: true
echo_transcripts: truechannels:
discord:
platform: discord
token: ${DISCORD_BOT_TOKEN}
stt:
enabled: true
language: enchannels:
signal:
platform: signal
account: ${SIGNAL_ACCOUNT}
bridge_url: ${SIGNAL_BRIDGE_URL} # optional; default http://localhost:8080
stt:
enabled: true
language: enDiscord and Signal specifics
Both adapters transcribe the first audio/* attachment of a message that has no text, after the access gates run.
- Discord — if a message carries both text and audio, the text wins; voice is only transcribed for empty-text messages.
- Signal — audio is fetched from the operator-configured
signal-cli-rest-apibridge. Keep the bridge on localhost or a private network, as in the Signal Bot setup.
When STT Is Off or Fails
Voice notes were previously dropped silently when transcription was unavailable. Now the adapter substitutes the [Voice message received] placeholder so the agent always gets the turn — it can ask the user to retype, fall back to another channel, or acknowledge the message.
User: [voice note] (STT disabled)
Agent: receives "[Voice message received]" and can reply
"I got your voice note but can't transcribe it here —
could you type it out?"See fixed issue #2721 for context.
Best Practices
Set language when you know it
Forcing language: en (or the relevant code) improves transcription accuracy and speed over auto-detection.
stt:
enabled: true
language: enEnable echo_transcripts for accessibility
echo_transcripts: true sends the recognised text back to the user so they can confirm what the bot heard — helpful for accessibility and correcting mis-hearings.
stt:
enabled: true
echo_transcripts: trueOpt out on privacy-sensitive channels
Turn STT off where voice content must not leave the device or reach a third-party STT provider.
stt:
enabled: falseShip a fallback plan
The [Voice message received] placeholder means the agent still gets the turn when transcription is off or fails. Give the agent instructions to handle that case gracefully.
agent = Agent(
name="assistant",
instructions="If a voice note can't be transcribed, ask the user to type it.",
)Related
The outbound counterpart — speak the agent’s reply back as a native voice note.
Inbound MediaForward user photos and documents to your agent’s vision capability
Audio Toolsstt_tool, tts_tool, and AudioAgent.transcribe
Built-in and custom bot chat commands
GatewayUnified gateway and control-plane overview