When a call begins, CXB Core fetches the bot’s full runtime configuration from CXB API. This single response carries everything the live pipeline needs: prompts, provider settings + injected API keys, tools, transfer config, variable namespaces, and post-call instructions. The same endpoint serves all four transports.
GET /api/v1/config/{bot_id}?caller_id=...&stream_id=...&connected_event={...}
X-CXBCore-Secret: {secret}
The route handler get_config() assembles the contract via build_config_for_call() in the config service.
The endpoint requires X-CXBCore-Secret. A mismatch returns 403. An unknown bot_id returns 404. A call arriving outside active hours returns 503 with detail outside_active_hours: ....

Query parameters

ParamDefaultPurpose
caller_id""Caller number, stored on the call skeleton.
stream_id""Transport stream identifier (used by WebSocket-transport CDR merge).
connected_event"{}"URL-encoded JSON of call/campaign/CRM variables. Parsed into a dict; malformed JSON falls back to {}.

connected_event

connected_event is the dynamic per-call payload. Every field becomes a call.* template variable (userrefno{{call.userrefno}}) and is stored on the call record for post-call variable access. It also seeds effective_crm (see Variable namespaces). Reserved control flags are popped from the event before variables are built:
FlagEffect
_campaign_session_idOverrides the generated session_id.
_skip_prefetchSkip the CRM pre-fetch HTTP call.
_skip_post_pushMark the call so the post-call CRM push is skipped.
_mock_crmTest-form CRM values, merged between connected_event and live pre-fetch.
_campaign_id / _campaign_call_id / _campaign_attempt / _campaign_run_numberCampaign linkage; also used to load callback context.
sip_candidate_headersRaw SIP X-headers, filtered by the bot’s sip_header_config into sip_context.

Build flow

Active-hours gating

If bot.active_hours.enabled is true, the gate runs before any expensive work (CRM pre-fetch, prompt rendering) and raises OutsideActiveHoursError (→ 503) when the call falls outside the window:
  • The bot timezone is resolved (invalid timezone falls back to UTC with a warning).
  • The current local weekday must be in active_hours.days (default: all 7 days).
  • The current local time must fall within start_timeend_time. Overnight windows (e.g. 22:0006:00) are handled when start > end.

Variable namespaces

Prompts, opening message, analysis/QC prompts, and agent-desk context are all rendered against a merged variable dict:
NamespaceSourceExample
system.*Current date/time in the bot timezonesystem.current_date, system.current_time, system.current_datetime, system.timezone
call.*Every connected_event field + filtered SIP header variables (+ callback context on callback attempts)call.userrefno, call.callerId
crm.*effective_crm = connected_event < _mock_crm < live CRM pre-fetch (later wins)crm.CUSTOMERNAME, crm.amount

Name transliteration

When a recognised name field is present (CUSTOMERNAME, name, customer_name, borrower_name, farmer_name, FIRSTNAME — first match wins), CXB API adds Devanagari variants for Hindi TTS via to_devanagari / to_firstname_devanagari: crm.CUSTOMERNAME_HI, crm.FIRSTNAME, crm.FIRSTNAME_HI, plus call.<field>_hi, call.<field>_firstname, call.<field>_firstname_hi.

Contract shape

build_config_for_call() returns a flat dict. Selected fields:
FieldNotes
session_idGenerated UUID unless _campaign_session_id overrides.
webhook_urlhttps://{host}/api/v1/call-results — where CXB Core posts results.
system_promptRendered prompt. For policy bots, built by build_policy_system_prompt; for direct-prompt bots, static + dynamic.
prompt_partsPresent for non-policy bots: mode, cache_enabled, static_system_prompt, dynamic_runtime_prompt, static_version, language-model cache-key/retention hints.
opening_messageRendered greeting.
vad, min_words_interruption, re_engagement, ambient_soundPipeline tuning.
stt / llm / ttsBot provider config with the matching api_key injected from system settings. (The turn-detecting STT engine reuses the streaming STT key.)
toolsBot tools, plus an injected detected_voicemail function when voicemail detection is enabled.
conversation_policy, transfer_numbers, transfer_targets, pre_transfer_messageTransfer / policy config.
post_call_analysis_prompt, qc_promptRendered post-call prompts (or null).
post_call_cache_enabled, post_call_cache_version, post_call_cachePost-call explicit-cache controls (combined + per-namespace analysis_version/qc_version).
live_prompt_cache_stateSlimmed {cache_name, expires_at} for the live prompt cache (see Live prompt cache).
sip_context, call_context, crm_contextFlat maps CXB Core uses for tool/transfer template resolution.
knowledgeRAG config (enabled only when both system + bot KB are enabled and KB IDs validate).
callback_detection_enabledTrue only when the linked campaign enables callback detection.
minio, agent_desk_enabled, agent_desk_context, auto_dispositions, voicemail_message, max_call_duration_seconds, timezone, bot_idMisc runtime fields.
The config response also has a side effect: it inserts the call skeleton into db.calls (status: "active") carrying session_id, bot_id, connected_event, sip_context, crm_data, integration_log, and campaign linkage. This is what the post-call results webhook later updates by session_id.

Redis caching + invalidation

The bot document and system settings are read through the cache service:
KeyTTLSet byInvalidated by
bot:{bot_id}3600s (BOT_CACHE_TTL)set_cached_bot on a Mongo readinvalidate_bot_cache on bot edits
system:settings3600sset_cached_settingsinvalidate_settings_cache on settings edits
Direct MongoDB writes to a bot or to system settings do not invalidate Redis. After an out-of-band DB update, the next call can serve a stale config for up to one hour. Always go through the admin API (which invalidates) or clear the cache key manually.

Operational checks

SymptomFirst place to check
CXB Core gets 403X-CXBCore-Secret mismatch between fleet .env and CXB API.
CXB Core gets 404bot_id does not exist, or wrong CXB API base URL.
Call rejected with 503 outside_active_hoursbot.active_hours window vs the bot timezone.
Prompt shows literal {{...}}Variable not present in any namespace; check connected_event / CRM pre-fetch.
Stale prompt or provider after an editRedis bot:{bot_id} cache not invalidated.
CRM data missing in promptcrm_pre_fetch config, _skip_prefetch, or pre-fetch timeout (integration_log).

CXB API overview

Control-plane responsibilities and module map.

Conversation policy

How policy-engine system prompts are assembled.

CXB Core bot config

How CXB Core consumes the runtime config.

Post-call variables

The full variable catalog across namespaces.