Operators
Human-in-the-loop call monitoring, takeover, escalation management, and operator analytics.
Operators are human agents who can monitor, join, and take over live voice calls. The operator system provides escalation management, live call monitoring, call transcripts, and a full audit log, all built on the platform's world model with dual-entity event writes for independent state tracking.
Operator Lifecycle
Listen mode: the operator monitors the call silently. The AI agent continues handling the conversation. The operator is muted at the telephony level.
Takeover mode: the AI agent's audio output is muted (speaker suppressed) and the operator speaks directly with the caller. The agent's processing loop continues running. When the operator leaves or switches back to listen, the agent resumes immediately with no re-initialization.
Mode switching: toggling between listen and takeover is instantaneous. It modifies the telephony mute state and the agent speaker mute, not the underlying session. Operator transcripts during takeover are captured as human_segment turns via a dedicated per-participant STT stream.
Connection Methods
Operators can join calls via two methods, each using the conference architecture:
Phone
PSTN (telephony dials operator)
Dedicated per-participant stream
Higher (PSTN round-trip)
Remote operators, PSTN connectivity
Browser
WebRTC (direct browser audio)
Browser-handled
Lower (direct connection)
Desktop operators, real-time monitoring
Idempotent join: joining is idempotent. The same operator joining the same call returns the cached response. A different operator attempting to join the same call receives a conflict error (only one operator per call).
Browser Connection Flow
Request an access token via
POST .../operators/{operator_id}/access-token→ returns a JWT andconnect_params.Call
POST .../operators/{operator_id}/join-call→ caches operator metadata (no telephony API call for browser).Frontend creates a Voice SDK device with the token, registers, and calls
device.connect({ params: connectParams }).The telephony system calls the voice agent's call-control instruction endpoint, which detects the browser operator via the client identity in the token.
The endpoint returns conference join instructions; browser audio joins the existing conference directly.
For listen-mode joins, the operator is muted at the telephony level.
Three-Party Speaker Resolution
When an operator is on the call, three participants produce audio simultaneously. Speaker attribution uses a priority chain:
Every turn in the call record carries speaker_id and speaker_role, ensuring accurate transcript attribution even in three-party conversations.
Escalations
An escalation hands a call to a human. There are two paths:
Operator join
An operator joins the call from the dashboard or escalation queue (listen or takeover mode). Joining a call that has no open escalation creates one with trigger operator.
Agent call forwarding
The agent's context graph reaches a forwarding action (forward_call) and transfers the caller to a human phone number - for example when the caller asks for a person or the flow requires human judgment. See call forwarding.
Escalation Lifecycle
Dual-entity event writes: each escalation event is written to BOTH the call entity AND the operator entity, enabling independent state recomputation for each. The call entity tracks its escalation history; the operator entity tracks their availability and performance.
Event chain: Each escalation event supersedes the previous (escalation.requested → escalation.connected → escalation.handback → escalation.completed), forming a version chain with full temporal history.
escalation.requested
Escalation created
escalation_id, trigger, trigger source, reason
escalation.connected
Operator joins and takes over
Operator entity ID, connection type, response time
escalation.handback
Operator returns to listen mode
Agent resumes
escalation.completed
Call ends or operator explicitly completes
handle_time_seconds, outcome
Operator Flow (Complete)
Operator Guidance
Operators in listen mode can send text guidance to the agent without taking over the call:
The guidance is injected into the active session as a guidance event type. It interrupts the agent's current speech and the agent acts on the instruction immediately. This is distinct from operator takeover: the caller does not know a human intervened.
Permission: requires Operator:Update on the operator entity. The operator must belong to the same workspace as the call.
How it works: the platform delivers the guidance to the active voice session as an injected event (see session event injection). The operator's identity is recorded in the call transcript as the event sender.
Delivery status: the response includes a status field. "delivered" confirms the session received the guidance; "failed" indicates the guidance could not be delivered. The "queued_no_subscriber" semantics (call ended or session not yet listening) apply only to the session event-injection endpoint documented in session event injection.
Dashboard & Analytics
Dashboard
Composite view: operator status counts, active escalation count, daily escalation stats, recent escalations
Active Escalations
Paginated queue of active escalations with trigger and call context
Escalation Stats
Aggregation by period (day, week, month) and dimension (status, trigger, operator)
Performance
Operator rankings by response time, resolution rate, and average handle time
Call Transcript
Human-segment events for a specific operator's call participation
Audit Log
Every operator action is recorded as a world model event, providing a complete audit trail:
Join call
operator.joined_call
Call + Operator (status → busy)
Switch to takeover
operator.mode_changed
Call (audit)
Switch to listen
operator.mode_changed
Call (audit)
Leave call
operator.left_call
Call + Operator (status → online)
Complete escalation
escalation.completed
Call + Operator (handle time recorded)
Dual-entity writes: every escalation event is written to both entities to enable independent queries. "Show me all escalations for this call" and "show me all escalations this operator handled" are both O(1) entity reads, not cross-entity joins.
Entity Types
Operator Entity
Projected state from operator events:
status
Current availability (online, busy, offline)
profile
Name, contact info
total_escalations_handled
Lifetime count of escalations handled
avg_handle_time_seconds
Average escalation duration
last_call_at
Timestamp of the operator's last completed escalation call
last_status_change
Timestamp of the last availability transition
Call Entity (Escalation Fields)
The call entity's projected state includes escalation-specific fields:
escalation.status
Current escalation state (none, requested, connected, handback, completed)
escalation
Escalation detail: trigger, trigger source, requested/connected/completed timestamps, wait and handle time
human_segments
Operator speech transcripts captured during takeover
audit
Operator action audit summary (event count, latest event)
API Reference
Last updated
Was this helpful?

