config.prompt is where the agent’s behaviour lives. Model choice moves latency and cost; the prompt decides whether the agent is any good. This page is about writing one — the mechanics of the {{…}} tokens in it are in variables and userdata.

The structure that works

Give the prompt five things, in this order: Two habits are worth more than any wording. First, write the rules as things to do rather than things to avoid — “ask for the order number before you look anything up” beats “don’t guess order numbers”. Second, when the agent does something wrong on a real call, add the rule that would have prevented it rather than rewriting the prompt from scratch.

Writing for speech

A voice or video prompt is not a chat prompt with a different model behind it. The output is played through a text-to-speech voice into somebody’s ear, and everything that makes a document readable makes speech worse.
  • Natural, brief and interruptible. Two or three sentences per turn. A caller cannot skim, and a long answer is a long wait for the one clause they needed.
  • Never dump long information. Give the next useful piece and ask whether to go on. “There are four plans. The one most people on your usage pick is Growth — want me to run through it, or list all four?”
  • No markdown, no emoji, no JSON, no bullet lists in anything the agent says. Say so in the prompt; models default to formatting because their training data is written.
  • Spell out anything the voice will mangle. Text-to-speech reads symbols and abbreviations unevenly across providers and languages. Give the agent the spoken form you want:
    • Currency: “say amounts as words — ‘one thousand two hundred rupees’, not ‘₹1200’.”
    • Reference numbers and codes: “read codes one character at a time, with a short pause between groups: ‘A — seven — X — nine’.”
    • Dates and times: “say ‘Thursday the ninth of April, at four in the afternoon’, not ‘09/04’ or ‘16:00’.”
    • Abbreviations and product names: give the pronunciation once — “say GST as ‘gee ess tee’; say Northwind as one word.”
  • Say what to do while a tool runs. A tool call is silence on the line, and silence reads as a dropped call. “Before you look an order up, say you are checking and give the caller something to hold on to: ‘Let me pull that up, one moment.’”
  • Give it an out. Tell the agent what to say when it does not know, and when to hand over. A model with no permission to fail invents an answer.
On a text agent none of this applies. Formatting is fine, length is cheaper, and a person can re-read.

Personalizing a prompt

The prompt and the greeting are substituted per session, before the agent starts. Three roots are available in both: Use them well:
  • Write so the sentence survives an empty value. A field that is not in userdata resolves to nothing, not to an error, so You are speaking with {{userdata.name}}. becomes “You are speaking with .” on a caller you know nothing about. Prefer a form that reads either way: If you know the caller's name it is {{userdata.name}} - use it if it is there, and ask otherwise.
  • Branch on {{system_vars.direction}} to let one agent open differently on a call it received and a call it placed.
  • The clock is frozen at the moment the agent starts. {{system_vars.date}} and {{system_vars.time}} do not tick during the call, so an agent reasoning about “in ten minutes” needs a tool, not the prompt.
  • {{system_vars.now}} is a machine timestamp (2026-08-19T19:26:59+05:30). Send it to an API from a tool; never put it in a line the agent will read aloud.
  • Any clock variable requires config.timezone. Using one without setting the timezone is a save error, naming the field.
A token whose root is not one of ours is an error at save, not text. A bare {{name}}, a {{customer.number}} pasted from another platform, or a typo like {{userdate.name}} is refused. So is {{userdata}} with no field — that would hand the model the whole bag. Rewrite each one onto a real root.

What does not belong in a prompt

Reading a {{vars.x}} the agent does not declare is a warning, not an error: the request that starts a session can legitimately supply one. Everything else in this table fails the save.

Examples

Adapt one rather than starting from a blank box, and test it with a real call before publishing — the dashboard editor has a test panel beside the config.

Next

Variables

Declaring {{vars.*}} and supplying values per session.

Userdata

What the agent knows about the person, and how tools write to it.

Tools

Giving the agent something to do besides talk.