Standard bot call

Runtime stages

1

Ingress

A call reaches CXB Core 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

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

Pipeline build

CXB Core 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 an LLM-provider cached-content entry (or via the LLM provider’s prompt-cache-key hints) and the pipeline builder 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 CXB API. When post_call_cache_enabled is set, analysis/QC use a version-based explicit LLM-provider 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 CXB Core, CXB API, 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 CXB API 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/503CXB API routes/config.py, services/config_service.py, bot status, active hours.
Bot says wrong variableCXB API variable resolution, CRM pre-fetch, campaign CSV columns, bot prompt tokens.
Audio pipeline failsCXB Core route log, STT/LLM/TTS provider config, the pipeline builder.
Result missingCXB Core post-call finalization, result outbox, CXB API routes/results.py.
Recording does not playCXB Core upload settings, CXB API recording service, recording_key, storage settings.
Campaign attempt stuckCXB Dialler loop.py, health.py, campaign call status, stale reaper.