Sessions and Handoff
A Session is a short-lived, per-subscriber handle. Reuse a session_id to
continue a conversation; allocate a new id to start a new one. Cross-node
handoff moves a call to another process while the call is still CallState.NEW,
before the voice connection opens.
Opening a session
Behavior is get-or-create. Server sessions have a ~30-minute sliding idle TTL; the next process_call / make_call / send_message transparently re-opens if needed.
Rules:
- Never share one session id across different subscribers.
- Sessions have a small participant cap - do not pile unrelated customers into one id.
- Dedup inbound calls with
IncomingCallNotification.call_idand inbound WhatsApp withIncomingMessage.id(at-least-once delivery).
Observability:
Attach or create a call
process_call attaches media credentials (URL + JWT). Until you answer / dial / connect / send_audio, state stays NEW. WhatsApp send does not open a voice connection. See WhatsApp Messaging.
Tutorial: cross-node handoff
Move media processing to another server before the voice connection opens. Node A receives the call, serializes with to_json() while still CallState.NEW, and publishes the payload. Node B reconstructs with Call.from_json() and answers - no SessionManager required on Node B.
This demo uses a file as the queue (/tmp/pending_call.json). Swap that for Redis, SQS, or your bus.
Node A - serialize while NEW
Node B - restore and answer
Run Node A first (leave it running). Then start Node B after the handoff file exists.
Single-process switcher (optional)
For local testing you can put both in one file and select with NODE=A / NODE=B:
Constraints:
to_json()after media opens raisesCallStateError.- Node B still needs network reachability to AgentDuet media endpoints carried in the payload.
- Do not answer on both nodes.
