Where usage rows are written
The panel is one query, keyed by the call sid of the drive that is running:- The query does not run until a call exists. Test drive starts a call
with
telephony.originate(trunk__test_drive__, destinationagent:<agentId>@<orgId>, appAI_BIDIRECTIONAL_STREAM) and only then has acall_sidto ask about. Before Start, the panel has nothing to show because nothing has been asked for. - One callβs numbers can never leak into another callβs panel. Switching agents in the left rail keeps the screen mounted, so the screen clears the call sid explicitly; starting a second drive mints a new sid. Either way the query re-keys and the previous callβs totals disappear rather than being carried forward.
rows holds the individual usage records; totals is their sum. A row lands
as a turn completes, so the panel grows during the call rather than appearing
all at once at the end. The console polls it while the call is live and
re-reads it after Stop, so the totals settle on the final turn instead of
freezing wherever the last poll happened to land.
A Test drive call has no call row and no SIP dialog behind it β the only
server-side record of ownership is the voice:owner:<call_sid> marker
telephony.originate writes for the test-drive trunk. Usage is keyed by the
sid itself, which is why a test drive still produces a metrics panel even
though there is no CDR-style call record to hang it off.
The four totals
If the response carries no
totals object, the console substitutes zeros for
all five fields. So a row of zeros means βnothing has been reported yetβ,
not βmeasured as zeroβ β an agent that reports no usage and an agent that
has not yet finished a turn look identical in the panel. The distinction is
in whether rows is empty, and in the causes listed under
Why a call shows no metrics.
Tokens are reported as two numbers, input and output, and the panel keeps them
separate. Do not add them and compare the sum against a providerβs single
βtotal tokensβ figure without checking which of the two that figure includes.
Usage rows vs the live telemetry ring
The Live events pane immediately above the Metrics panel is a different source, and the two fail independently.monitoring.agentEvents returns whatever the telemetry consumer currently
holds for the org, newest first, capped by the limit you pass. It is a ring:
it holds recent traffic for every agent in the org, which is why the screen
filters it down to records that name the current call sid before rendering
anything. Older records fall out of it. Nothing in that pane is a record you
can come back to later.
The ring also reports whether it is running at all. When the telemetry consumer
is not configured, monitoring.agentEvents returns enabled: false with an
empty events array β permanently, not βnot yetβ. The console reads that flag
so a deployment with the observability spine down is distinguishable from a
quiet call. That flag says nothing about the Metrics panel. Usage rows do
not travel through the ring, so the panel can be fully populated while the
events pane is switched off, and vice versa.
One overlap worth knowing: the conversation rail merges transcript turns from
the MoQT session with items derived from the ring, and tool calls appear there
because the ring carries them. The tool_calls number in the Metrics panel is
the durable count. If the rail shows a tool call the panel has not counted yet,
the turn has not finished; if the panel counts tool calls the rail never showed,
the ring dropped or never received them.
Reporting usage from an externally hosted agent
An external agent is one you run yourself βagent_config.external_handle
is non-null on the agent β using LiveKit Agents plus
livekit-plugins-telequick. Only its media crosses the
TeleQuick engine. The model calls, the TTS, and the tools all happen inside
your worker process.
That is the whole reason this section exists: the engine cannot meter what it
does not run. For an in-engine agent, the turn machinery that calls the model
is the same machinery that writes the usage row. For an external agent there is
no such point, so your worker must report its own usage β sendUsage for
token / audio / character accounting and sendToolCall for tool invocations.
Whatever your worker does not send does not appear in the panel, and the
corresponding total stays at its zero default.
Two further things follow for external agents on this screen:
- Text mode is unavailable. Typed turns run through the in-engine model, which an external agent does not have. The console offers the Text toggle greyed out with that reason rather than hiding it, and forces the mode back to Voice when you switch to an external agent.
- Presence is a precondition. See below.
Worker presence before a test drive
You cannot start a drive against an external agent whose worker is not connected. The engine dispatches the call to a present worker and refuses when there is none, so the console checks first:- For an in-engine agent the check is skipped entirely and Start is always enabled.
- For an external agent, Start is disabled until
connectedistrue, with the hover reason βYour agent worker is not connected β start it first.β - The screen shows one of four states:
checking workerβ¦while the query is in flight,worker status unavailableif it errors,worker connected, orworker not connectedwith a hint to start your agent process against the connect URL from the External agents screen. - While no call is running, presence is re-polled, so a worker you start in another terminal enables the button without a page reload.
- Polling stops for the duration of a call. The engine holds the worker then, and presence going blank mid-call means the worker dropped β which the audio watchdog surfaces on its own.
Ending the session so totals settle
Closing the browser tab or navigating away does not end the agent session. The engine is told nothing by a dropped MoQT session: the provider WebSocket stays open (and billable) on a call nobody is on, the relay uplink stays armed, and an external worker stays assigned to a job whose caller is gone. The Stop button, leaving the screen, and switching agents all call the same release:voice:owner:<call_sid> marker against your org β a sid that is
not yours is rejected β then invokes agentruntime.stop, which closes the
provider session and tears down the relay uplink, sending an external worker
its shutdown over the media transport. On success the ownership marker is
deleted.
The call is best-effort by contract. The screen has already hung up, so a
failure is logged rather than raised at you. If usage keeps climbing on a drive
you thought you ended, this is the first thing to check.
Why a call shows no metrics
Work down the list; the causes are ordered by how often they are the answer.- No call sid. The query is disabled until a drive is running. Idle screen, empty panel.
- No turn has completed. Rows land as turns complete. If the session shows βConnected, but the agentβs audio track hasnβt delivered anything yetβ, there is nothing to total yet β your mic is still going through, so watch the transcript fill in first.
- An external agent that does not report. If the agent has an
external_handleand your worker never callssendUsage/sendToolCall, the totals stay at their zero defaults forever. This is the single most common cause of a permanently empty panel on a call that otherwise worked. - You are reading the wrong emptiness. An empty Live events pane with the feed reported as off is the telemetry consumer being unconfigured, which has no bearing on usage rows. Check which pane is empty before you go looking at the observability spine.
- The panel re-keyed. Switching agents or stopping the drive clears the call sid, and the panel empties by design rather than showing the last callβs numbers. Restart the drive to get a fresh record.
- Audio never reached you, so no turn happened. If
gatewayConnectInforeturnsenabled: false, the call still originates and events still show, but you will not hear the agent; likewise if the browser is holding playback or the subscribe failed. Those are media-path problems, but a conversation that never happened produces no usage to total.
Related
- Telemetry β metrics, traces, and the durable CDR stream
- Telephony Metrics β the call-quality numbers, as opposed to agent cost
- Authentication β API keys for the control plane, relay tokens for the media leg