/attach route joins an already-answered LiveKit room and runs the bot pipeline. It is the entry point VoxDialler uses once it has dialed, screened (ring/answer/AMD), and confirmed a live callee. VoxCore joins as the bot participant; the SIP leg (the callee) is already in the room.
This differs from LiveKit SIP outbound: with /attach, VoxCore does not dial — VoxDialler owns dialing and pacing, VoxCore only runs the conversation.
Connection flow
Endpoint
X-VoxCore-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 VOXBRIDGE_CONFIG_URL for the config fetch |
connected_event | object | No | CRM/campaign metadata forwarded to VoxBridge and used for Agent Desk handoff variables |
campaign_call_id | string | No | VoxDialler lease identifier |
Response
Speaks immediately
Because the callee already answered before VoxDialler 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 VoxBridge’s /call-results (base URL derived from config_url or VOXBRIDGE_CONFIG_URL), matching the CallResultsPayload schema with zero duration and the determined disconnected_by. This ensures VoxDialler/VoxBridge 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 VoxCore 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 VoxBridge, start a hold worker, and set disconnected_by = "transfer_to_agent" on success.