Skip to main content
This guide focuses on Coda. The same patterns work with the Mist model family; note that the grammar normalizer and the spell() function are Mist-family features that Coda does not run.
LLMs are trained and post-trained to produce grammatically correct prose for readers. Voice agents need something different: text that sounds natural when spoken. Without guidance, LLM output sent to a TTS model can sound like formal, stiff prose read aloud. That leaves the LLM with two jobs: write conversational speech, then format it so Rime’s normalizer reads it correctly. The system prompt at the end handles both.

Sound like a person

The agent is not trying to pass as human. Its voice should make callers comfortable enough to respond naturally, which usually leads to better outcomes. Real speech includes fillers, restarts, soft pauses, and occasional phrases like “yeah, no.” Coda does not accept SSML. Do not use <break>, <emotion>, or other inline tags. The only supported inline function is spell(). Rime deliberately keeps the interface small. Coda uses the meaning of the text to shape emotional delivery, while punctuation controls pacing and emphasis. Exclamation marks and interrobangs add excitement. Commas and ellipses add pauses.

Show, don’t tell

Instructions like “be conversational” are too vague. Give the model examples it can imitate instead. The right register depends on the call type, persona, and caller, so the examples below are not universal. They show the gap between default LLM prose and speech that usually sounds more natural. Even formal calls include occasional fillers and restarts. Use them lightly.

Put disfluencies in the text

Write “um,” “uh,” “so,” “yeah,” and “well” where someone would genuinely hesitate. Do not rely on tags, and do not stack fillers. Two “um”s in a row sounds like a bug.

Punctuation controls prosody

  • Comma. Short internal pause with a slight rise.
  • Period. Sentence end, falling pitch.
  • Question mark. Rising intonation.
  • Ellipsis. Hesitant or trailing pause. Use sparingly.
  • Semicolon. Somewhere between a comma and a period.
Keep spoken sentences under 25 words. Long sentences without internal commas sound breathless, so split them.

Describe personality through speech

Replace adjectives like “friendly” or “warm” with observable speech patterns the model can imitate. “Friendly” requires interpretation. “Starts sentences with ‘yeah’” gives the model a behavior. Keep the baseline calm and even. Save exclamation marks for situations that warrant them. A support agent does not need excitement in every reply.

Normalize cleanly

The Rime normalizer reads common formats natively: currency with symbols, full dates, clock times with minutes, phone numbers, percentages, and standard measurements. Pass these values through unchanged:
Expand only the patterns in Pre-normalization before synthesis. Text normalization contains the full reference. Send any tricky string to the /textnorm endpoint before release to confirm how Rime will read it.

Use spell() for IDs

If Rime must read an identifier one character at a time (confirmation codes, account numbers, SKUs, vanity phone letters), wrap it in spell(). spell() is processed by the Mist family (on Mist v3 it groups characters in threes where possible and pairs where necessary, and handles symbols such as @ and -); Coda’s pipeline passes it through to the model unprocessed.
Do not use spell() for standard phone numbers (digit grouping sounds more natural without it) or for real words that happen to be uppercase. Avoid dashes in numeric IDs; they cause unnatural pauses. Use spaces or spell() instead.

Drop-in system prompt

This system prompt combines the voice and normalization guidance above. Paste it into your LLM’s system message, then adapt it to the agent’s persona.
voice-system-prompt.md