/attach route joins an already-answered LiveKit room and runs the bot pipeline. It is the entry point CXB Dialler uses once it has dialed, screened (ring/answer/AMD), and confirmed a live callee. CXB Core joins as the bot participant; the SIP leg (the callee) is already in the room.
This differs from LiveKit SIP outbound: with /attach, CXB Core does not dial — CXB Dialler owns dialing and pacing, CXB Core only runs the conversation.
Connection flow
Endpoint
X-CXB-Core-Secret header (403 without).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
room_name | string | Yes | Existing LiveKit room the callee is already in |
bot_id | string | Yes | Bot configuration to use |
to_number | string | No | Callee number (also the SIP participant identity suffix sip-{to_number}) |
from_number | string | No | Caller ID / DID |
config_url | string | No | Multi-client passthrough — overrides CXB_API_CONFIG_URL for the config fetch |
connected_event | object | No | CRM/campaign metadata forwarded to CXB API and used for Agent Desk handoff variables |
campaign_call_id | string | No | CXB Dialler lease identifier |
Response
Speaks immediately
Because the callee already answered before CXB Dialler attaches, the route sets thecall_answered event immediately (call_answered.set() before the pipeline starts). There is no ring-back gating — the bot can queue the opening message as soon as it joins.
Error-result fallback
If config fetch fails (config isNone), there is no bot to run post-call analysis. Instead of dropping the call silently, the route POSTs a minimal error result directly to CXB API’s /call-results (base URL derived from config_url or CXB_API_CONFIG_URL), matching the CallResultsPayload schema with zero duration and the determined disconnected_by. This ensures CXB Dialler/CXB API always learn the outcome of an attached call.
Capacity
The route returns429 At capacity when the worker has no free slot. /attach is in the fleet nginx 429-retry list (proxy_next_upstream ... http_429), so nginx retries another worker — safe because CXB Core returns 429 before starting any side effects.
Agent Desk handoff
The attached call supports human-agent escalation via thetransfer_call tool / agent_desk_callback, identical to the other LiveKit routes: enqueue a durable handoff to CXB API, start a hold worker, and set disconnected_by = "transfer_to_agent" on success.