Skip to main content
A voice prompt is a script for a two-minute phone call, not a chatbot persona. The call has one job, one caller and one ending. Everything the model writes is spoken aloud, at speaking speed, to someone holding a phone to their ear. Every extra word costs the caller time, an unclear line can end in a hang-up, and a paragraph turns into a monologue. The method is the same every time: design the call as a structure, test it against a caller who says no, and refine it one line at a time. This page covers the mechanics. The thinking behind them is in The Zen of Voice Agents.

Why voice is not chat

Everything else on this page follows from three constraints. The caller cannot scroll, and cannot re-read. A sentence they missed is gone. Anything that matters should be said once, briefly, and then read back. A long reply is the thing they wait through. They hear every word before they can answer. Reply length is the single biggest latency lever you own, bigger than anything in the stack. Cap it in the prompt, in words the model cannot round up: “one short sentence, maximum two”. Turn-taking replaces reading. In chat you can ask three things in one message and let the reader sort it out. On a call, two questions in one turn get one answer, and you will not know which question it answered. Ask one thing, then stop.

What the engine already does

The engine already handles a lot of what people write into voice prompts. Repeating it in the prompt only spends turns and tokens.
  • The opening line runs before the model does. The engine speaks first_message the moment the callee answers, so it sets your first-audio latency. The model is told what was said, so it does not greet twice.
  • Refusals already end the call. When end_call.enabled is true (the default), the engine appends an ending rule to every prompt. If the caller refuses or asks to end (“नहीं चाहिए”, “बात नहीं करनी”, “रखता हूं”, “call खत्म करो”), the agent does not re-sell. It says one farewell sentence and calls end_call. A second refusal gets the same treatment.
  • A bare “ok” does not hang up. With end_call.confirm: true (the default), the first end_call inside the window asks the caller to confirm; the second one ends the call.
  • Barge-in is automatic. The caller can talk over the agent. After two words of caller speech, the agent stops and listens. If they barge in without actual words, the agent says “हाँ, बोलिए ना, क्या बात है?”.
  • Silence is handled. If the caller goes quiet for about 10 seconds, the agent checks in once. If they stay quiet, it says a short goodbye and the call ends with idle-timed-out.
  • Voicemail is detected by the engine and handled by the agent’s voicemail setting.
  • Per-call data is substituted for you. {{placeholders}} in both system_prompt and first_message are filled from the call’s variables.
None of this belongs in your prompt. Use the prompt for the job the call has to do.
The agent can only do what its tools do.Besides ending the call, an agent acts only through the tools you give it: HTTP requests to your own systems before, during or after the call, and built-ins such as scheduling a callback. Transfer to a human is not available yet, so a prompt must never promise “I’ll transfer you”. It must not promise “I’ll send you the link” or “I’m booking it in the system” either, unless a tool on that agent does exactly that. Without one, the honest line is “the team will call you back” or “आपको team से call आएगा”. For branching conversations, use node-based agents.

The structure

Every house template uses the same six blocks, in this order, and nothing else:
ROLE is one sentence with the name, the company and the reason for the call. “You are मीरा, a polite female voice agent calling from Mirai Finance to remind the customer their EMI is due and capture a clear payment commitment” is a complete role. FACTS sets the boundary of what the agent may say: amounts, dates, policy and what it cannot do. If a claim is not in FACTS, the agent does not make it and says the team will call back instead. This is the block your customer edits. CALL FLOW is numbered steps, one ask per step, in the order a person would ask them. Steps are instructions to the agent, not lines to read aloud. IF THEY PUSH BACK allows one nudge, then acceptance. The engine already stops a hard refusal, so this block is for the soft “not right now”. EXAMPLE EXCHANGE is two to four turns of the hardest moment done right. Models copy tone from examples far more reliably than from adjectives, so two good turns do more than a paragraph about being warm and professional. LANGUAGE RULES + CONVERSATION STYLE is the fixed block shown further down this page. Paste it verbatim at the end of every prompt.

The opening line

