Base system instructions. The bridge appends per-call caller context (name, tenant, direction) and tool guidance.
OPENAI_FIRST_MESSAGE
unset
Deterministic opening line the agent speaks as its first response.
OPENAI_VAD
server_vad
Turn detection: server_vad (volume-based) or semantic_vad (the model decides when the turn is over). Anything else fails startup.
OPENAI_TRANSCRIPTION_MODEL
unset
Input-transcription model (e.g. gpt-4o-mini-transcribe). Required for user-side transcript logging.
OPENAI_TTS_VOICE
unset
Enables the deterministic governor goodbye (exact text via the standalone TTS endpoint). Without it, the goodbye is delegated to the agent.
OPENAI_TTS_MODEL
gpt-4o-mini-tts
TTS model for the goodbye line.
OPENAI_HOST
api.openai.com
Restricted to *.openai.com.
OPENAI_HOST_ALLOW_ANY
unset
Set to true only to point OPENAI_HOST at a deliberate trusted proxy/test host.
OPENAI_MCP_SERVERS
unset
JSON array of remote MCP tool entries ({server_label, server_url, allowed_tools?, authorization?, ...}) the Realtime API executes server-side. server_url must be https; require_approval defaults to "never". See Extending the Agent’s Tools.
Bridge-side hard cap per call, in minutes (fractional allowed). Keep it below 60: the Realtime API caps a session at 60 minutes server-side, and a call reaching that ceiling drops abruptly with agent-disconnected instead of a goodbye. The bridge warns at startup when this governor would not fire first.
GOODBYE_TEXT
a default line
The goodbye the bridge-side governor speaks.
GOODBYE_GRACE_MS
8000
How long to let the goodbye play out before ending the call when its duration is unknown (agent-said fallback). Always hard-bounded.
An OpenAI-compatible chat-completions endpoint with image input. Set it to enable path-2 vision (describe-then-answer). Validated at startup: must be a well-formed http(s) URL with no embedded credentials; a private/loopback IP is allowed (local Ollama/vLLM) but logged as a warning.
VISION_API_KEY
unset
Bearer key for the vision endpoint (local endpoints may not need one).
VISION_MODEL
unset
Vision model name (required when VISION_API_URL is set).
PEM cert/key for native TLS (wss://). Without both, the bridge serves plain WS and MUST be fronted by a TLS terminator.
HMAC_FRESHNESS_MS
60000
Allowed clock skew for the HMAC timestamp.
MAX_CONNECTIONS
0 (= 64)
Max concurrent connections.
MAX_CONNECTIONS_PER_IP
0 (= MAX_CONNECTIONS)
Per-IP cap. Defaults to the total cap (effectively off) because StandIn dials from a small set of IPs; set explicitly (with TRUST_PROXY_XFF=true behind a proxy you control) for a real limit.
TRUST_PROXY_XFF
false
Key the per-IP cap on the first X-Forwarded-For hop. Only behind a proxy you control.
PRE_START_TIMEOUT_MS
0 (= 10000)
Drop a connection that authenticates but never sends session.start.
WORKER_IDLE_TIMEOUT_MS
0 (= 90000)
Dead-peer window: end the call after this long without any worker message (the worker heartbeats every 30 s). Frees the call id for reconnect and closes the billed Realtime session.
LOG_TRANSCRIPTS
false
Log transcripts (still gated on Teams recording.status == "active"; user turns additionally need OPENAI_TRANSCRIPTION_MODEL).
LOG_LEVEL
info
debug | info | warn | error. An invalid value falls back to info.
The bridge also exposes GET /metrics (Prometheus text format, no auth): calls total/active, call seconds, upgrade rejections by cause, frames relayed each way, backpressure drops, and OpenAI connect failures. Like /healthz it is served on the same port - keep the port private to your network or scrape through your ingress.
Audio formats are not configurable: the wire is PCM 16 kHz by contract, and the session is pinned to PCM 24 kHz (the only rate the Realtime API supports); the bridge resamples between them internally.