The Sessions (Live) screen is a presence roster. It answers one question: right now, who is signed in, and what is each of them doing? Every row on the screen comes from a single call to adminSessions.list({ orgId }). That procedure reads the TeleQuick presence store in Redis and joins it to the dim_agent dimension, so each row carries both the live state (which changes second to second) and the durable agent identity (name, email, external id). The screen polls the procedure and re-renders; it never mutates anything. The query is scoped to one org and is disabled until an org is selected. There is no cross-org roster.

What a session row represents

One row is one agent, not one call. The row is keyed on agentId, so an agent appears exactly once no matter how many calls they have handled in the period you are looking at. That has two consequences worth knowing before you read the screen:
  • A row is a current snapshot. It has no history. If you need the sequence of states an agent moved through, this screen is the wrong tool — see Related.
  • At most one call id is attached to a row (currentCallId). The roster describes the call the agent is on now.

Session states

state is the field that drives the colour and the badge on the right of each row. The screen’s state filter enumerates the full set of values the procedure returns: ringing and on_call are the only two states that render as a live pill (the animated variant). That is deliberate: those are the two states where the agent is attached to a call leg and where the value is expected to change without you doing anything. Note which states pair with which companion field, because it tells you where the state came from:
  • ringing and on_call carry a currentCallId. They describe call activity. They are not modes an agent picks from a UI — an agent becomes ringing because a call was offered to them.
  • aux carries an auxReason (the free-form label the agent or your integration supplied, e.g. a break or training code). This is a selected state, which is why it has a reason attached.
  • acw (after-call work) carries neither. It is the wrap-up window that follows a call, and it is distinct from aux: an agent in acw is finishing the previous interaction, an agent in aux has deliberately made themselves unavailable.
The screen shows no transition arrows and exposes no way to change a state. The only transition evidence on the row is stateSinceMs — how long the agent has been where they are.

Row fields

These are the fields the roster actually reads off each row. The primary label degrades in a fixed order: displayName, then externalAgentId, then the raw agentId. An agent showing a raw id usually means the presence entry has no matching dim_agent row yet. stateSinceMs is a Unix timestamp in milliseconds. The screen renders it as an age relative to the browser’s clock: seconds below a minute, minutes below an hour, then hours. A missing or zero stateSinceMs renders as —. Because the age is computed client-side, a skewed workstation clock skews every age on the screen at once — if all the ages look implausible, suspect the clock before the roster.

How offline is detected

Presence is not a flag that an agent turns off on the way out. It is a Redis entry that has to be kept alive. The gateway writes the entry as the agent’s session reports in, and the entry expires on its own if those reports stop. So offline on this screen means there is no live presence entry for this agent, and the identity you see is coming from the dim_agent side of the join. Three different real-world situations collapse into that one value:
  • the agent signed out cleanly,
  • the agent’s client or softphone died and the presence entry lapsed,
  • the network between the agent and the gateway dropped long enough for the entry to lapse.
The roster cannot distinguish them. What it gives you instead is stateSinceMs: an agent who has been offline for seconds is interesting, an agent who has been offline for hours is just not working today. Expiry also explains a lag you will observe. An agent who yanks their network cable does not flip to offline at that instant. They flip when their presence entry lapses, and only then does the next poll show it. Treat offline as “we stopped hearing from this session”, not as “this session ended at this moment”. The empty state on the screen — “Agents appear here when they sign in” — is the other side of the same coin: an agent with no presence entry and nothing to join against contributes no row at all.

Refresh and polling behaviour

This screen polls. adminSessions.list is re-fetched on a fixed 8-second interval and the roster re-renders from whatever the latest response says. There is no push-based invalidation here. The original operator console invalidates this query from a QUIC push when presence changes; this Voice AI port has no realtime hook available, so it drops the push path and uses a tighter poll instead. The practical difference:
  • Worst-case staleness on this screen is one poll interval, not one round trip from the presence change.
  • The ages on the rows advance only when a poll lands, because stateSinceMs is re-rendered from the response rather than ticked locally. An age that appears to “jump” several seconds is the poll landing, not a data problem.
  • The poll runs whenever the screen is mounted and an org is selected. Leaving the screen open leaves the poll running.

Why the counters ignore the filters

The header reads N online · N ready · N on call · N aux. Those four numbers are computed from the full response, before the search box and the state filter are applied. Filtering the table down to one agent does not change them. That is intentional — the counters are the org-wide picture and the table below is your lens onto it — but it means the numbers do not add up the way you might expect:
  • online counts every row whose state is anything other than offline. So ringing and acw agents are included in online.
  • ready, on call, and aux are exact-state counts.
  • There is no ringing or acw counter. Those agents are visible in online but in none of the three breakdown numbers, so ready + on_call + aux is normally less than online. The difference is your ringing plus acw population.
  • offline rows are counted internally but not surfaced in the header strip.
If you want the ringing or acw head-count, select that value in the state filter and count the rows. The filters themselves behave as follows. The state dropdown is an exact match on state. The search box is a case-insensitive substring match against displayName, email, and externalAgentId joined together — so a query can span fields, and searching by raw agentId will not match. The two filters combine with AND.
  • Telemetry — the metrics, trace, and CDR streams, for the per-call record behind a currentCallId.
  • Telephony Metrics — AHT, ASA, and the other contact-centre numbers that aggregate the states on this screen.
  • Authentication — how the org scope on this query is established.