Standard bot call
Runtime stages
Ingress
A call reaches VoxCore through one of the supported transports: WebSocket, LiveKit SIP inbound, LiveKit SIP outbound, Exotel WebSocket, or widget.
Capacity guard
The worker uses
CallTracker to enforce the configured concurrency. In production the intended model is MAX_CONCURRENT_CALLS=1 per worker.Config fetch
VoxCore calls VoxBridge’s config endpoint with bot ID, caller ID, stream/session metadata, SIP headers, or campaign variables.
Pipeline build
VoxCore creates STT, LLM, TTS, VAD, turn detection, transcript, recorder, tool runtime, and post-call state for that call only. When live prompt caching is active, the static policy/system prompt is served from a Gemini/Vertex
CachedContent entry (or via OpenAI prompt_cache_key hints) and factory.py passes tools=NOT_GIVEN so tools and the system instruction are folded into the cached content rather than sent per request.Conversation
Customer audio flows through STT, the LLM decides responses/tools, and TTS audio is sent back to the customer.
Termination
The call ends because the customer hung up, bot ended, voicemail was detected, RNR/dead air occurred, max duration hit, SIP failed, or an error happened.
Post-call
Shared post-call logic applies auto dispositions, optionally runs LLM analysis and QC, uploads/links recording, and sends results back to VoxBridge. When
post_call_cache_enabled is set, analysis/QC use a version-based explicit Gemini cache (post_call_cache_version) so the static prompt template is reused across calls and only re-created when the template changes.Important fields
| Field | Meaning |
|---|---|
session_id | Stable call identifier used across VoxCore, VoxBridge, recordings, and reports. |
bot_id | Bot runtime config key. |
connected_event / variables | Per-call variables from CRM/dialler/campaign. |
disconnected_by | System-level reason: bot, customer, voicemail, RNR, outside_hours, timeout, error, no_answer, rejected. |
recording_key | Storage key used by VoxBridge to generate secure recording access URLs. |
events | Timeline of call events, tools, knowledge search, latency, and system decisions. |
post_call_analysis | LLM-derived business fields, including disposition when analysis runs. |
qc | Quality-control output when QC prompt is configured. |
Auto disposition shortcut
Some calls skip expensive LLM post-call analysis:disconnected_byiserror,timeout,voicemail, orRNR- duration is under 5 seconds
- customer never spoke (
has_customer_messageis false)
BotConfig.auto_dispositions). This keeps failed/no-speech calls cheap and predictable.
The
no_customer_message auto disposition fires whenever the customer never spoke, regardless of who disconnected (customer hangup, bot hangup, or short call). It triggers on not has_customer_message only — not on duration < 5 when the customer did speak.Where to debug
| Symptom | Start with |
|---|---|
| Config 404/503 | VoxBridge routes/config.py, services/config_service.py, bot status, active hours. |
| Bot says wrong variable | VoxBridge variable resolution, CRM pre-fetch, campaign CSV columns, bot prompt tokens. |
| Audio pipeline fails | VoxCore route log, STT/LLM/TTS provider config, pipeline/factory.py. |
| Result missing | VoxCore _post_call.py, result outbox, VoxBridge routes/results.py. |
| Recording does not play | VoxCore upload settings, VoxBridge recording service, recording_key, storage settings. |
| Campaign attempt stuck | VoxDialler loop.py, health.py, campaign call status, stale reaper. |