VEXYL AI

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=http is required with bulbul:v4-flash: the default WebSocket transport drops the tail of sentences.
  • bulbul:v4-flash speakers are persona ids such as kavya_hi_conversational. SARVAM_TTS_SPEAKER_<LANG> overrides the speaker for one language.
  • The code default for SARVAM_TTS_MODEL is bulbul: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 example GOOGLE_VOICE_ML_IN. Keep Chirp3-HD voices so text-to-speech streams.
  • Do not set GOOGLE_TTS_VOICE_NAME on 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_MODEL picks 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_MODEL is gemini-2.5-flash-tts, which stays on the Cloud Text-to-Speech API. GEMINI_TTS_BACKEND=auto sends only 3.8 models to Vertex.
  • The service account needs access to Vertex AI. GEMINI_TTS_VERTEX_PROJECT overrides the project taken from the key file.
  • With streaming on, Vertex returns audio progressively and first audio arrives before the whole sentence is rendered; false falls back to batch.
  • The 3.8 models read the text verbatim, so a style prompt would be spoken aloud. The gateway ignores GEMINI_TTS_PROMPT on Vertex unless GEMINI_TTS_VERTEX_PROMPT=true.
  • Cost: billed per character at a per-model rate that changes on a published date, so check config/pricing.json before 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_v3 model automatically. ELEVENLABS_V3_ENABLED=false turns 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 the divya voice, 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_KEY falls back to GEMINI_API_KEY when unset.
  • The bot, prompt and tools come from the local bot configuration under config/bots/, config/prompts/ and config/tools/; DEFAULT_BOT_ID is 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:port or wss://host:port; the gateway adds the /voice path.
  • 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.1 is 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