Voice agent benchmark · independent, dated
How well do voice agents hold up on a real phone line?
Independent, dated measurements of the caller-side voice stack callerlab runs (LLM, TTS and STT). Whole agents on real calls will appear after the first real run. Timing figures publish after we re-run the timing measurements.
Caller LLM
RealHow callerlab picks the model behind its own test caller, not a ranking of models for your agent. Candidates run against each provider’s API on 12 real call contexts. Persona adherence and plan-following are judged 1 to 5 by an LLM judge (Model 1 on Host A). Rankings need at least 10 of 12 replies.
voicebench v0.1Oct 13, 2026, 01:00 ET6 models from 3 providers12 contextstext-only replaylist-price cost unless gateway-reported
How it’s measuredPersona and plan scores
Judged 1 to 5 by an LLM judge: persona, plan. Gaps of 0.1 or less are ties. Values read persona / plan, on a 4.4 to 5 axis because bars from zero would hide every difference. One reply rated a point lower moves a score by a tenth of a point or less.
Cost per turn vs quality
2 of 6 models plotted. $ per turn (log scale, estimated or gateway-reported) against quality. Up and left is better.
n/m · price re-check
| 1 to 5Judged | 1 to 5Judged | USDest. or gateway | of 12Measured | |
|---|---|---|---|---|
| Also the judgeHost A | 5.00 | 5.00 | $0.000168 est. | 12/12 |
| Host A | 5.00 | 5.00 | $0.000044 est. | 12/12 |
| how measuredGroq | 5.00 | 5.00 | n/m | 12/12 |
| how measuredBaseten | 4.92 | 5.00 | n/m | 12/12 |
| how measuredBaseten | 4.92 | 4.83 | n/m | 12/12 |
| how measuredGroq | 4.75 | 4.92 | n/m | 12/12 |
Text to speech (TTS)
RealCandidate voices for callerlab’s caller: six emotional caller lines per voice. Word error is measured after 8 kHz telephone downsampling.
voicebench v0.1Oct 13, 2026, 01:01 ETstreaming synthesis, not on a call11 to 12 clips per voice
How it’s measured| Voice | WER at 8 kHz% · Derived | ClipsMeasured |
|---|---|---|
| TTS 2Realvoice, anonymized | 5.3% | 12/12 |
| TTS 1Realvoice, anonymized | 6.8% | 11/12 |
Speech to text (STT)
Real, non-streamingTranscribers for callerlab’s own call checks: word error on 8 kHz phone audio.
voicebench v0.1Oct 13, 2026, 01:01 ETSTT 134 clips
How it’s measuredStreaming STT is not measured yet. The one real row is a non-streaming upload of clean synthetic clips, so it says nothing about noisy callers. The CLI’s callerlab transcribe checks spoken digits; it is not what this table measures.
| Transcriber | WER at 8 kHz% · Derived | ClipsMeasured | Method |
|---|---|---|---|
| STT 1Realmodel | 5.3% | 34 | Non-streaming file upload |
Agents on real calls: not run yet
No whole-agent benchmark results are published yet. Agent results will appear here after the first real run.
Nothing is shown for agents until a real run exists.
End-to-end reply gap
WithheldEnd of caller audio to first agent audio, read off two-channel PSTN recordings of calls to our own reference agents over the older Gather path. Includes the carrier both ways and the agent platform’s end-of-turn wait.
16 live calls, Oct 11–12, 2026Twilio Gather (half-duplex)quiet calls
How it’s measuredWe recorded the reply gap on these 16 live calls to our own reference agents, over the older Gather path. The figures publish after the re-run.
Methodology
Every number names its conditions, and the numbers themselves are in benchmark-data.json (schema callerlab.benchmark/1.0). These rows predate the Standard; its rubric applies to agent results once it is frozen.
| Layer | Status | Conditions | n | When (ET) |
|---|---|---|---|---|
| End-to-end | Withheld |
| 16calls | Oct 11–12 |
| LLM | Real |
| 12contexts per model | Oct 13, 01:00 ET |
| TTS | Real |
| 11–12clips per voice | Oct 13, 01:01 ET |
| STT | Real |
| 34clips | Oct 13, 01:01 ET |
How the LLM numbers were measured
- Harness
- voicebench v0.1, task
caller_next_line(bench_llm.py). It predates the callerlab Standard, so these rows carry no Standard version. The scripts and the 12 frozen contexts are not published yet. - Region and network
- One Linux box (8 vCPU) with egress at Cloudflare colo IAD (Ashburn, VA, us-east). Each provider’s public API is called directly.
- Model IDs
- As each provider’s API names them, under the model name in the drill-down of each named model. IDs are withheld for the 3 rows shown as “Model N” (Groq Model 3, Host A Model 1, Host A Model 2): the ID, or another host serving the model, would name an anonymized vendor.
- Prompt and contexts
- A fixed system prompt (the caller’s role and goal, persona and affect guidance, and “one short spoken line ≤ 30 words”) plus the real conversation so far, taken from live callerlab transcripts: agent turns are sent as
user, caller turns asassistant. 12 contexts drawn with seed 7 from scenarios S1–S5 and R1–R5; every model gets the same ones. Text only, no audio. - Sample size
- 12 requests per model, one per context, sent one at a time. A model is ranked only with at least 10 of 12 non-empty replies; each row shows its count.
- Streaming and retries
POST /chat/completionswithstream: trueandstream_options.include_usage,max_tokens400 (the equivalent field where an API names it differently). Reasoning is kept to the minimum each API allows; a row that setsreasoning_effortshows it in its drill-down. If a provider rejects a param, the param is dropped and the request retried once; params are recorded as requested, not as applied.- Cost formula
- Per reply: input tokens × input list price + output tokens × output list price, where output tokens include reasoning tokens if the provider counts them. Cost per turn is the mean over a model’s successful replies.
- Price sheet
- List prices as of Oct 12, 2026. Not shown for Baseten and Groq: the list price is being re-checked. Anonymized vendors’ price lists are not linked, since a link would name them. Prices change, so these may be stale.
Known limits
- US PSTN only
- End-to-end calls used the Gather path (half-duplex); streaming calls are not in these rows yet
- No SIP/WebRTC direct, no tool-call correctness, no WER of the agent
- LLM, TTS and STT: one box, one region, one request at a time, in one time window; provider load varies by hour
- Quality scores come from an LLM judge, not human ratings; prices are list prices except gateway rows
Fairness
- Rule. Vendor terms are checked before a name is published. Providers whose terms forbid benchmarking, or need their consent before results are published, are left out; vendors whose terms only limit use of their name are anonymized.
- Named. 2 of 2 named vendors have a recorded check.
- Anonymized. 4 more (Host A, TTS 1, TTS 2, STT 1) until their terms clearly allow naming them.
- Left out. 4 LLM providers and 1 TTS provider, because their terms forbid benchmarking or need consent first (terms checked Oct 14, 2026).
Conflict and corrections
callerlab sells testing. We don’t sell or resell any voice platform, have no affiliate deals with them, and never audit a platform we rank. If that ever changes, we disclose it on the affected vendor’s benchmark row. Verified factual errors anywhere on the benchmark are corrected and logged below.
What each number is
- Cost per turn
- Gateway-reported usage cost when the gateway gave one, otherwise list price times measured tokens. List prices are as of Oct 12, 2026 and may be stale. est.
- Persona and plan
- An LLM judge (temperature 0) rates each reply 1 to 5: persona is in character and sounds like a phone caller; plan advances the goal and answers what was asked. A lenient judge, not human ratings: use it for gross failures. The judge is also one of the candidate models, so its own scores may be inflated. Judged
- WER at 8 kHz
- The 8 kHz clip is transcribed by the model in the STT table and compared with the input text (word-level Levenshtein, lowercase, punctuation stripped). Number formatting inflates it. Derived
Anonymized results and consent
Who is shown, and how.
Agent results
Never published from client work
Reference agents
Test your own agent
The callerlab harness, pointed at your agent. Dry run first. (The LLM, TTS and STT rows above come from voicebench scripts that aren’t published yet.)
# first: export CALLERLAB_DIAL_TO=<a number you own, E.164> # dry run: plans and prices the calls, dials nothing callerlab explore --pack examples/packs/home-services.json \ --to "$CALLERLAB_DIAL_TO" --repeat 3 --transport stream --record
callerlab explore --pack examples/packs/home-services.json \ --to "$CALLERLAB_DIAL_TO" --repeat 3 --transport stream --record --yes
--yes enables paid calls. Confirm permission and consent first.Configure a speech-to-text endpoint for the stream before placing this call. --record saves the two-channel audio locally for the gaps command below.
callerlab scorecard --report .cache/reports/<stamp> callerlab gaps --recording .cache/runs/<stamp> # reply gaps off the recording
From a dry run to a CI gate
The quickstart covers install, Twilio setup, the first real call and gating a build on the scorecard.