first_message is spoken before the model runs, so all of it adds to first-audio latency. Keep it to the agent’s name, the brand and a check that you are speaking to the right person.
Leave the pitch out of the opener. The model already knows what was said and carries on from there. Hindi verbs are gendered, and the verb has to match the voice. This catches everybody at first. The console renders this for you when you pick a template. The API does not, so if you switch voice_id on an existing agent, fix the opening line in the same request.

Language rules for Hinglish

Real Indian phone calls use Hindi grammar with English nouns mixed in. An agent that sticks to one pure language sounds like a recording. The console appends this block to every template. Paste it at the end of your prompt, unchanged:
Why each rule is there:
  • Devanagari for Hindi words. Romanized Hindi in the prompt gets read as English. “kar payenge” comes out with English vowels, and the caller hears an accent instead of a person.
  • Roman script for English words. Nobody on a phone call says भुगतान; they say payment. Writing the English word in Roman script matches how the sentence is actually spoken.
  • No shuddh Hindi. Formal Hindi belongs in a government notice. On a phone call it sounds like a recording, even when the audio is perfect.
  • Numbers as English words. The voice reads English number words most reliably. Digits and Hindi number words are read inconsistently.
  • धन्यवाद once. Models over-thank, and thanking four times in ninety seconds is the clearest sign that nobody is there.
For English calls (language: "en-IN") the shape is the same: drop the Devanagari rule and keep everything else. Numbers still go in as words, and identifiers are still read digit by digit.

Numbers, dates, amounts and identifiers

The model copies what you write straight into speech, so write numbers the way they should sound. Amounts and quantities are natural words, and a quantity can sit inline in a Hindi sentence (“दो items”). Identifiers (pincode, phone, order id, vehicle number, challan number) are always read digit by digit and never grouped into “ninety-eight thousand”. Digit-count sanity. An Indian pincode is six digits. A mobile number is ten. If a read-back is short, the recogniser dropped digits, and the agent must push back instead of accepting it:
The read-back protocol has three moves, and it belongs in every flow that touches a number. The caller states the number, the agent reads it back digit by digit, and then the agent asks “सही है?”. Nothing gets written down until the caller confirms.

Facts, and the customer

The agent may say what is in FACTS and nothing more. Anything outside it, such as a policy question, an exception or a price you did not list, gets the answer “the team will call you back”. Never invent policy, waive a penalty or quote a number that is not in FACTS. Per-call data goes in variables, not in the prompt. One agent runs thousands of calls, and the customer’s name, amount and date change every time. Hard-coding them means managing one agent per customer.
Those values are already in spoken form on purpose. The model copies a variable’s value verbatim into speech, so format it for the ear when you build the map, not in the prompt. five thousand two hundred comes out right every time, and 5200 might not. How variables behave:
  • Names are matched loosely. {{Customer Name}}, {{customer_name}} and {{CustomerName}} are the same variable, because matching uses only letters and digits and ignores case.
  • An unknown placeholder in the system prompt becomes an empty string. It does not error, and it does not leave braces for the agent to read aloud.
  • Values are plain strings, and braces inside a value are stripped.
  • Variables are static per call. There is no way to change one mid-call.
  • Keep them short, because they count as prompt tokens on every turn.
Tell the agent what day it is. Without it the model does not know, and “tomorrow” or “this Friday” becomes a guess. The prompt supports Liquid filters, so put the real date in at call time, in IST:
If the script mentions a time window, include the time as well:

The flow

  • One ask per step. Two questions in one turn get one answer, and you will not know which one it was.
  • Never assume what was not clearly said. If the caller mumbled a date, the agent asks again. A confidently wrong confirmation is worse than a second question.
  • Confirm by exception. Read back only what changed, and do one consolidated read-back at the end. Confirming every field turns a ninety-second call into three minutes.
  • Listen when they are dictating. While the caller reads out an address, the agent should only give backchannels (“जी”, “हम्म”) and then do one read-back at the end. If it interrupts to confirm line one, you lose the rest of the address.
  • Mishear recovery is surgical. Re-ask the one field that was wrong. Never restart the flow.
  • Answer, then return. If the caller derails with a question, answer it in one line from FACTS and go straight back to the step you were on.
  • Every turn moves forward. Acknowledge and ask the next thing in one utterance. A turn that only says “ठीक है” costs the caller time without moving the call on.

