Best practices
Writing prompts for voice
How prompt writing changes when every word is spoken aloud, and which assistant field each kind of instruction belongs in.
A prompt that reads well on a screen usually fails out loud. The caller cannot skim it, cannot scroll back to the part they missed, and will start talking over anything that runs long. The same wording that produces a good chat answer produces a bad phone call. Writing for voice is a different craft, not a shorter version of the same one.
What follows is that craft, and where each kind of instruction belongs on an OnCore assistant.
Where prompt text lives#
An assistant's spoken behavior comes from several fields at once. Knowing which one to reach for is half the work.
| Surface | Field | What belongs in it |
|---|---|---|
| Shared system prompt | promptId → a prompt | Persona, tone, and rules you want several assistants to share |
| This assistant's rules | developerPrompt | Behavior specific to one assistant, injected into the default system prompt |
| Values that change | parameters | Facts referenced from the prompt as {{placeholders}} |
| Small behavior tweaks | Custom instructions | Up to six titled rules, 500 characters each |
| Step-by-step flows | Task groups | An ordered sequence the assistant works through when taskDrivenMode is on |
| Opening line | firstMessage | The exact words that start the call |
| Closing line | endOfCallMessage | The exact words before the assistant hangs up |
| Silence prompts | idleMessages | What the assistant says when the caller has gone quiet |
| Tool behavior | A tool's description and instruction.steps | When to call your endpoint, and what to say around the call |
| Post-call analysis | summaryPrompt, structuredDataPrompt, categories | How the call is summarized and classified afterwards |
| Hand-off briefing | whisperSummaryPromptId | What a colleague hears before a warm transfer connects |
| Return message | warmReturnMessage | What the caller hears when a hand-off goes unanswered |
Two properties of this set matter more than any individual field.
They compose, they do not replace. A developerPrompt, a shared prompt, six custom instructions, and a linked task group all reach the same conversation. When an edit produces no change in behavior, another surface is usually supplying the behavior you are trying to remove. Calls and assistant behavior walks through untangling that.
Configuration is read when a call starts. A call already in progress keeps the configuration it began with, so every prompt change is tested by placing a new call.
Write turns, not paragraphs#
In text, a long answer is generous: the reader takes what they need and ignores the rest. Spoken, a long answer is an obstacle: it arrives one word at a time, at a fixed speed, and the caller has to sit through all of it.
The unit of a voice prompt is the turn: one thing said, then the floor handed back. Instruct for it explicitly.
Answer in one or two sentences, then stop and let the caller respond.
Never list more than three options at once. If there are more, name the
three most common and offer to go through the rest.
Ask one question at a time. Do not stack a second question onto the first.Two consequences of getting this wrong:
- Long turns get cut off. The caller barges in partway through, the assistant stops speaking, and everything after the interruption is simply never said, including the question you needed answered. You can tune how easily that happens with
interruptionPlan(minDuration, 0 to 5 seconds of sustained speech;minWords, 0 to 10 transcribed words), but tuning the barge-in threshold is a worse fix than not monologuing. - Stacked questions get one answer. Ask "What is your name and what date were you thinking?" and you will reliably get a name and silence, or a date and silence. Then the assistant asks again, and the caller feels unheard.
If the assistant genuinely has to deliver something long (terms, a list of times, an address), have it say so first and check: "There are six slots free that afternoon. Do you want me to run through them, or narrow it down first?"
Formatting is silence#
Everything the assistant produces is spoken. Markdown, bullets, numbered lists, headings, emphasis, emoji, and tables have no spoken form: at best they vanish, at worst they are read out as punctuation.
Say so in the prompt, because a language model's default habit is to format:
Never use bullet points, numbered lists, markdown, or emoji. Everything you
say is read aloud. Use plain spoken sentences and connect items with words
like "and", "or", and "after that".The same rule applies to anything you inject. A {{placeholder}} filled with a markdown table, or knowledge-base content pasted from a formatted document, becomes spoken punctuation. Store values in the form you want heard: "10am to 10pm, seven days", not "| Mon-Sun | 10:00-22:00 |".
Say numbers the way people say them#
Digits and symbols are where written and spoken text diverge hardest, and the assistant says whatever it writes. Tell it the spoken form you want.
| Written | What you want heard |
|---|---|
$1,250.00 | "twelve hundred and fifty dollars" |
2026-08-17 | "the seventeenth of August" |
+1 555 555 0123 | grouped in threes and fours, slowly |
A4B9 | "A as in alpha, four, B as in bravo, nine" |
[email protected] | "jo dot smith at example dot com" |
A workable instruction:
Read phone numbers and reference codes digit by digit, grouped, with a
short pause between groups. Never say a code as a word. Read money as
words, not symbols. Say dates as a person would say them, never as
numbers separated by dashes.Reference codes deserve their own rule. If callers routinely read back booking references or member numbers, ask the assistant to use a phonetic alphabet for letters. "B as in bravo" costs a second and removes the most common source of a wrong record.
Confirm before you commit#
The caller is on a phone line, possibly outdoors, possibly on speaker. Speech recognition is good, not perfect, and a misheard name is invisible until something goes wrong downstream. So the rule is simple: anything the assistant is about to act on gets read back first.
Before booking, changing, or cancelling anything, repeat the details back
in one sentence and wait for a yes. Spell names back letter by letter.
Read phone numbers and email addresses back digit by digit or word by word.
If the caller corrects you, repeat the corrected version back once more.Confirm the things that are expensive to get wrong (names, numbers, dates, quantities, addresses) and skip the things that are not. An assistant that confirms everything is exhausting, and callers stop listening to confirmations they hear five times.
Two related settings:
phoneNumberPassThroughlets the assistant reference the caller's own number ("Would you like to use the number ending in 595?") instead of asking them to recite it. That is both faster and more accurate. With it off, the assistant always asks, in which case make sure your prompt has it read the number back.- Capture forms are the better tool when you are collecting a fixed set of typed answers. Each field has its own
question, an optionalpromptsteering how it is asked, and the results are delivered to the recipients you name. The structure lives in the form rather than in prose you have to keep re-describing.
Never leave the caller in silence#
Silence on a phone line reads as a dropped call. Within about two seconds, callers say "hello?", and if that lands mid-turn it registers as an interruption. Three places to close the gaps:
While a tool runs. A tool call is a live request inside the conversation. A tool's body.messages can carry a request-start filler spoken while it runs, either fixed text or phrased by the model. "Let me check that for you" costs nothing and buys you the round trip.
When the caller goes quiet. idleMessages are spoken after idleTimeoutSeconds of silence, at most idleMessageMaxSpokenCount times. Write them as escalating checks rather than repeats of the same line ("Are you still there?", then "I'll stay on the line for a moment", then a graceful close), so a caller who has genuinely walked away ends the call cleanly instead of holding an open line.
Between a question and an answer the assistant has to think about. Instruct it to acknowledge first and answer second: "Good question, one moment" beats a pause.
Tell it what to do when it does not know#
Most of the damage a voice assistant does is confident invention: a price it has not been given, a policy it inferred, an appointment it implied it had made. A prompt that only describes what the assistant can do leaves the model to improvise the rest.
Write the boundary and the exit together:
If you do not know something, say you do not know and offer to have someone
call back. Never guess a price, a policy, an availability, or a delivery
date. If the caller asks for something outside bookings and opening hours,
say it is outside what you can help with and offer to put them through.Then make the exit real. An instruction to "put them through" needs a transfer reason that actually matches the situation and a destination that answers. If that destination is not always staffed, the warm-return mode is what stops the caller landing in a ringing void.
Put moving facts in parameters, not in prose#
Opening hours, branch names, and prices belong in parameters and are referenced from developerPrompt as {{placeholders}}. One prompt then serves every location, and updating a fact is a value change rather than a prompt rewrite.
{
"developerPrompt": "We are open {{opening_hours}} at {{branch_name}}.",
"parameters": { "opening_hours": "10am to 10pm", "branch_name": "Newtown" }
}The names must match character for character. {{openingHours}} is not filled by opening_hours. The caller simply hears the literal braces, which is the single most common cause of an assistant saying something obviously wrong.
Where parameters apply
At call start, OnCore substitutes assistant parameters across the assembled voice prompt. That includes the shared prompt, developerPrompt, custom instructions, and per-call custom prompt sections. An unmatched {{key}} remains literal.
Task instructions are separate: they do not receive assistant parameters. Task groups use single-brace placeholders such as {booking_id} for call context and outputs from earlier tasks. Capture-form fields use that form's own properties for their documented {{property}} placeholders.
Choose the smallest surface that can carry the change#
When behavior needs adjusting, the instinct is to edit the main prompt. Usually something smaller is correct, and smaller changes are easier to reverse when a Tuesday's calls come back worse than a Monday's.
| You want to… | Reach for |
|---|---|
| Change persona or tone everywhere | The shared prompt: several assistants can point at one |
| Change one assistant's rules | developerPrompt |
| Add a small, standalone rule | A custom instruction: titled, capped at six, easy to delete |
| Update a fact | parameters |
| Enforce an order of steps | A task group, with per-assistant instructionOverride for the one venue that differs |
| Collect a fixed set of answers | A capture form |
| Change when a tool fires | The tool's description: that text is what the model selects on |
| Change how expressive the voice sounds | deliveryMode and expressiveOptions, not prose about tone |
That last row is worth dwelling on. Delivery (pacing, fillers, laughter) is a configuration setting on the assistant, not something to litigate in the prompt. Asking a prompt to "sound warm and natural" mostly spends words; deliveryMode addresses it directly, and expressiveOptions.instructionsAppend exists for guidance that genuinely is about delivery. Both modes depend on the voice you picked. Voices that do not support the mode keep their normal delivery. Read Expressive mode or Emotion tagging before writing prompt text to compensate, and Eleven v3 audio tags if the voice is eleven_v3 and you want to write tags by hand.
Hear it before you ship it#
Voice prompts cannot be reviewed by reading. Three cheap checks, in order:
Read the assistant's lines out loud#
You will catch stacked questions, unspeakable formatting, and sentences that run out of breath faster than any review will.
Place a real call#
Browser calling gets you a live conversation with the same assistant without dialling anything, and accepts a per-call firstMessage so you can jump straight into the part you are testing.
Read the transcript afterwards#
The transcript on the end-of-call report shows what was actually said versus what you intended, including the turns that ran long enough to be interrupted. Do this after every prompt change for the first few days.
Then change one thing at a time. Prompt surfaces compose, so editing three of them at once and placing one call tells you nothing about which edit did what.
Next steps#
- Debugging a voice agent: how to find which layer a bad call actually broke in.
- Prompts: creating, sharing and linking the prompt records themselves.
- Create and configure an assistant: every field named on this page, with its type and limits.
- Task groups: when a conversation needs an enforced order rather than more prose.