Standard bot call
Runtime stages
Ingress
A call reaches CXB Core 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
CXB Core calls CXB API’s config endpoint with bot ID, caller ID, stream/session metadata, SIP headers, or campaign variables.
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.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 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
| Field | Meaning |
|---|---|
session_id | Stable call identifier used across CXB Core, CXB API, 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 CXB API 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 | CXB API routes/config.py, services/config_service.py, bot status, active hours. |
| Bot says wrong variable | CXB API variable resolution, CRM pre-fetch, campaign CSV columns, bot prompt tokens. |
| Audio pipeline fails | CXB Core route log, STT/LLM/TTS provider config, the pipeline builder. |
| Result missing | CXB Core post-call finalization, result outbox, CXB API routes/results.py. |
| Recording does not play | CXB Core upload settings, CXB API recording service, recording_key, storage settings. |
| Campaign attempt stuck | CXB Dialler loop.py, health.py, campaign call status, stale reaper. |