arrow_backBACK TO BUILDING VOICEBOTS — TELEPHONIC & BROWSER, THE REAL ENGINEERING
Lesson 08Building Voicebots — Telephonic & Browser, the Real Engineering5 min read

Latency & Feeling Human

October 28, 2026

TL;DR

A voicebot feels human when it's fast and interruptible. Walk the latency budget for one turn: endpointing/VAD (~250ms, often the biggest), final STT (~150ms), network (~60ms), LLM time-to-first-token (~350ms), TTS time-to-first-byte (~150ms), playout (~90ms) — a naive sum of ~1 second, right at the 'laggy' threshold. You beat it by STREAMING and OVERLAPPING stages (feed partial STT to the LLM, feed partial LLM text to TTS so speech starts before the LLM finishes), attacking the two big bars (tune endpointing, pick a fast LLM for TTFT), and hiding the rest with a tiny filler ('let me check…'). Barge-in — letting the user interrupt — is the other half: when VAD hears the user over the bot, instantly STOP and flush the TTS, discard the half-spoken reply, and take the interruption as the next turn (echo cancellation stops the bot interrupting itself). All numbers illustrative; measure your real stack.

Two things make a voicebot feel like talking to a person rather than a machine: it responds quickly, and you can interrupt it. Both are about the same underlying thing — respecting the rhythm of human conversation — and both are where voicebots most often fail. This lesson makes latency concrete with a worked budget (so you know where to spend effort), and covers barge-in, the interruption handling that a natural conversation demands.

The Latency Budget of One Turn

“Make it fast” is vague. Let’s make it specific: here’s where the time goes in one turn, from the user finishing their sentence to the bot starting to speak. (These numbers are illustrative — the point is the shape, and you should measure your own stack.)

The latency budget of one turn: user stops talking to bot starts talking, keep it under about 1 second (illustrative). Endpointing / VAD (detect silence) 250 ms, Final STT transcript 150 ms, Network to LLM 60 ms, LLM time-to-first-token 350 ms, TTS time-to-first-audio 150 ms, Network / playout buffer 90 ms, naive sum about 1050 ms. How to get under the 'laggy' line (about 1000 ms): STREAM and OVERLAP, the stages don't have to run one-after-another, feed partial STT to the LLM, feed partial LLM text to the TTS so TTS starts speaking while the LLM is still generating; attack the two big bars, tune ENDPOINTING (the 250 ms) and pick a fast LLM for TTFT (the 350 ms); use streaming STT and streaming TTS (Lessons 4-5), never 'wait for the whole thing'; hide remaining latency with a tiny filler ('let me check...') or a thinking sound for slow tool calls; measure the REAL end-to-end number on your stack, don't trust a spec sheet

The stages and their illustrative costs:

  • Endpointing / VAD (~250 ms) — the time to be sure the user has stopped (Lesson 4). Often the single biggest chunk, because you must wait out a pause to confirm they’re done.
  • Final STT transcript (~150 ms) — settling the final text after the endpoint.
  • Network to LLM (~60 ms) — sending the transcript, queueing.
  • LLM time-to-first-token (~350 ms) — how long until the model starts producing its reply. The other big chunk.
  • TTS time-to-first-byte (~150 ms) — until the first audio comes out (Lesson 5).
  • Network / playout buffer (~90 ms) — getting that audio to the user’s ear.

Add them up naively and you get ~1050 ms — right at the “this feels laggy” threshold (Lesson 1). So how do real voicebots feel snappy? Two moves.

Beating the Naive Sum: Stream and Overlap

The naive sum assumes the stages run one after another, which they don’t have to. The core trick (Lesson 1) is to stream and overlap:

  • Feed partial STT to the LLM so it can start as soon as the final arrives (and sometimes act on partials for simple cases).
  • Feed partial LLM output to the TTS sentence-by-sentence, so TTS starts speaking while the LLM is still generating the rest of the reply (Lesson 5).

With overlap, the TTS’s time-to-first-byte starts during the LLM’s generation, not after it — so the stages’ times don’t fully add; they telescope. That’s how a ~1-second naive pipeline becomes a sub-second perceived response. This is why streaming STT (Lesson 4) and streaming TTS (Lesson 5) aren’t optional niceties — they’re what make the budget work.

Then attack the two big bars directly:

  • Tune endpointing (the ~250 ms). A smarter endpointer — using the content of the transcript to detect completeness, not just raw silence — can shave this meaningfully without cutting people off. This is high-value tuning (Lesson 4).
  • Pick a fast LLM for time-to-first-token (the ~350 ms). A smaller, faster model often beats a bigger one for the snappy feel voice needs — and it’s cheaper too (Lessons 6, 11). Reserve big models for genuinely hard turns.

