Project metrics
The Metrics area of a project answers whether your agent is healthy, fast and reliable. It has four tabs, Overview, Sessions, Voice and Agent. Credits, billable time and credit packs live on the separate Usage page. Everything you see is scoped to the one project you opened.
Ranges, zoom and limits
Every tab shares one range control. Pick a preset (1 hour, 6 hours, 24 hours, 7 days or 30 days) or choose a custom start and end. Switching tabs keeps your range, and the range is stored in the page link, so you can share a link that shows the same window. The default is 24 hours.
To zoom, drag across any chart. The page reloads for the selected window and a Reset zoom button takes you back. Hovering a chart shows the same moment on every other chart in the tab, and clicking a name in a legend hides or shows that series.
- Sessions, Overview and Agent cover up to 90 days.
- Voicecovers up to 14 days. For a longer range the Voice tab shows a notice instead of empty charts, and the Overview voice tile reads "Last 14 days only".
Each chart is split into roughly 300 intervals, so the interval gets wider as the range grows. Session and agent numbers are cached for up to 60 seconds, so a session that just ended can take about a minute to appear. Voice numbers appear after your agent has handled voice turns, usually within a few minutes.
Overview tiles
The tiles are computed over the whole range you selected, not over what is currently drawn in a chart.
- Sessions: sessions started in the range.
- Success rate: completed sessions divided by finished sessions. Finished means completed, failed or never connected. A session that ended because the agent crashed counts as failed.
- Peak concurrent: the most sessions running at the same time, next to the number your plan allows.
- Time to connect p95: 95 percent of sessions connected within this time, measured from the session request to the caller being connected. The p50 (the typical session) is shown under it.
- Voice response p95: how long callers wait for the first audio after they stop talking, for 95 percent of replies. It turns amber above 1.5 seconds and red above 3 seconds. It is hidden for data-only projects.
Sessions
Sessions over time
Started sessions per interval, stacked by outcome. Completed sessions connected and ended normally. Failed sessions ended with an error or an agent crash. Never connected sessions were created but the caller never joined, which usually points at the client side.
Concurrent sessions
The most sessions running at once in each interval, drawn against a reference line for your plan limit. If the line touches the limit, new sessions wait in the capacity queue or fail with Over capacity. Either upgrade your plan or shorten sessions, for example with a lower idle timeout (see Session idle timeout).
Time to connect
p50 and p95 of the time from the session request to the caller being connected. A rising p95 usually comes from capacity pressure, a slow client network, or an agent that takes long to start.
Capacity queue wait
When your project is at its concurrent session limit, new sessions wait for a free slot. This chart shows p50 and p95 wait time and the number of queued sessions. Any non-zero value means callers waited. Sessions that waited too long show up as Capacity wait expired under failures.
Session duration
A histogram of connected time (from the caller joining to the session ending) in five groups: under 30 seconds, 30 seconds to 2 minutes, 2 to 10 minutes, 10 to 30 minutes, and over 30 minutes, with p50 and p95 markers. A large group under 30 seconds often means callers hang up early or the agent ends calls quickly.
Failures by reason and end reasons
Failures by reason counts failed sessions by their failure code, or by their end reason when no code was recorded (for example a crash). End reasons counts every finished session by why it ended. Codes the dashboard does not know are shown as they are, so nothing is hidden. These are the labels you can see:
| Label | What it means |
|---|---|
| Caller disconnected | The caller's connection dropped without a hang-up. |
| Caller hung up | The caller ended the call. |
| Caller closed the session | The client closed the session itself, for example by leaving the page. |
| Ended by your agent | Your agent code disconnected the session. |
| Agent crashed | Your agent process exited with an error. These count as failed sessions. Check the Agent tab and your agent logs. |
| Idle timeout | Nobody spoke or sent data for longer than the idle timeout. |
| Maximum duration reached | The session hit the maximum session length. |
| Caller never connected | The session started but the caller never joined. |
| Replaced by a newer connection | The same peer connected again and took over the session. |
| Monthly usage limit reached | The project's monthly usage limit stopped the session. |
| Stopped to free capacity | The platform ended the session to free capacity. |
| Agent not deployed | No active build was deployed to the cloud. |
| No runner available | No voice worker was ready to take the session. |
| Over capacity | The project was at its concurrent session limit. |
| Capacity wait expired | The session waited in the queue for a free slot and gave up. |
| Session start failed | Starting the session failed on the platform. |
| Join token error | The join token could not be issued. |
| Timed out | The session did not finish starting in time. |
Open the sessions behind a failure
Select a reason in Failures by reason to open the Sessions page for the same time range, showing only the sessions that failed for that reason. The list has as many rows as the bar, and a chip for each filter that you can remove. On the Sessions page, the reason menu lists the failure reasons that occurred in the range, each with its count, so you can switch reason without going back. End reasons are not links, because they also cover sessions that did not fail.
Voice
The Voice tab is hidden for data-only projects. It follows one reply from the caller stopping to the first audio they hear. Voice values cover completed turns in the range and appear within about a minute of a turn.
- Response time: from the caller stopping to the first audio from your agent (p50, p95, p99). This is what the caller experiences as the pause before an answer.
- Finalize delay: the pause between the caller stopping and the final transcript. See Tuning the finalize delay.
- Agent + TTS time: the time your agent code and text-to-speech take, from the final transcript to the first audio.
- Where the time goes: finalize delay plus agent and TTS time stacked, which add up to the response time.
- STT latency and TTS latency: p50, p95 and p99 of the speech-to-text and text-to-speech calls.
- TTS time to first audio: from your agent's speak request to the first audio frame.
- Latency by vendor and language: p95 per STT vendor, TTS vendor and STT language, slowest first, top 5. Useful for spotting one vendor or language that drags the average.
- Abandoned turns: the share of caller turns where the caller kept talking or interrupted before your agent replied. The tile turns amber above 10 percent.
- Turns per minute: caller turns and agent replies per minute.
- Barge-ins per reply: how often callers interrupt the agent, per agent reply.
- VAD transitions, under Advanced: voice activity speech start and end events per second.
Response time, finalize delay, agent + TTS time, TTS time to first audio and abandoned turns need a voice runtime built on node-webrtc-rust 0.9.34 or newer. Until your project runs on it, those charts say that no data is there yet. If the metrics store cannot be reached, only the Voice tab shows an unavailable notice. The other tabs keep working.
Tuning the finalize delay
The finalize delay is usually the largest part of the response time you can change yourself. It starts when voice activity detection decides the caller stopped and ends when the speech-to-text result is final. Three advanced voice settings control it. Find them under Project overview, then Voice (STT / TTS), then Advanced voice pipeline. The Voice tab links there from Where the time goes.
| Setting | Dashboard label | Default | Effect |
|---|---|---|---|
vad.minSilenceDurationMs | Minimum silence duration (ms) | 1100 | Silence needed before a phrase counts as finished. Lower values end turns sooner. |
vad.sttGateHoldMs | STT gate hold (ms) | 400 | How long audio keeps flowing to speech-to-text after speech ends, for trailing words. |
vad.utteranceFinalizeTimeoutMs | Utterance finalize timeout (ms) | 1500 | Grace period after the last partial or speech end before the final transcript is forced. |
Shorter values make replies faster but cut off more callers who pause mid-sentence, and the last word of a turn can be lost. After you lower any of them and deploy, watch Abandoned turns and Barge-ins per reply on the Voice tab. If either rises while the finalize delay falls, you went too far. Change one setting at a time and compare the same time of day. Raise the values again if callers get interrupted or transcripts lose their last word. The full list of voice settings is in Advanced voice settings.
Agent
- Agent log volume: warnings and errors your agent code logged per interval. Turn on Info in the legend to include info lines.
- Agent crashes: sessions that ended because the agent process crashed.
- Top errors: the ten most frequent error messages in the range. Only the first line of each message is used, and stack traces and file paths are removed, so the same error groups together. Select a row to open your agent logs with the level set to Error, the same time range, and the start of the message as a search, so you land on the full text.
- Turns per conversation: p50 and p95 of messages exchanged in one conversation.
A very short message, such as a single word, is too unspecific to search by. Its row opens the Error logs for the time range without a message search. Open agent logs at the bottom of the table does the same for all errors. See Agent logs & session errors for how logs are collected and for the filters you can put in the address.
From the CLI
@voicethere/cli 0.16.0 or newer reads the same numbers from your terminal, one command per tab. Each command uses the project in .voicethere/config.json unless you pass --project.
voicethere projects metrics overview --period 7d voicethere projects metrics sessions --period 24h voicethere projects metrics agent --period 24h voicethere projects metrics voice --period 6h
--period takes 1h, 6h, 24h, 7d, 30d or mtd (month to date) for overview, sessions and agent, and 1h to 7d for voice. For a custom window pass both --start and --end as ISO 8601 timestamps instead of --period. Add --json to print the raw API response for scripts.
voicethere projects metrics sessions --start 2026-10-07T12:00:00Z --end 2026-10-08T12:00:00Z --json
To list the sessions behind an entry in Failures by reason, filter the sessions list with the reason key and the same window:
voicethere sessions list --failed --reason agent_crash --from 2026-10-07T12:00:00Z --to 2026-10-08T12:00:00Z --json
--reason implies --failed. The agent logs behind a top error take the same time flags, see Agent logs & session errors. Every option is listed in the CLI reference.
API
The tabs read from three endpoints you can also call yourself. Authenticate with an organization session (dashboard cookie) or a personal / project API key that belongs to the same organization as the project. Access to another project is denied. See the Control plane API for auth headers and error shapes.
GET /api/v1/projects/{projectId}/metrics/sessions
GET /api/v1/projects/{projectId}/metrics/agent
GET /api/v1/projects/{projectId}/voice-metricsQuery parameters. period is one of 1h, 6h, 24h, 7d or 30d (the voice endpoint accepts 1h to 7d). start and end are ISO 8601 timestamps and, when both are set, win over period. The default is 24h. Invalid values return a validation error (HTTP 400). Sessions and agent accept up to 90 days, voice up to 14 days.
Sessions returns one point per interval plus whole-range breakdowns. Times are in seconds.
{
"project_id": "…",
"period": "24h",
"range_start": "2026-10-07T12:00:00.000Z",
"range_end": "2026-10-08T12:00:00.000Z",
"bucket_seconds": 300,
"plan_concurrency_limit": 10,
"series": [
{
"bucket_start": "2026-10-07T12:00:00.000Z",
"started": 4, "completed": 3, "failed": 1, "never_connected": 0,
"peak_concurrent": 2,
"connect_p50_s": 1.4, "connect_p95_s": 3.2,
"queue_wait_p50_s": null, "queue_wait_p95_s": null,
"queued": 0
}
],
"duration_buckets": [{ "label": "30 s–2 m", "count": 3 }],
"duration_p50_s": 95, "duration_p95_s": 410,
"connect_p50_s": 1.5, "connect_p95_s": 3.4,
"queue_wait_p95_s": null,
"failures": [{ "code": "agent_crash", "count": 1 }],
"end_reasons": [{ "reason": "client_hangup", "count": 3 }]
}Agent returns log counts per interval, the top errors and conversation length.
{
"project_id": "…",
"period": "24h",
"range_start": "2026-10-07T12:00:00.000Z",
"range_end": "2026-10-08T12:00:00.000Z",
"bucket_seconds": 300,
"series": [
{ "bucket_start": "2026-10-07T12:00:00.000Z", "warn": 2, "error": 1, "info": 40, "crashes": 0 }
],
"top_errors": [
{
"message": "TypeError: Cannot read properties of undefined",
"count": 7,
"match_text": "TypeError: Cannot read properties of undefined"
}
],
"turns_per_conversation_p50": 6,
"turns_per_conversation_p95": 18
}match_text is the text the dashboard passes as the q filter of the agent logs list to find the lines behind a row, or null when the message is too short to search by. To list the sessions behind an entry in failures, call the sessions list with the same range:
GET /api/v1/projects/{projectId}/sessions?outcome=failed&reason=agent_crash&from={range_start}&to={range_end}reason is the code from failures. from is inclusive and to is exclusive, and both are ISO 8601 timestamps. An unknown outcome, a reason with characters other than letters, digits and _ . : - (or longer than 64), or an invalid range returns HTTP 400. See the Control plane API reference for the full parameter list.
Voice returns available and range_too_long flags, then latency blocks with p50_ms, p95_ms, p99_ms and a time series. Timestamps in series (t) are Unix time.
{
"project_id": "…",
"period": "24h",
"range_start": "2026-10-07T12:00:00.000Z",
"range_end": "2026-10-08T12:00:00.000Z",
"available": true,
"range_too_long": false,
"turn_response": {
"p50_ms": 820, "p95_ms": 1450, "p99_ms": 2100,
"series": [{ "t": 1791460800, "p50": 800, "p95": 1400, "p99": 2000 }]
},
"final_to_audio": { "p50_ms": 520, "p95_ms": 900, "p99_ms": 1300, "series": [] },
"finalize_delay": { "p50_ms": 300, "p95_ms": 550, "p99_ms": 800, "series": [] },
"stt": { "p50_ms": 180, "p95_ms": 320, "p99_ms": 450, "series": [] },
"tts": { "p50_ms": 210, "p95_ms": 380, "p99_ms": 520, "series": [] },
"tts_first_audio": { "p50_ms": 240, "p95_ms": 420, "p99_ms": 600, "series": [] },
"by_vendor": {
"stt": [{ "key": "deepgram", "p95_ms": 320 }],
"tts": [],
"stt_language": []
},
"abandoned_ratio": { "value": 0.04, "series": [] },
"barge_in_per_reply": { "series": [] },
"replies_per_min": { "series": [] },
"volume": { "series": [] },
"barge_in": { "series": [] },
"vad": { "series": [] }
}The values above are examples. The voice endpoint is also described in Voice metrics.