VEXYL AI

Realtime mode

Realtime mode hands the whole conversation to a single speech-to-speech model instead of running the speech pipeline of recognition, AI brain and synthesis. This chapter explains how to choose between the two modes, how to set up the two realtime providers (Gemini Live and LiteBot Live), how hang-up and transfer behave, and the separate Gateway Mode for OpenAI-compatible realtime services.

Pipeline or realtime

One gateway can serve both modes at the same time. The mode is decided per call.

Pipeline Realtime
Who listens and speaks Your chosen speech recognition and text-to-speech providers The model itself, one audio stream in and out
AI brain LiteBot or your custom endpoint, see AI brain Inside the model (Gemini Live) or inside LiteBot (LiteBot Live)
Voice Any text-to-speech provider and voice Only the voices the model offers
Tuning Barge-in, noise floor, filler sounds, transcript gate Handled by the model
Best for Control over every stage and regional voices Natural turn-taking and fast interruptions

In realtime calls no speech recognition or text-to-speech provider variable applies.

How the mode is chosen

The first matching rule wins, from most specific to least.

Order Source Result
1 Session metadata realtimeProvider set to gemini-live or litebot That realtime provider for this call
1 Session metadata realtimeProvider set to off, pipeline or an empty string Pipeline for this call
2 Bot configuration realtime.provider set to gemini-live Gemini Live
2 Bot configuration realtime.provider set to off, pipeline or empty Pipeline
3 REALTIME_PROVIDER The value of the variable; empty means pipeline

Metadata is posted per call, see HTTP API. The bot configuration is only consulted when the metadata does not name a provider.

REALTIME_PROVIDER=

Leave it empty for pipeline by default. Set it to gemini-live or litebot to make realtime the default for every call.

Gemini Live

Gemini Live runs the bot inside the gateway. The bot's prompt, tools, model and voice come from files you control.

REALTIME_PROVIDER=gemini-live
GEMINI_LIVE_API_KEY=<your-key>
Variable Default What it does
GEMINI_LIVE_API_KEY falls back to GEMINI_API_KEY Key used for the Gemini Live connection
GEMINI_LIVE_MODEL none Model used when the bot configuration names none
GEMINI_LIVE_VOICE none Voice used when the bot configuration names none
GEMINI_LIVE_TRANSCRIPTS true Send caller and bot transcripts to logs and webhooks
GEMINI_LIVE_INBOUND_GAIN 2.0 Gain applied to the caller's audio before it reaches the model
GEMINI_LIVE_VAD empty Empty uses the model's own speech detection; silero uses local speech detection instead
GEMINI_LIVE_DRAIN_MS 15000 Ceiling for letting the goodbye finish at hang-up
GEMINI_LIVE_DRAIN_STALL_MS 300 Abort the wait if the queued audio stops shrinking for this long
GEMINI_LIVE_PRICE_AUDIO_IN_PER_1M built-in table Audio input price in USD per million tokens
GEMINI_LIVE_PRICE_AUDIO_OUT_PER_1M built-in table Audio output price in USD per million tokens
GEMINI_LIVE_PRICE_TEXT_IN_PER_1M built-in table Text input price in USD per million tokens
GEMINI_LIVE_PRICE_TEXT_OUT_PER_1M built-in table Text output price in USD per million tokens

The price variables override the built-in rates used for call cost; see Webhooks and billing. The bundled default bot uses the model gemini-3.1-flash-live-preview; other Gemini Live models can be set per bot.

Bots, prompts and tools

Each bot is a JSON file that points at a prompt and lists the tools it may use. Your own files go under config/ next to the gateway. Bundled bots, prompts and tools ship inside the product and are loaded first.

