Configuration recipes
Copy one block into .env, fill in the keys, and nothing else is required. Every block extends the minimal .env from Quick start: binary, so the ports, TELEPHONY_MODE and LICENSE_KEY lines are the same in each recipe. Leave LICENSE_KEY= empty to stay on the Free tier.
Restart the gateway after editing .env. Values in angle brackets are placeholders you replace.
Every recipe uses a LiteBot bot as the AI brain. To use your own HTTP endpoint instead, replace the LLM_PROVIDER and LITEBOT_* lines with LLM_PROVIDER=custom and CUSTOM_LLM_URL=https://<your-endpoint>; the request and response format is in AI brain.
The gateway bills each call per provider and model with built-in rates. To override them, create config/pricing.json from the example in Webhooks and billing and edit it.
Recipe a: Indian languages with Sarvam
Sarvam does speech-to-text and text-to-speech, and LiteBot is the AI brain.
HTTP_PORT=8081
AUDIOSOCKET_PORT=8080
# sip_bridge or both: see chapter 05
TELEPHONY_MODE=audiosocket
LICENSE_KEY=
DEFAULT_LANGUAGE=ml-IN
STT_PROVIDER=sarvam
TTS_PROVIDER=sarvam
SARVAM_API_KEY=<sarvam-key>
SARVAM_TTS_MODEL=bulbul:v4-flash
SARVAM_TTS_STREAM_TRANSPORT=http
SARVAM_TTS_SPEAKER=kavya_hi_conversational
SARVAM_TTS_SPEAKER_ML_IN=shilpa_hi_narration
LLM_PROVIDER=litebot
LITEBOT_API_URL=http://<litebot-host>:3345
LITEBOT_BOT_ID=support
SARVAM_TTS_STREAM_TRANSPORT=httpis required withbulbul:v4-flash: the default WebSocket transport drops the tail of sentences.bulbul:v4-flashspeakers are persona ids such askavya_hi_conversational.SARVAM_TTS_SPEAKER_<LANG>overrides the speaker for one language.- The code default for
SARVAM_TTS_MODELisbulbul:v3, which takes plain speaker names. Do not mix a v3 name with the v4-flash model. - Speech-to-text and text-to-speech both stream, so audio starts before the full reply is synthesized.
- Cost: billed per character of speech (text-to-speech) and per listening time (speech-to-text). Chapters 08 and 09 tune the voice.
Recipe b: Google speech and Chirp3-HD voices
Google handles speech-to-text and text-to-speech, and LiteBot is the AI brain.
HTTP_PORT=8081
AUDIOSOCKET_PORT=8080
# sip_bridge or both: see chapter 05
TELEPHONY_MODE=audiosocket
LICENSE_KEY=
DEFAULT_LANGUAGE=ml-IN
STT_PROVIDER=google
GOOGLE_STT_MODEL=latest_long
TTS_PROVIDER=google
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
GOOGLE_VOICE_ML_IN=ml-IN-Chirp3-HD-Despina
LLM_PROVIDER=litebot
LITEBOT_API_URL=http://<litebot-host>:3345
LITEBOT_BOT_ID=support
- One service-account file serves both speech-to-text and text-to-speech.
- Set voices per language with
GOOGLE_VOICE_<LANG>, for exampleGOOGLE_VOICE_ML_IN. Keep Chirp3-HD voices so text-to-speech streams. - Do not set
GOOGLE_TTS_VOICE_NAMEon a bot that speaks more than one language: Google rejects a voice that does not match the language and the turn plays silence. - Google speech-to-text streams and is slightly slower to finalize a turn than Sarvam;
GOOGLE_STT_MODELpicks the recognizer. - Cost: billed per audio minute (speech-to-text) and per character (text-to-speech). See chapters 08 and 09.
Recipe c: Gemini 3.8 voices with Sarvam listening
Sarvam transcribes, Gemini 3.8 text-to-speech speaks, and LiteBot is the AI brain. The 3.8 models run on Vertex AI in location global.
HTTP_PORT=8081
AUDIOSOCKET_PORT=8080
# sip_bridge or both: see chapter 05
TELEPHONY_MODE=audiosocket
LICENSE_KEY=
DEFAULT_LANGUAGE=ml-IN
STT_PROVIDER=sarvam
SARVAM_API_KEY=<sarvam-key>
TTS_PROVIDER=gemini
GEMINI_TTS_MODEL=gemini-3.8-flash-lite-tts
GEMINI_TTS_BACKEND=auto
GEMINI_TTS_STREAMING=true
GEMINI_TTS_VOICE_NAME=Kore
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
LLM_PROVIDER=litebot
LITEBOT_API_URL=http://<litebot-host>:3345
LITEBOT_BOT_ID=support
- The code default for
GEMINI_TTS_MODELisgemini-2.5-flash-tts, which stays on the Cloud Text-to-Speech API.GEMINI_TTS_BACKEND=autosends only 3.8 models to Vertex. - The service account needs access to Vertex AI.
GEMINI_TTS_VERTEX_PROJECToverrides the project taken from the key file. - With streaming on, Vertex returns audio progressively and first audio arrives before the whole sentence is rendered;
falsefalls back to batch. - The 3.8 models read the text verbatim, so a style prompt would be spoken aloud. The gateway ignores
GEMINI_TTS_PROMPTon Vertex unlessGEMINI_TTS_VERTEX_PROMPT=true. - Cost: billed per character at a per-model rate that changes on a published date, so check
config/pricing.jsonbefore relying on it. See Text to speech.
Recipe d: Voice preference variants
Each block replaces the TTS_PROVIDER and SARVAM_TTS_* lines of recipe a. Keep SARVAM_API_KEY (listening still uses it) and the brain settings.
ElevenLabs:
TTS_PROVIDER=elevenlabs
ELEVENLABS_API_KEY=<elevenlabs-key>
ELEVENLABS_MODEL=eleven_flash_v2_5
ELEVENLABS_VOICE_ID=<voice-id>
ELEVENLABS_VOICE_ML_IN=<malayalam-voice-id>
Smallest.ai:
TTS_PROVIDER=smallest
SMALLEST_API_KEY=<smallest-key>
SMALLEST_TTS_VOICE_ID=avni
SMALLEST_TTS_STREAMING=true
SMALLEST_TTS_COMPLETE_BACKOFF_MS=0
OpenRouter:
TTS_PROVIDER=openrouter
OPENROUTER_API_KEY=<openrouter-key>
OPENROUTER_TTS_MODEL=mistralai/voxtral-mini-tts-3-0
OPENROUTER_TTS_VOICE=voice_3150
- ElevenLabs streams with a persistent socket; languages the fast model cannot speak are routed to the
eleven_v3model automatically.ELEVENLABS_V3_ENABLED=falseturns that off. - Smallest.ai streams 8 kHz audio natively. Keep
SMALLEST_TTS_COMPLETE_BACKOFF_MS=0, otherwise each sentence waits several seconds for the end-of-text frame. Avoid thedivyavoice, which truncates long text. - OpenRouter is batch only, so the first audio is slower than the streaming providers. One key reaches several vendors; choose with
OPENROUTER_TTS_MODEL. The voice id is model specific. - Cost: each provider bills by its own unit; the gateway has built-in rates per provider and model, overridable in
config/pricing.json. - Voice selection per call and per language is in Text to speech.
Recipe e: Realtime with Gemini Live
One streaming model listens, thinks and speaks. No separate speech or brain provider is used.
HTTP_PORT=8081
AUDIOSOCKET_PORT=8080
# sip_bridge or both: see chapter 05
TELEPHONY_MODE=audiosocket
LICENSE_KEY=
REALTIME_PROVIDER=gemini-live
GEMINI_LIVE_API_KEY=<gemini-key>
GEMINI_LIVE_MODEL=gemini-3.1-flash-live-preview
GEMINI_LIVE_VOICE=Aoede
DEFAULT_BOT_ID=default
GEMINI_LIVE_API_KEYfalls back toGEMINI_API_KEYwhen unset.- The bot, prompt and tools come from the local bot configuration under
config/bots/,config/prompts/andconfig/tools/;DEFAULT_BOT_IDis used when a call names no bot. - Realtime mode is one model: the lowest turn latency, but fewer provider choices than the pipeline recipes.
- Cost: billed by tokens of audio and text. Per-million-token rates are set with the
GEMINI_LIVE_PRICE_*variables. - Details and tools are in Realtime mode.
Recipe f: Realtime with LiteBot Live
LiteBot hosts the live session, bot, prompt and tools. The gateway only carries audio.
HTTP_PORT=8081
AUDIOSOCKET_PORT=8080
# sip_bridge or both: see chapter 05
TELEPHONY_MODE=audiosocket
LICENSE_KEY=
REALTIME_PROVIDER=litebot
LITEBOT_LIVE_URL=ws://<litebot-host>:3345
LITEBOT_LIVE_API_KEY=<litebot-server-key>
LITEBOT_LIVE_BOT_ID=support
- Write the URL as a bare
ws://host:portorwss://host:port; the gateway adds the/voicepath. - The model, voice, language and tools are all set on the LiteBot side. Local bot configuration is ignored.
- Hangup and transfer requested by a LiteBot tool are carried out by the gateway; goodbye audio plays out before the call is torn down.
- Cost: reported by LiteBot for the session; see Realtime mode.
Recipe g: Add the browser widget
Append these lines to any recipe above to let a web page talk to the bot.
WEBSOCKET_AUDIO_ENABLED=true
WEBSOCKET_AUDIO_PORT=8082
WEBSOCKET_AUDIO_API_KEY=<random-secret>
WEBSOCKET_AUDIO_ALLOWED_ORIGINS=https://www.example.com
WEBSOCKET_AUDIO_HOST=127.0.0.1
- Every browser session takes one of the call slots your licence allows, so an open endpoint is free speech spend for strangers. Always set the API key and the allowed origins.
WEBSOCKET_AUDIO_HOST=127.0.0.1is for a reverse proxy on the same host that terminates TLS. Without a proxy leave it unset (the default is all interfaces).- Generate the key with
openssl rand -hex 24. - Page code and proxy setup are in Browser widget.
Which recipe
| Use case | Recipe |
|---|---|
| Indian-language phone bot, lowest effort | a |
| Enterprise Google account or compliance needs | b |
| Natural Gemini voices with Sarvam listening | c |
| A specific voice vendor (ElevenLabs, Smallest.ai, OpenRouter) | d |
| One-model conversation, bot defined locally | e |
| One-model conversation, bot defined in LiteBot | f |
| Talk to the bot from a web page | g, added to another recipe |
| SIP trunk instead of Asterisk | any recipe plus SIP trunk |