Voice Truth Guard — Decision
PROPOSED — PENDING FEDE'S PICKHow to stop Clara asserting things on phone calls that didn't happen ("You're all set — tour rescheduled" for a pending, conflicted slot — the Aug 22 Camellia incident), without paying for it in dead air. Commissioned by Fede 2026-08-22. Standing rule: nothing voice-related merges without his explicit approval.
The evidence (all measured, none estimated)
- The lie is deterministic, not flaky: with today's tool wording, the voice model asserted the unbacked booking 20 / 20 times. With honest wording — either variant — 0 / 20. (Offline replay of the real incident turn; merged as evidence.)
- Latency, measured on a real throwaway voice agent (30 live WebSocket conversations): tool double-checking itself before answering adds ~15 ms typical / 28 ms worst; a fast second model re-checking wording pre-speech adds ~846 ms typical / 950 ms worst.
- Architectural fact: our code never sees Clara's words before they're spoken — the language model runs inside ElevenLabs. Our only levers: what tools return, agent config, ElevenLabs' own (alpha) guardrail feature, and after-the-call detection.
- Coverage fact: text and email replies pass a hallucination / promise-backing / fair-housing pipeline before sending. Voice passes nothing.
The options
Three zero-latency pieces shipped together:
- Tools dictate the sentence. Every tour tool returns a machine-computed status (confirmed / pending team approval / slot taken / failed) and a pre-written sentence for it — the conflict-explicit shape Fede specified ("that slot is already booked — I have 1:15 or 1:30") — and that is the only status information the model receives. Nothing ambiguous left to embellish. Extends a pattern one tool branch already uses.
- Config: Clara can't speak while a tool is running (ElevenLabs interruption/wait setting) — no narrated guesses about in-flight actions.
- Widen the after-call fake-claim detector (word-order patterns + confirmed-vs-pending check — both gaps test-pinned already) so we can measure the incident rate falling instead of assuming.
Limit acknowledged: this constrains what the model is told, it doesn't inspect what it says. The detector is the accountability layer. Industry note: no vendor documents the tool-dictated-sentence pattern — this is novel work, not borrowed practice.
ElevenLabs' new (alpha) guardrail can run a custom natural-language rule over each reply before audio plays — the only true pre-speech hook they offer. Blocking mode costs 200–500 ms per their docs; its only remediations are retry or end-call. Worth piloting behind Option A on a test line, never as the only defense — alpha status and semantic (a second model's judgment, not deterministic).
Host the LLM call ourselves and hand ElevenLabs only the voice — the architecture where real interception and mid-stream correction become possible (how LiveKit/OpenAI Realtime do it; even they admit some audio can escape). Big migration, and the measured cost of a verify step (~0.85 s) eats the latency budget. Park as the long-term conversation, incl. a feature request to ElevenLabs for a deeper hook.
Keep speaking from ambiguous tool results and catch lies after the call. Rejected as the primary answer: the 20/20 result shows the caller hears the lie every time the state is ambiguous — and we now know a 0-latency prevention exists.
Your pick
| Choice | What ships | Latency cost |
|---|---|---|
| A (recommended) | Truthful tool wording + no-talk-during-tools + wider detector | ≤ 28 ms |
| B | A, plus a Guardrails 2.0 pilot on a test line | A + 200–500 ms on the piloted line only |
| C | Scope the platform-boundary migration as its own project | n/a (design phase) |
| D | Nothing preventive | 0 |
All artifacts: wording eval (merged), latency prototype PR #6114 (held), research catalog in the session record. Whatever the pick, every voice change stays merge-held for Fede's explicit approval. Related fix already correcting the design record: the turn-integrity architecture note assumed a pre-speech buffer voice cannot have on this platform.