Hallucinaties van voice AI zijn veruit de belangrijkste reden waarom voice-agents bij bedrijven blijven steken in de pilot en nooit productie halen. Niet de latency. Niet de accenten. Niet SIP. Een tekstchatbot die een retourbeleid verzint, is hinderlijk maar de gebruiker kan het teruglezen en naast zich neerleggen. Een voice-agent die met een warme, zelfverzekerde, menselijk klinkende stem zegt "Yes, your appointment is confirmed for Tuesday at 3pm" — terwijl dat tijdslot niet bestaat — is een risico waar je operationele team pas achter komt als de klant voor een leeg kantoor staat.
Dit is het engineeringdraaiboek voor een feitelijk correcte voice-agent: harde grounding zodat het model alleen uit opgehaalde waarheid spreekt, afgedwongen gestructureerde output bij transactionele beurten, een refusal-structuur die "dat weet ik niet" tot een volwaardige uitkomst maakt, RAG met lage latency die binnen het tijdsbudget van een spreekbeurt past, en een voice-AI-eval-harnas dat groundedness aantoont voordat je er echte telefoonnummers op richt.
Waarom de spraakmodaliteit het hallucinatierisico versterkt
Dezelfde LLM-hallucinatie die in chat te tolereren is, wordt aan de telefoon gevaarlijk om drie structurele redenen.
Geen scrollback. Chatgebruikers scannen, lezen terug en betrappen het model erop dat het zichzelf twee berichten hoger tegenspreekt. Spraak is vluchtig — eenmaal uitgesproken is de bewering weg, en de enige registratie zit in het geheugen van de klant (meestal onjuist) of in een transcript dat niemand leest tot er een geschil is. Er is geen visuele hint dat de agent twijfelt.
De stem zelf is een vertrouwenssignaal. Prosodie, tempo en een natuurlijke TTS-stem registreren in het menselijk brein als competentie. In CX beoordelen bellers zelfverzekerd klinkende agents stelselmatig als accurater, ongeacht of ze gelijk hadden. Je TTS-laag is in feite een zelfverzekerdheidsversterker, geschroefd op een model dat geen idee heeft wanneer het fout zit.
Beurtdruk dwingt het model tot een uitspraak. Een voice-agent kan niet 4 seconden stil blijven terwijl hij "nadenkt" — dode lucht breekt het gesprek. Dus vindt het decoderen plaats onder latencydruk, vult het model het gat, en precies bij het vullen van dat gat gaan LLM's fabuleren. Hetzelfde tijdsbudget dat spraak menselijk laat aanvoelen (zie ons werk over voice-architectuur onder 300 ms) is het budget dat het model verleidt tot gokken.
Alles bij elkaar: spraak neemt de ergste faalmodus van een LLM en haalt elke vangrail weg die de gebruiker eerder had. Daarom is de nauwkeurigheid van een AI-voice-agent een architectuurprobleem, geen kwestie van prompts bijschaven.
De vier faalmodi die je echt moet stoppen
Generiek advies om "hallucinaties te verminderen" is nutteloos, want de vier manieren waarop een voice-agent liegt hebben verschillende impactstralen en verschillende oplossingen.
- Verzonnen beleid. "You can return that any time within 90 days." De echte termijn is 30 dagen. Het model interpoleerde een plausibel getal. Oplossing: uitsluitend antwoorden vanuit retrieval — zie de volgende sectie.
- Verzonnen prijs. "That plan is $49 a month." Het is $59. Getallen zijn de meest risicovolle tokens die een LLM uitspuugt: goedkoop te genereren, duur als ze fout zijn. Oplossing: gestructureerde output afdwingen — laat prijzen nooit via vrije tekstgeneratie lopen.
- Valse bevestiging. "You're all set, confirmation number A-4471." Er is geen boeking weggeschreven. Het model vertelde over een geslaagde tool-call die nooit heeft plaatsgevonden (of hallucineerde het ID voordat de tool antwoordde). Oplossing: grounding op het toolresultaat — de agent mag alleen bevestigen wat de API daadwerkelijk teruggaf.
- Valse escalatie / valse belofte. "I'm transferring you to a specialist who'll call back within the hour." Die wachtrij bestaat niet. Oplossing: refusal-structuur plus een allowlist van de acties waarvoor de agent daadwerkelijk is aangesloten.
Herleid elke guardrail die je bouwt tot een van deze vier. Vermindert een controle er geen enkele, dan is het theater.
Harde grounding: alleen antwoorden uit retrieval en afgedwongen gestructureerde output
Het kernprincipe: het model moet opgehaalde feiten verwoorden, niet onthouden. Parametrisch geheugen — wat het LLM "weet" uit pretraining — is verboden bij het beantwoorden van zakelijke vragen.
Gebruik voor informatieve beurten (beleid, openingstijden, prijzen, voorwaarden) een retrieval-patroon voor voice AI waarin de system prompt uitspraken zonder bron verbiedt:
You answer ONLY using the <context> block. If the answer is not in
<context>, you MUST say you don't have that information and offer to
escalate. Never use prior knowledge. Never estimate, infer, or round.
Every factual claim must be traceable to a context snippet.
Die prompt alleen is noodzakelijk maar niet voldoende — prompts lekken. Stop bij transactionele beurten (alles met een prijs, datum, aantal, ID of een ja/nee-toezegging) volledig met vrije tekstgeneratie en dwing gestructureerde output af. Laat het model een getypeerd object uitgeven dat je applicatie valideert en deterministisch naar spraak rendert:
{
"name": "quote_plan",
"schema": {
"type": "object",
"properties": {
"plan_id": { "type": "string", "enum": ["basic", "pro", "enterprise"] },
"price_cents":{ "type": "integer" },
"source_doc_id": { "type": "string" }
},
"required": ["plan_id", "price_cents", "source_doc_id"],
"additionalProperties": false
}
}
Vervolgens zoekt jouw code — niet het model — price_cents op in de prijstabel met plan_id als sleutel, en weigert te spreken als source_doc_id geen echt document is. Het model kiest welk plan; het systeem bezit het getal. Een verzonnen prijs wordt structureel onmogelijk, omdat het model nooit de bron van de cijfers is.
Dezelfde discipline maakt korte metten met valse bevestigingen. De agent mag niet "het staat vast" zeggen op basis van een gegenereerde string. Hij stuurt een book_appointment-tool-call, wacht op het echte API-antwoord, en een bevestigingsregel uit een template wordt gevuld vanuit het teruggegeven boekingsobject. Geen toolresultaat, geen bevestiging — punt. Dit is de natuurlijke uitbreiding van de state-machine-aanpak die we beschrijven bij het bouwen van deterministische AI-agents: transactionele beurten zijn toestanden met getypeerde overgangen, geen open gesprek.
Refusal-structuur: "dat weet ik niet" als elegante, ontworpen uitkomst
De meeste hallucinaties zijn het model dat weigert te weigeren. Het verzint liever iets dan een hiaat toe te geven, omdat niets in het gesprek dat toegeven beloont. Je moet de afrit zelf ontwerpen.
Een goede refusal doet drie dingen: hij doet niet alsof, blijft vriendelijk, en stuurt de beller ergens nuttigs heen. Bouw dat expliciet op:
# Refusal policy
If <context> does not contain the answer, do NOT guess. Respond with:
1. A brief, friendly acknowledgement ("That's a good question—")
2. An honest gap statement ("—I don't want to give you the wrong
number on that.")
3. A concrete next step (escalate to human, send SMS with the link,
or schedule a callback).
Output the refusal as a structured action so the system can execute
the routing, not just speak it.
Koppel de prompt aan een gestructureerde refusal-actie, zodat het systeem de routering bepaalt en het model geen doorverbinding kan beloven die niet bestaat:
{
"action": "refuse_and_route",
"reason": "no_grounding",
"route": "human_handoff", // must be in the configured allowlist
"spoken": "I don't want to give you a wrong answer on that, so let me get you to a specialist."
}
route wordt gevalideerd tegen de kanalen die je daadwerkelijk hebt aangesloten. Is human_handoff niet geconfigureerd voor deze lijn, dan schaalt het systeem terug naar de eerstvolgende beschikbare route (terugbelverzoek, sms) in plaats van de agent een fictie te laten vertellen. Zo elimineer je faalmodus nr. 4. Goed uitgevoerd verhoogt een elegante refusal de CSAT — bellers vertrouwen een agent die zijn grenzen kent meer dan een die de helft van de tijd zelfverzekerd fout zit.
RAG met lage latency voor spraak: grounding binnen het beurtbudget krijgen
Grounding is waardeloos als het het latencybudget opblaast en de agent stilvalt. Spraak geeft je ruwweg 800 ms–1,2 s round-trip als plafond voordat het gesprek kapot voelt, en RAG moet daar binnen passen, niet bovenop. Mik op onder 200 ms p90 voor retrieval, zodat het leeuwendeel van het budget overblijft voor ASR, het LLM en TTS.
Drie dingen maken voice-RAG snel genoeg:
- Hybride zoeken, geen pure vectorzoekopdracht. Combineer BM25/keyword met dense embeddings en fuseer de rankings (reciprocal rank fusion). Bellers noemen artikelnummers, plannamen en interne bijnamen voor beleid — exacte lexicale tokens waar puur dense retrieval op stukloopt. Hybride vangt ze op. Houd het embeddingmodel klein en gekwantiseerd; je hebt geen 7B-reranker nodig in het kritieke pad.
- Chunk voor het oor, niet voor het oog. Web-RAG chunkt op 500–1000 tokens. Voor spraak chunk je tot één gesproken antwoord — 1 tot 3 zinnen, op zichzelf staand, zonder "zoals in de tabel hierboven te zien is". Een chunk moet iets zijn dat TTS letterlijk kan voorlezen en dat dan nog klopt. Sla naast de brontekst een kort, uitspreekbaar
answer-veld op. - Voorverwarmen en cachen. Cache embeddings voor de belangrijkste intents, houd de index in het geheugen en zet de retrievalservice naast de orchestrator om een hop tussen regio's te vermijden. Dezelfde latency-engineering die we op SIP en mediapipelines toepassen, geldt hier: elke netwerkgrens is een belasting die je elke beurt betaalt.
Een praktische p90-verdeling binnen een budget van 1 s: ASR-finalisatie ~150 ms, retrieval ~180 ms, eerste LLM-token ~250 ms, eerste TTS-audio ~200 ms — met streaming, zodat de beller spraak hoort voordat het volledige antwoord is gedecodeerd.
Het voice-eval-harnas: groundedness aantonen vóór livegang
Je levert nauwkeurigheid van een AI-voice-agent niet op gevoel. Je hebt een offline harnas nodig dat de agent scoort op achtergehouden, echte transcripten en dat deploys blokkeert. Vier metrieken tellen:
- Feitelijkheid — is elke bewering waar ten opzichte van de bron van waarheid?
- Groundedness — wordt elke bewering gedekt door de opgehaalde context die de agent daadwerkelijk had? (Een bewering kan waar maar ongegrond zijn — dat is geluk, geen systeem.)
- Refusal-correctheid — weigerde de agent in plaats van te verzinnen wanneer het antwoord niet op te halen was? En omgekeerd: weigerde hij niet te vaak bij vragen die wel te beantwoorden waren?
- Transactionele integriteit — kwam elke uitgesproken bevestiging overeen met een echt toolresultaat?
Bouw het harnas uit geanonimiseerde productietranscripten (of red-teamscripts), gelabeld met het juiste antwoord en met de vraag of het überhaupt te beantwoorden was. Scoor elke beurt met een deterministische check waar dat kan en met een LLM-judge waar dat niet kan:
def score_turn(turn, ground_truth):
claims = extract_claims(turn.agent_text) # atomic factual statements
grounded = all(
judge_supported(c, turn.retrieved_context) # LLM-judge: entailment
for c in claims
)
factual = all(judge_matches(c, ground_truth) for c in claims)
if not ground_truth.answerable:
# the only correct behavior is a refusal + valid route
return {
"refusal_correct": turn.action == "refuse_and_route"
and turn.route in ALLOWED_ROUTES,
"hallucinated": len(claims) > 0, # any claim here is a hallucination
}
return {
"grounded": grounded,
"factual": factual,
"over_refused": turn.action == "refuse_and_route",
}
Aggregeer tot een groundedness-percentage en een hallucinatiepercentage, stel een release-gate in (bijvoorbeeld hallucinatiepercentage < 0,5% op de achtergehouden set, refusal-correctheid > 98%) en laat de deploy falen als een prompt- of modelwijziging dat verslechtert. Draai de suite bij elke modelwissel — een "beter" basismodel kan stilletjes groundedness inruilen voor vloeiendheid. Dit is regressietesten op waarheid, en het is het artefact dat "we denken dat het accuraat is" omzet in een getal dat je aan een klant kunt laten zien.
Guardrails in productie: confidence-drempels en human-in-the-loop
Offline evals vangen bekende faalvormen. Productie heeft live vangnetten nodig voor de onbekende.
- Confidence-drempels op retrieval. Ligt de gefuseerde score van de bovenste opgehaalde chunk onder een ondergrens, behandel het dan als "geen grounding" en route naar een refusal — beantwoord niets op basis van een zwakke match. Een zwakke retrieval is een hallucinatie die staat te wachten om uitgesproken te worden.
- Human-in-the-loop bij intents met hoge inzet. Tag intents op impactstraal. Openingstijden en winkeladres: volledige autonomie. Annuleringen, terugbetalingen boven een drempel, medische of juridische vragen, alles wat geld verplaatst of een toezegging doet: eis een tool-gevalideerd pad, een bevestigende terugkoppeling ("Just to confirm, you want to cancel order 4471 — yes or no?") of een warme overdracht. De bevoegdheid van de agent moet omgekeerd evenredig schalen met de kosten van een fout.
- Log elke bewering met haar bron. Elke uitgesproken feitelijke bewering hoort in het gesprekslog de
source_doc_idmee te dragen waar ze vandaan komt. Bij een geschil beantwoord je "wat zei de agent en waarom" in seconden in plaats van te gokken. Dit voedt bovendien je evalset — geschillen uit productie zijn de waardevolste achtergehouden cases die je ooit krijgt.
Stapel dit alles en de vier faalmodi hebben geen schuilplaats meer: verzonnen beleid en verzonnen prijzen worden geblokkeerd door grounding en gestructureerde output, valse bevestigingen door de binding aan het toolresultaat, valse escalaties door de allowlist met routes — en alles wat nieuw is triggert een confidence-drempel en belandt in een elegante refusal.
Hoe Finn dit standaard afvangt
De voice-agents van Finn zijn standaard gegrond: alleen antwoorden uit retrieval, afgedwongen gestructureerde output bij elke transactionele beurt, een refuse-and-route-laag die aan je echte escalatiekanalen hangt, en hybride retrieval onder 200 ms binnen het budget van een spreekbeurt. Het eval-harnas zit bij het platform — richt het op je transcripten en krijg een groundedness- en hallucinatiecijfer nog vóór één live gesprek. Wil je je hallucinatiepercentage zien op je eigen gespreksdata? Boek een technische Finn-demo.
Veelgestelde vragen
Kan prompt engineering alleen hallucinaties van voice AI stoppen? Nee. Een grounding-prompt is noodzakelijk maar lekt onder belasting. Je hebt afgedwongen gestructureerde output nodig bij transactionele beurten, binding aan toolresultaten voor bevestigingen, en een eval-gate. Prompts verlagen het percentage; architectuur haalt de faalmodus weg.
Wat is het verschil tussen feitelijkheid en groundedness? Feitelijkheid vraagt "is de bewering waar?". Groundedness vraagt "wordt de bewering gedekt door de context die de agent werkelijk heeft opgehaald?". Een bewering kan bij toeval waar zijn en toch ongegrond — dan kwam je systeem om de verkeerde reden bij het juiste antwoord en komt het ooit bij een verkeerd antwoord uit. Volg beide; gate op groundedness.
Hoe snel moet RAG zijn voor spraak? Mik op onder 200 ms p90 bij retrieval, zodat het binnen een conversationele round-trip van ~800 ms–1,2 s past zonder dode lucht te veroorzaken. Gebruik hybride zoeken (keyword + vector), kleine gekwantiseerde embeddings, een index in het geheugen, en zet retrieval naast de orchestrator.
Hoe weet ik vóór livegang dat mijn voice-agent niet gaat hallucineren? Draai een offline eval-harnas over achtergehouden, gelabelde transcripten dat feitelijkheid, groundedness, refusal-correctheid en transactionele integriteit scoort. Stel een release-gate in (bijvoorbeeld hallucinatiepercentage onder 0,5%) en draai die opnieuw bij elke prompt- of modelwijziging.



