Standard bot call

Runtime stages

1

Ingress

A call reaches VoxCore through one of the supported transports: WebSocket, LiveKit SIP inbound, LiveKit SIP outbound, Exotel WebSocket, or widget.
2

Capacity guard

The worker uses CallTracker to enforce the configured concurrency. In production the intended model is MAX_CONCURRENT_CALLS=1 per worker.
3

Config fetch

VoxCore calls VoxBridge’s config endpoint with bot ID, caller ID, stream/session metadata, SIP headers, or campaign variables.
4

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.
5

Conversation

Customer audio flows through STT, the LLM decides responses/tools, and TTS audio is sent back to the customer.
6

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.
7

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

FieldMeaning
session_idStable call identifier used across VoxCore, VoxBridge, recordings, and reports.
bot_idBot runtime config key.
connected_event / variablesPer-call variables from CRM/dialler/campaign.
disconnected_bySystem-level reason: bot, customer, voicemail, RNR, outside_hours, timeout, error, no_answer, rejected.
recording_keyStorage key used by VoxBridge to generate secure recording access URLs.
eventsTimeline of call events, tools, knowledge search, latency, and system decisions.
post_call_analysisLLM-derived business fields, including disposition when analysis runs.
qcQuality-control output when QC prompt is configured.

Auto disposition shortcut

Some calls skip expensive LLM post-call analysis:
  • disconnected_by is error, timeout, voicemail, or RNR
  • duration is under 5 seconds
  • customer never spoke (has_customer_message is false)
These calls use hardcoded or bot-configured auto dispositions (override via 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

SymptomStart with
Config 404/503VoxBridge routes/config.py, services/config_service.py, bot status, active hours.
Bot says wrong variableVoxBridge variable resolution, CRM pre-fetch, campaign CSV columns, bot prompt tokens.
Audio pipeline failsVoxCore route log, STT/LLM/TTS provider config, pipeline/factory.py.
Result missingVoxCore _post_call.py, result outbox, VoxBridge routes/results.py.
Recording does not playVoxCore upload settings, VoxBridge recording service, recording_key, storage settings.
Campaign attempt stuckVoxDialler loop.py, health.py, campaign call status, stale reaper.