What the activity rail includes and excludes
The rail callsreportsAllCalls.list with handlerKind: 'llm'. That
filter is fixed in the screen and is not user-adjustable.
Consequences worth internalising before you use this screen as evidence:
- A call missing from the rail is not a call that did not happen. It may have been handled by something other than an LLM handler, or it may have fallen off the first page.
- The rail is not a search tool. There is no date range, no filter box, and no pagination control. For arbitrary queries over call history, use the call reporting surfaces in the contact-center suite or query CDRs directly — see Telemetry.
The 25-row window and refresh cadence
The query is issued as{ orgId, handlerKind: 'llm', page: 1, perPage: 25 }
and re-runs every 15 seconds. Only page 1 is ever requested.
The counter pill in the card header shows rows.length — the number of
rows currently rendered, not a total call count for the org. When the
org has more than 25 AI-handled calls in range, the pill reads 25 and
stays there.
The header chevron collapses and expands the list body. Collapsing hides
the rows; it does not stop the query, so the rail stays current while
collapsed and the count in the pill keeps updating.
When the query returns no rows, the card shows the empty state
“No calls yet”.
Row fields
Each row is a button. The left side identifies the call, the right side summarises its outcome.
Duration is formatted by flooring to whole seconds and zero-padding, so
95 renders as 1:35. There is no separate talk / hold / wrap breakdown
on this screen — total_duration_sec is the only duration the rail reads.
Dispositions and colour tones
The rail does not define a disposition vocabulary of its own. It takes thelast_disposition string exactly as the call-reporting
pipeline recorded it, renders that string verbatim as the tag label, and
passes the same string to the shared statusTone helper to pick the
tag’s colour tone.
Two practical rules follow:
- Read the label, not the colour. The tone is a hint derived from
the string. A disposition that
statusTonedoes not recognise still renders — it just renders with the neutral default tone. A neutral tag means “unmapped”, not “neutral outcome”. - A missing tag is not a disposition. If
last_dispositionis empty or absent, the row shows no tag at all. That is a gap in the call record, not an outcome value.
statusTone in the console’s shared UI layer, not in
this screen.
How agent selection reorders the list
When an agent is selected in the console, the rail reorders the rows it already fetched so that the selected agent’s calls appear first. A row counts as the selected agent’s when either:last_handler_idequals the selected agent’s id, orlast_handler_display_nameequals the selected agent’s name.
Reading a transcript drawer
Clicking a row opens a right-hand drawer and issuesreportsCallDetails.byId with { orgId, callId }. The drawer header
shows the call_id in monospace so you can correlate with CDRs and
traces. Clicking the backdrop or the close button dismisses it; clicks
inside the drawer do not.
The drawer tolerates three response shapes, in this order:
detail.segmentsdetail.turns- the response itself, when it is an array
The speaker tag is tinted with the
ok tone when the resolved speaker
value is exactly llm; every other speaker value renders with the
default tone. That is the only colour signal in the drawer — it
distinguishes agent turns from everything else, not agent turns from
caller turns specifically.
If a segment resolves no body text from any of the three fields, the
drawer falls back to printing the raw segment object as JSON, truncated
to 200 characters, in monospace. Seeing that fallback means the segment
exists but uses field names this drawer does not know about — it is a
schema mismatch, not an empty turn.
While the query is in flight the drawer shows Loading….
When a call has no captured segments
If the resolved segment list is empty, the drawer shows:No transcript — This call has no captured segments.What that message does and does not tell you:
- It means
reportsCallDetails.byIdreturned a record whosesegments/turnswere empty or absent for thatcall_id. - It does not distinguish “the call was never transcribed” from “the transcript was captured elsewhere” from “the record no longer carries segments”. This screen surfaces the call-details record as-is; it does not create, backfill, or re-request segments, and it exposes no retention or capture setting.
call_id shown in the drawer
header against your CDRs and traces — both carry a call identifier and
the tenant, so the same call is addressable from
Telemetry.
Reading the voice relay data-plane panel alongside call rows
Above the Activity card sits a relay panel fed byobservability.relayHealth with ns: 'voice', polled every 5 seconds.
The two surfaces answer different questions, and reading them together is
the point of this layout:
An empty rail with a healthy relay reads very differently from an empty
rail with a silent relay — the first is “no traffic”, the second is
“traffic that may hear nothing”.
How the panel handles failure
relayHealth invokes the relay.metrics service with a 3 second
timeout. The short timeout is deliberate: the panel polls every 5 seconds,
and a slow engine must read as one missed tick rather than stacking up
requests.
If that invocation throws or times out, the procedure returns
{ configured: false, text: '' } and the panel renders as No data.
Read that state carefully. configured: false is returned on any RPC
failure, including a control-plane problem that has nothing to do with the
relay. A “No data” panel is a signal to check the metrics path itself; it
is not evidence that the relay is down.
Related
- Telemetry — CDRs, metrics, and traces for the same calls
- Telephony Metrics — definitions for the numbers behind call outcomes
- Authentication — how the console’s org scope (
orgId) is established