The agent console is the workspace for human agents handling escalated/handoff calls. It is gated by the ADK feature flag and the agent/supervisor roles, and is served under /agent-console. The console persists across page refresh and is built from several pieces.

Surfaces

SurfaceComponentRole
Layout + heartbeatAgent layoutshell, nav, heartbeat, call recovery
Status toggleAgent status toggleavailable/away/busy selector
Queue ticker + drawerQueue tickerscrolling waiting list
Queue cardQueue cardaccept/decline/reject a call
Incoming modalIncoming call modalfull-screen accept prompt
Waiting homeAgent queue pageidle “waiting for call” screen
Active callAgent call page + call panellive LiveKit call + wrap-up

Status toggle

The status toggle reads/writes status via getAgentStatus / setAgentStatus. Agents can select Available, Away, or Busy. The control locks (read-only) while in a non-selectable state — on_call, wrap_up, offline, or disconnected — and shows a colored dot per status. On a failed update it re-reads the server status and surfaces an error.

Heartbeat and call recovery

The agent layout calls heartbeatAgent every 15 seconds and updates the agent status from the response. On pagehide/unmount it marks the agent offline. When the status is active (on_call, wrap_up, disconnected) and the agent is not already on the call page, the layout recovers the current call via fetchCurrentCall and redirects to /agent-console/call, so a refresh or stray navigation cannot abandon a live call or skip a pending wrap-up.

Queue ticker, drawer, and incoming modal

The queue ticker polls fetchQueue every 3 seconds. It shows a “N waiting” label and a scrolling ticker of callers. Clicking opens a drawer of queue cards. The oldest waiting call is treated as primary and — when the agent is available and not on the call page — pops the incoming call modal. Per-call actions (shared by card and modal):
ActionAPIEffect
AcceptacceptCallstores call in sessionStorage, navigates to /agent-console/call
DeclinedeclineCallremoves from this agent’s queue (may terminate if no agents left)
RejectrejectCallends the call with a reason
The incoming modal renders rich handoff context: customer name, escalation reason, summary, lead classification, transfer tags, flags, ordered customer fields, and a variables preview.

Active call and wrap-up

The agent call page restores call state from location.state or sessionStorage (and recovers from fetchCurrentCall on refresh). It captures mic audio, mixes in remote tracks, and records the call locally. The call panel joins the LiveKit room, lists connected participants (filtering out service identities like hold-worker, core-bot, ai-copilot), and offers mute and end-call controls. When Agent Assist is enabled it shows the Agent Assist panel (live suggestions + transcript over LiveKit data messages). Wrap-up is enforced: when the call ends (agent hangup or customer disconnect, detected via LiveKit callbacks with a 3-second state-poll fallback), a modal requires a Disposition (Resolved, Transferred, Escalated, No Resolution, Callback Scheduled) and Comments before submit. Finalize tears down via endCall, then best-effort uploads the recording via uploadRecording.

Agent history & analytics

An agent’s handled calls and personal stats.

Supervisor dashboard

Listen, barge in, and force-end.

Agent Assist

Phrase-triggered suggestion moments.

Agent Desk (CXB API)

Queue, rooms, and supervisor controls server-side.