Pushback and endings

Allow one light nudge, then accept the answer. The engine already enforces the refusal ending, so your job is the success ending. It is the line people forget:
Without it the model keeps talking, because nothing tells it the job is done. A “no” is a valid outcome. Capture it and close cleanly; a refusal that ends in twenty seconds is a good call. The close has three moves: a one-line summary of what was agreed, a goodbye, then end_call. Say धन्यवाद once, in that goodbye. If you leave end_call.message empty (the default), the model’s own goodbye is the farewell. If you do set a message, it is spoken after the model’s goodbye, so it must not repeat it. A धन्यवाद in both means the caller hears it twice. Finally, size the call. max_duration_secs is a hard cap, and hitting it ends the call mid-sentence with ended_reason: exceeded-max-duration. For a one-job call, 180 to 300 seconds is right. The default is 300, and the allowed range is 30 to 1800.

Sounding like a person

  • Lead word up front. Starting a turn with “जी।”, “अच्छा—” or “ठीक है।” makes the voice start sooner, and the agent sounds like somebody who was listening.
  • Punctuation is your only expressiveness control. Use interjections and emphasis at the moments that need them, such as an apology or a pushback, and keep everything else flat. When every line is expressive, none of it stands out.
  • No stage directions, no tags, no emoji, no markdown. The voice reads the text it is given. Asterisks, bullet characters and (warmly) come out as noise.
  • Match the caller’s register. If they answer in English, the agent continues in English. If they switch to Hindi mid-call, so does it.
  • Contractions and everyday words. Write the sentence you would say out loud, not the one you would put in an email.

What not to write

Test, then refine

Every real phone call costs money (there is no test key), so the loop is designed to find problems in the cheapest place first.
1

Start from a template

Agent Studio in the console has six house scripts in the template dropdown: Govt · Traffic challan, BFSI · EMI reminder, BFSI · GSTR-1 filing, D2C · Order confirmation, D2C · Service reminder and Hospitality · Booking confirmation. All six already follow the structure above. If none of them is close, use Describe the call and we draft it → Generate script. You write a one-line brief and get back a house-style prompt and opening line to edit.
2

Call yourself on the web phone

The web phone in the right rail runs the agent without dialling a phone. Play the customer you are afraid of: say no, correct a digit half-way through, ask something that is not in FACTS, then go quiet and see what happens. You can catch most prompt bugs here, and it costs nothing.
3

Read the transcript, change one thing

Turns come back as they were spoken, without translation. See Get the transcript. Find where it went wrong, change one line and run it again. If you change three lines at once, you cannot tell which one worked.
4

Three real calls to your own number

A phone line sounds very different from a browser mic, with carrier codecs, background noise and callers who are walking. Prompts often pass on the web phone and fail on a real handset, and numbers are the first thing to break.
5

A small campaign, then read it

Start with twenty to fifty contacts. Read the transcripts and the campaign report, and fix what you find before you scale up. See Campaigns.
Judge a call by its outcome. Did it reach a defined end state (confirmed, refused or callback)? “It sounded nice” is not a metric, and a warm agent that never gets a commitment has still failed the call.

A worked example

Here is the EMI reminder, rendered for the aishe voice with the agent named मीरा. system_prompt:
Replace the last line with the fixed block from Language rules, pasted verbatim. first_message:

Create the agent

emi-agent.json
Keep the prompt in a file next to your code and read it in. It is a script that will change often, so it does not belong inline in a JSON literal. end_call is left at its defaults on purpose (confirmation on, no canned farewell), so the धन्यवाद in the EXAMPLE EXCHANGE is the only one the caller hears.

Place the call

As before, the variable values are already in spoken form.

Copy-paste skeleton

Fill in the angle brackets and keep everything else.

If a prompt still is not working and the structure is right, the problem is usually a belief about what a call is. The Zen of Voice Agents covers that.