TL;DR: The hard part of a production voice agent is not holding a conversation. It is writing down an email address correctly. Speech recognition is tuned for words, and names, emails, postcodes and reference numbers are not words. My rules: never ask for a field you can already look up, ask for the fewest fields the next step actually needs, confirm identifiers in chunks rather than all at once, validate the shape in the pipeline instead of trusting the model's ears, move spelling into text where text belongs, and always give the repair loop an exit. A booking that saves with a slightly wrong name is fine. A booking that saves with a wrong phone number is lost revenue nobody notices.
A garage agent I reviewed had a beautiful conversation flow. Warm greeting, good scheduling logic, clean handoffs. It was also emailing confirmations into the void roughly a third of the time, because "gmail" had been transcribed as "g mail", "hotmail" as "hot mail", and one caller's surname had been heard four different ways across a two minute call.
Nobody complained. That is the whole problem. Failed capture is silent. The call sounds successful, the transcript reads successful, the dashboard counts it as successful, and the lead never receives anything.
I have written about keeping the call fast, booking against a real calendar and what the agent should know. This is the layer people skip: getting structured, correct data out of a noisy phone line.
Why identifiers are harder than conversation
Speech models are extraordinarily good at language and mediocre at strings. Language has redundancy, so context repairs errors. If the model mishears one word in "can I book my car in for Thursday morning", the sentence still resolves. Identifiers have no redundancy at all. Every character carries information, so a single mistake destroys the whole value, and there is no context to recover it from.
Then add the phone line. Telephony audio is narrowband, and the frequencies it discards are exactly where the consonants that distinguish letters live. "M" and "N", "S" and "F", "B" and "P" are hard for humans on a bad line, which is why the military invented a phonetic alphabet in the first place. Your model is listening through the same pipe.
So capture failures cluster in predictable places: email local parts, surnames, street names, alphanumeric references, postcodes, and any digit sequence spoken quickly.
Rule one: do not ask for what you can already know
The cheapest capture is the one that never happens.
Most inbound calls arrive with caller ID. If that number matches a record in the CRM, the agent should not be asking for a name, an email or a phone number at all. It should be confirming: "I have you as Sarah at 14 Oakfield Road, is that still right?" One yes replaces three risky fields.
On the CallSetter AI work at Tested Media, the same principle applies in reverse for outbound and callbacks. If the lead came from a form fill or a missed call, the record already holds most of the fields. The agent's job on that call is to verify one or two things, not to re-collect a profile that already exists.
Every field you can look up instead of ask removes a failure mode and shortens the call. That is two wins from one decision.
Rule two: collect the minimum the next step needs
Ask what the downstream system genuinely requires to act, and nothing else.
To book an appointment you usually need a name, a callback number and an appointment type. You do not need an email address unless something is actually going to be emailed. You do not need a full postal address unless someone is driving to it. Every optional field is another chance to fail silently, another twenty seconds of call time, and another moment where the caller decides this is taking too long.
I make the client justify each field before it goes in the script. In practice about a third of the fields on a first draft turn out to be there because the old paper form had them.
Rule three: confirm in chunks, not in one long readback
The instinct is to collect everything and read it all back at the end. That is the worst possible design, because a caller listening to a twelve second recital of their own details stops paying attention halfway through and says yes to a wrong digit.
Confirm each identifier as you take it, in chunks small enough to check:
- Phone numbers. Read back grouped, in threes or fours, the way people say them naturally. Groups also make correction cheap, because the caller can say "no, the last four are wrong" instead of starting over.
- Emails. Split at the "at". Confirm the local part, then the domain separately. Domains are usually one of a handful of providers, so the domain half is nearly free while the local part carries all the risk.
- Names. Confirm the spelling out loud only when it matters downstream, and expect to fail. More on this below.
- Reference or registration numbers. Read back in the same grouping the caller used, and never re-group them, because a caller who said their reg as three chunks will not recognize it as two.
One useful habit: have the agent read letters back phonetically when confirming an unusual spelling, but never demand phonetics from the caller. Asking a customer to spell their name in NATO alphabet is a support-desk experience, not a receptionist one.
Rule four: validate the shape in the pipeline, not in the prompt
Never trust the model to be the validator. Models will happily accept "sarah at gmail" as an email address and pass it on.
Structural validation belongs in the n8n workflows behind the call, where it is code and it is deterministic. What that layer does on every capture:
- Normalizes. Strips spaces from spoken emails, removes "dot" and "at" as literal words, collapses "g mail" and "gee mail" to gmail.com, applies the country's phone format, upper-cases and re-spaces postcodes.
- Checks the shape. A valid email pattern, a phone number with the right digit count for the region, a postcode that matches the national format. Shape checking catches the majority of real capture errors, because bad captures are usually malformed rather than merely wrong.
- Corrects the obvious near-misses. A small map of common mistranscriptions of the top five email providers fixes more failures than any amount of prompt tuning. Do this in code, with an explicit list, not by asking a model to guess.
- Flags rather than blocks. If the email fails validation, the booking still saves, and the record gets a flag so a human can fix it. Losing the appointment because the optional field was mangled is a far worse outcome than an appointment with a missing email.
The agent should be told the result of that check while the caller is still on the line where possible, so a genuinely broken value can be retried once. But the check itself must live in the pipeline.
Rule five: give the repair loop an exit
Two failed attempts at the same field is the signal. A third attempt does not work, it just annoys someone who is now certain the machine is broken.
The ladder I use, in order:
- Retry once, differently. Not "sorry, can you repeat that", but a changed strategy: ask for it slower, or in parts, or ask them to spell just the first half.
- Switch channel. For emails specifically, the best move is to stop trying. "I will text you a link to confirm your email, is this number good for a text?" A phone number captured by voice is far more reliable than an email captured by voice, and the link collects the email in the medium where people type accurately. This requires the SMS half of the stack to be properly set up, including A2P registration, or the text quietly never arrives.
- Use the keypad. DTMF is the honest fallback for pure digit fields such as account numbers, reference numbers and dates of birth. It is not a failure to ask someone to type it, and it is close to error free.
- Hand off. If identity or an exact reference is required and voice capture has failed twice, that is a transfer, with everything already captured attached so the human does not start from zero.
The one thing the agent must never do is loop. A repair loop with no exit is the single most common reason a caller hangs up on an otherwise decent agent.
Names are a different problem
Names deserve their own rule because the usual instinct is wrong.
There is no correct spelling the model can infer, transcription accuracy on surnames is much worse than on common words, and accent variation makes it worse still. Building UK agents at Fortell AI for vet clinics and medical practices, name capture was the most consistent source of dirty records.
What works: capture the name as heard, do not fight for character accuracy, and key the record on the phone number instead. The phone number is the reliable identifier. The name is a label for a human to read.
The exception is anywhere the name is the lookup key into a system of record, patient records being the obvious case. There, the correct design is not better name capture, it is a different key entirely: a phone number, a date of birth, a reference number, or a human.
I picked this up building clinical eye-tracking diagnostics at Nystag. If a measurement's confidence is low, you record the confidence alongside the value rather than laundering the uncertainty away. Same thing here. A captured field with a "low confidence, unverified" marker is far more useful to the business than the same field presented as clean data.
Test it where it actually breaks
Standard agent testing uses clear speakers reading tidy values. That is a demo, not a test. The scenarios that find real bugs:
- Accents the client's actual customer base has, not the ones your test scripts have.
- Background noise: a car, a street, a waiting room, a speakerphone.
- Awkward but common values: hyphenated surnames, plus-addressed emails, numbers in the local part, non-obvious domains, and any postcode format the region actually uses.
- Callers who correct themselves mid-utterance, which is normal human speech and something scripted tests never produce.
I batch these through the Claude Code and Comet pipeline rather than dialing by hand, and I score per field rather than per call, because a 90 percent success rate on calls can hide a 60 percent success rate on emails.
Then measure it in production. Field-level capture accuracy belongs on the dashboard next to booking rate: what percentage of captured emails were deliverable, what percentage of numbers connected on the first callback attempt. Those two numbers expose a class of failure that no conversation metric will ever show you.
The short version
- Look it up before you ask for it. Caller ID plus a CRM lookup removes three fields.
- Collect only what the next step needs. Justify every field.
- Confirm each identifier as you take it, chunked, never in one long readback at the end.
- Validate structure in code, normalize aggressively, flag rather than block.
- Give the repair loop an exit: retry once, then text a link, then the keypad, then a human.
- Key records on the phone number, not the name.
- Store confidence with the value instead of presenting a guess as clean data.
- Test with accents, noise and awkward values, and score accuracy per field.
Conversation quality is what wins the demo. Whether the confirmation email actually arrives is what decides if the client renews.
I build production voice and chat agents on Retell, wired into n8n, GoHighLevel and Twilio, with the capture, CRM and reporting layer behind them actually working. More about my background here, or book a call.