And hide what’s left: for a slow operation (a tool call that takes a moment, Lesson 6), play a tiny natural filler — “let me check that for you…” or a brief thinking sound — so the user hears something immediately instead of dead air. Humans do this constantly (“um, let me see”); a well-placed filler buys you time without feeling laggy.

Finally, the rule that governs all of it: measure the real end-to-end number on your stack. Provider spec sheets lie by omission (they quote their stage, not your whole loop). Instrument every stage (Lesson 12) and optimise the one that’s actually slow — usually endpointing, the LLM, or a slow tool call.

Barge-in: Let People Interrupt

Speed is half of feeling human; the other half is barge-in — letting the user interrupt the bot, exactly as they would a person. A bot that ploughs on while you’re trying to correct it feels broken and infuriating.

Barge-in: let people interrupt, a bot you can't interrupt feels broken, handle it like a real conversation. The bot is speaking ('The scheme gives up to two thous—') while the user interrupts ('—no, the OTHER one'), overlap. What must happen the instant the user speaks: 1 VAD detects the user talking WHILE the bot is talking; 2 immediately STOP and flush the TTS audio (stop the speaker), don't talk over the user; 3 discard the half-spoken reply, start listening/transcribing the new input; 4 the LLM takes the interruption as the next turn (it may need the earlier context too). Why it's hard (and why a framework helps): on a phone call you hear your own echo so you need echo cancellation so the bot doesn't 'interrupt itself'; timing is tight and real-time; Pipecat handles VAD plus flush plus restart for you, a big reason to use it

When the user starts talking while the bot is speaking, four things must happen fast:

  1. VAD detects the user talking over the bot. You’re listening even while speaking.
  2. Immediately stop and flush the TTS — stop the speaker, discard queued audio. Don’t talk over the user; yield the floor instantly (this is why TTS must be interruptible, Lesson 5).
  3. Discard the half-spoken reply and start listening to / transcribing the new input.
  4. The LLM takes the interruption as the next turn — often it needs the earlier context too (what it was saying, what the user is now correcting).

Why this is genuinely hard: on a phone call the bot hears its own voice (echo), so without echo cancellation it would detect “speech” that’s actually itself and “interrupt itself” constantly. And the timing is tight and real-time. This is a major reason to use a framework (Lesson 7): Pipecat handles VAD + flush + restart (and relies on the transport’s echo cancellation, Lesson 3) so you don’t hand-build this delicate machinery. Get barge-in right and the bot feels like a patient, attentive person; get it wrong and it feels like a hold-music menu.

Pitfalls to Avoid

  1. Running stages sequentially. The naive sum lands at the laggy threshold. Stream and overlap so TTS starts before the LLM finishes (Lessons 4–5).
  2. Not measuring end-to-end. Spec sheets quote one stage; optimise your whole loop. Instrument every stage (Lesson 12) and fix the real bottleneck.
  3. Ignoring endpointing and LLM TTFT. They’re the two biggest bars. Tune endpointing and pick a fast model — don’t optimise the small stages first.
  4. Dead air during slow steps. A tool call with silence feels broken. Play a tiny filler (“let me check…”) to cover it.
  5. No barge-in. A bot you can’t interrupt feels like a machine. Detect the user over the bot, stop/flush TTS instantly, take the interruption as the next turn.
  6. Forgetting echo cancellation. Without it the bot interrupts itself on a phone call. Rely on WebRTC/the provider/your pipeline (Lessons 3, 7).

Quick Recap

  • The illustrative turn budget (~1050 ms naive) is dominated by endpointing (~250 ms) and LLM time-to-first-token (~350 ms); the naive sum sits at the laggy threshold.
  • Beat it by streaming and overlapping (TTS speaks while the LLM still generates), tuning endpointing, picking a fast LLM, and hiding remaining delay with a filler. Then measure your real stack.
  • Barge-in: when the user talks over the bot, VAD detects it → stop/flush TTS → discard the reply → take the interruption as the next turn; echo cancellation stops the bot interrupting itself.
  • A framework (Pipecat) handles barge-in and overlap for you (Lesson 7). All numbers illustrative — measure yours.

Next lesson: giving the bot knowledge the right way — when you need RAG, when a plain prompt or a structured lookup is better and cheaper, and how to store your information.