← Rehan Sanjay

Measurements

What voice agents actually do

Most writing about voice agents describes what they should do. These are measurements of what they do: timed against real calls or real failures, published with the code that produced them, and corrected in public when they were wrong.

Turn-end latency, against ground truth

How long after a caller stops talking does the agent decide the turn is over, and how often does it cut in during a pause the caller was going to speak through?

Calls scored
265, labelled
Final delay, VAD-only (Silero)
0.49s
Final delay, semantic turn head
0.18s
Cut-ins in pauses under 0.5s
13% vs 21%
Cut-ins in pauses of 0.5 to 1s
69% vs 62%

The semantic head is about 0.3s faster, and the trade-off flips with pause length. Under half a second VAD-only endpointing is the more cautious; between half a second and a second it cuts in more often. An unbucketed average hides both.

Three errors in the first published version were corrected, two found by a model's maintainer reading my scoring code and one I found myself. The corrections are written up in the repository rather than quietly replaced.

github.com/Rehansanjay/vad-turn-end-latency →

Half-open websockets: speech-to-text

When the provider disappears without closing the connection, how long does each streaming STT plugin in LiveKit Agents take to notice?

Plugins in the tree
19
Fail over
3, in about 46s
Detect it and tell no one
2
Never notice
8
Could not be redirected to measure
6

One parameter explains every result: whether the plugin passes a heartbeat to the websocket. A caller is quiet a lot of the time, so a read timeout is the wrong instrument for speech-to-text.

github.com/Rehansanjay/livekit-stt-halfopen →

Half-open websockets: text-to-speech

The same question for all twenty streaming TTS plugins, where a dead socket means the agent goes mute.

Plugins in the tree
20
Fail over
9, in about 10s
Fail over eventually
3, in 20 to 70s
Never notice
7
Could not be measured
1

The opposite answer to speech-to-text. Eighteen of the twenty pass no heartbeat, and what separates the groups is whether a read timeout reaches the receive call. All seven that never notice are fixed in livekit/agents#8035.

github.com/Rehansanjay/livekit-tts-halfopen →

Pipecat plugin health, nightly

Does every community Pipecat plugin still install, import and construct against the latest release and against main?

Plugins checked
75, every night
Working
56
Broken
6
Need an older Pipecat
8
Cannot be installed
3

It finds breakage before users do, and it builds each plugin from its own repository too, so a maintainer who fixed a plugin without cutting a release is not reported as broken.

Figures from the run on 8 November 2026. The repository has the live table.

github.com/Rehansanjay/pipecat-plugin-health →

One record per call

When an agent goes quiet mid-call, can the logs say why? Usually not: the transcript has the sentence in it, and the caller heard nothing.

Built from
the session's own events
Patches to the framework
none
Dead air measured from
the caller resuming
Detects
replies generated, never spoken

Cut-ins are bucketed by how long the caller actually paused, because the caller speaking again is what proves they were not finished. That lets a call label itself, without hand-labelled audio.

Tested on synthetic records so far, not live calls.

github.com/Rehansanjay/livekit-call-record →

How the numbers are made

  • Measure against ground truth where it exists, and say plainly where it does not.
  • Publish the corrections when a number turns out wrong, next to the number.
  • Every fix ships with a test, checked by reverting the fix and confirming the test fails.

Have a voice agent that misbehaves?

I take on paid work measuring and fixing this kind of problem in production agents. Email rehansanjay28@gmail.com.