Folder Holds
config/bots/*.json Your bot configurations
config/prompts/*.txt Your prompt files
config/tools/*.js Your tool modules
BOT_REGISTRY_EXTERNAL_DIR=./config
BOT_REGISTRY_HOT_RELOAD=true
DEFAULT_BOT_ID=default

With hot reload on, edits under config/ are picked up without a restart. A bot file looks like this.

{
  "id": "support",
  "promptFile": "support.txt",
  "realtime": {
    "provider": "gemini-live",
    "model": "gemini-3.1-flash-live-preview",
    "voice": "Aoede",
    "language": "en-US"
  },
  "tools": ["transferCall", "hangup"]
}

A tool module exports a name, a description, a parameters schema in JSON Schema form, and an asynchronous function that receives the parameters and the call context and returns the result. The bundled tools a bot can list are hangup and transferCall; add your own modules under config/tools/*.js and list their names.

Choosing a bot per call

Post a botId in the session metadata for the call. The id is case-sensitive; an unknown id falls back to the bot named by DEFAULT_BOT_ID.

curl -X POST http://127.0.0.1:8081/session/<call-uuid>/metadata \
  -H "Content-Type: application/json" \
  -d '{"botId": "support"}'

LiteBot Live

LiteBot Live makes the gateway a thin audio bridge to LiteBot's own voice endpoint. LiteBot hosts the model, the bot, the prompt, the tools, the voice, the language and the transcripts. The local bots, prompts and tools folders are ignored in this mode.

REALTIME_PROVIDER=litebot
LITEBOT_LIVE_URL=wss://<litebot-host>:<port>
LITEBOT_LIVE_API_KEY=<server-key>
LITEBOT_LIVE_BOT_ID=<bot-id>
Variable Default What it does
LITEBOT_LIVE_URL none, required ws:// or wss:// base address of your LiteBot server, for example wss://host:port; the gateway adds /voice itself
LITEBOT_LIVE_API_KEY none LiteBot server key used to authenticate
LITEBOT_LIVE_TOKEN none A JWT, as an alternative to the server key
LITEBOT_LIVE_BOT_ID falls back to LITEBOT_BOT_ID Bot to start on LiteBot
LITEBOT_LIVE_INBOUND_RATE 16000 Sample rate of caller audio; use 8000 if the bot is set up for 8 kHz
LITEBOT_LIVE_INBOUND_GAIN falls back to GEMINI_LIVE_INBOUND_GAIN Gain applied to the caller's audio
LITEBOT_LIVE_KICKOFF true Ask the bot to greet first once the session is ready
LITEBOT_LIVE_PING_MS 30000 Keep-alive interval; 0 disables it
LITEBOT_LIVE_CONTINUOUS_STREAM on Keep a steady audio stream flowing to LiteBot even when the handset sends nothing during silence
LITEBOT_LIVE_DRAIN_MS 15000 Ceiling for letting the goodbye finish when the session ends
LITEBOT_LIVE_DRAIN_STALL_MS 300 Abort the wait if the queued audio stops shrinking for this long
LITEBOT_LIVE_TRANSFER_TOOLS escalateToHuman Comma-separated tool names whose execution triggers a transfer

Leave LITEBOT_LIVE_CONTINUOUS_STREAM on. Some handsets stop sending audio during silence, and without a steady stream the model never decides the caller's turn has ended.

The gateway passes session details to LiteBot as variables so the bot can use them: caller name, caller number, channel and call direction, plus anything else you posted in the session metadata.

Hang-up and transfer in realtime mode

Both providers handle the end of a call the same way. When the bot decides to hang up, the gateway lets the goodbye finish playing and then closes the call. The wait is bounded by the drain ceiling (GEMINI_LIVE_DRAIN_MS or LITEBOT_LIVE_DRAIN_MS), and it ends early if the queued audio stops shrinking for the stall time. A hard safety net closes the call shortly after the ceiling in case anything is stuck.

Provider How a transfer starts
Gemini Live The bot calls the transferCall tool
LiteBot Live The tool result carries a transfer instruction, or the tool is named in LITEBOT_LIVE_TRANSFER_TOOLS

Where the call is sent is configured as for pipeline calls: TRANSFER_SIP_URI in SIP trunk for SIP-bridge calls, TRANSFER_ENDPOINT in Asterisk and AudioSocket for AudioSocket calls, and the caller-facing behaviour in Conversation behaviour.

Gateway Mode

Gateway Mode is a separate alternative to REALTIME_PROVIDER. It bridges an AudioSocket call straight to any WebSocket service that speaks the OpenAI Realtime protocol. There are no bots, tools or transfers in this mode; the remote service does everything.

Variable Default What it does
GATEWAY_MODE false true bridges every call to the remote service
LLM_WEBSOCKET_URL none, required WebSocket address of the realtime service
LLM_API_KEY none Key sent to the service
GATEWAY_INSTRUCTIONS You are a helpful AI assistant. Be concise and natural. System instructions for the session
GATEWAY_VOICE alloy Voice requested from the service
GATEWAY_MODALITIES audio,text Output types requested
GATEWAY_TEMPERATURE 0.8 Sampling temperature
GATEWAY_MAX_TOKENS 4096 Maximum tokens per response
GATEWAY_VAD_TYPE server_vad Speech detection type
GATEWAY_VAD_THRESHOLD 0.5 Speech detection sensitivity
GATEWAY_VAD_SILENCE_MS 500 Silence that ends a turn
GATEWAY_VAD_PREFIX_MS 300 Audio kept from before speech starts
GATEWAY_ENABLE_TRANSCRIPTION off Ask the service to transcribe the caller
GATEWAY_TRANSCRIPTION_MODEL whisper-1 Model used for that transcription
GATEWAY_LOG_TRANSCRIPTS off Write transcripts to the log
GATEWAY_COMMIT_ON_SILENCE off Commit the audio buffer when silence is detected
GATEWAY_MAX_ERRORS 10 Errors tolerated before the call is dropped