📝 Beginner ~9 min Volatile · 14d

Write a Call Script That Doesn't Loop

Six named prompt blocks, the turn-limit settings that stop a caller looping, and two vendor rules on prompt length that flatly contradict each other.

The AI Dude · Published July 31, 2026 · Verified July 31, 2026

Assumes you've done: What a Voice Agent Actually Needs, How to Use Grok Voice Agent Builder: No-Code Tutorial. Advisory, not a gate — this page stands on its own.

ElevenLabs' prompting guide tells you to say your most important instruction twice. xAI's migration notes tell you to cut your prompt down and delete the instructions you added to patch model quirks. Both are official documentation, published by the companies that trained the models, and they point in opposite directions.

That disagreement is the first thing to understand about call scripts. Prompt advice is not portable between platforms, and a script that behaves on one stack can loop on another for reasons neither vendor writes down. What is portable is the structure, and the settings underneath the prompt that decide when the agent stops talking.

Six named blocks, because the model reads the headings

ElevenLabs breaks a system prompt into Personality, Goal, Guardrails, Tone, Environment and Tools. The order is not decorative. The guide says of one of them: "Dedicate a guardrails section... Models are tuned to pay extra attention to this heading."

The examples in the docs are short and specific, which is the point:

Personality: "You are a customer service agent for Acme Corp. You are polite, efficient, and solution-oriented."
Goal: "Help customers resolve issues quickly by looking up orders and processing refunds when appropriate."
Guardrails: "Never share customer data across conversations or reveal sensitive account information"
Tone: "Keep responses concise (under 3 sentences) unless the user requests detailed explanations."

Two things worth copying from that. The Goal block names the tools by their job, so the model knows an order lookup is a thing it can do rather than a thing it should describe. The Tone block sets a hard sentence budget. On a phone call, a four-sentence answer is a caller reaching for the zero key.

The guide's advice on emphasis is oddly mechanical and worth repeating verbatim: "Repeating the most important 1-2 instructions twice in the prompt can help reinforce them," with "This step is important" appended at the end of critical lines. Its own worked example carries the verification rule in both the Goal and the Guardrails sections, phrased as "Never access account information without identity verification. This step is important."

The same page then says "Avoid repeating tone guidance throughout the prompt." So repetition is a tool for rules and a defect for style. That distinction is not explained anywhere on the page, and it is the sort of thing you find out by watching an agent turn into a broken record about being friendly.

Three documented settings that produce a loop

A looping agent is usually blamed on the prompt. Often it is a parameter.

Idle re-engagement. Grok's speech-to-speech session takes turn_detection.idle_timeout_ms, and the documentation describes exactly what happens when you set it: "the server proactively re-engages the user if no speech is detected for this many milliseconds after the assistant finishes responding. The timer re-arms after every response, so it fires repeatedly each idle_timeout_ms until the user speaks." The default is null. Set it to 3000 because you wanted a friendly nudge, and a caller who has put the phone down gets nudged every three seconds until the line drops.

No cap on the caller's turn. LiveKit's turn documentation exposes max_words and max_duration to "Cap how long a user can speak before the agent interrupts," and states plainly: "Both default to disabled, so the feature is off until you opt in." It also documents the accounting, which surprises people: "Word count and duration accumulate across consecutive user turns and reset only when the agent transitions to the speaking state."

False interruptions that restart the sentence. When the agent stops mid-sentence for a cough and then begins again from the top, the caller experiences a loop. LiveKit gives this its own event and two settings: false_interruption_timeout, the silence duration before an agent_false_interruption event fires, and resume_false_interruption, described as "Whether to resume the agent's speech after a false interruption is detected." Resume from where it stopped, and the loop disappears. Restart the turn, and it does not.

Two more dials belong in the same review. min_duration sets the minimum speech length that counts as an interruption, and min_words sets the "Minimum number of words to be considered as an interruption. Only used if STT is enabled." A single-word threshold turns a caller's "mhm" into a barge-in.

Lines that must never be improvised

Some sentences on a call are legal text. A model asked to say them will paraphrase, because paraphrasing is its job. Grok's API has a specific escape hatch for this, an item type called force_message that makes the agent "speak a hard-coded, TTS-synthesized line without involving the model," listed in the docs for "scripted greetings, compliance disclosures (e.g. 'This call is being recorded'), IVR prompts, or any utterance that must be delivered verbatim."

It takes three fields. item.type must be "force_message", item.content[].text carries the verbatim text, and item.interruptible defaults to true. Set that last one to false and "caller audio is dropped until playback completes," which is what a recording disclosure needs and what a greeting definitely does not.

The neighbouring parameter fixes the other scripted-line problem. replace maps phrases to spoken substitutions applied before text to speech, so mapping "Acme Mobile" to "Acme Mobull" changes only the audio while the transcript keeps the original spelling. The matching rules are strict and documented: case-insensitive, longest match wins, and whole-word boundaries are required, so Acme, Mobile, Acme-Mobile and Acme Mobiles do not match. Write out the variants or the brand name comes back mangled in half the calls.

For context that changes per call, there is a third option: set instructions on response.create and "The override applies only to this response." That is the documented way to inject CRM data for one turn without rewriting the session prompt.

Branching you can prove beats branching you hope for

A long prompt full of conditional sentences is a state machine written in English, evaluated by a model, with no way to test a path. ElevenLabs' workflows editor pulls the graph out of the prose. The node types are Subagent, Dispatch tool, Agent transfer, Transfer to number, and End, which "terminate the conversation flow gracefully."

The edges are where the loop protection lives. Four transition types are documented: Unconditional, LLM Condition, Expression, and Tool Result Edges that route on a "Success path" or "Failure path." Expression conditions provide "deterministic evaluation criteria based on data structure"; LLM conditions ask the model to judge in real time.

Use an Expression edge for anything you can represent as data. Whether the caller's date of birth has been captured is a variable, not a vibe. Reserve LLM conditions for genuinely fuzzy routing, such as whether a caller sounds like they want to cancel. And give every tool node an explicit Failure path, because the most common production loop is an agent whose calendar lookup returned nothing, asking for a preferred date again.

The advice that does not travel between vendors

Back to the disagreement at the top. xAI's guidance for its current voice model is the mirror image of the ElevenLabs playbook: "Simplify your system prompt. The model is significantly more capable, so your prompt should be much shorter." And: "Remove workaround prompting. Prompt hacks and edge-case fixes needed for GPT models are unnecessary. Strip out instructions added solely to patch bugs or limitations of the previous model." The same section notes that reasoning.effort defaults to "high" and can be set to "none", which is a behavioural lever a prompt cannot reach.

Neither vendor is wrong. They are describing different models with different training. What that means for you is narrower and more annoying: a script tuned on ElevenLabs and pasted into Grok Voice Agent Builder carries emphasis tricks that the receiving model was explicitly trained not to need, and vice versa. Port the six blocks. Rewrite the reinforcement.

One last detail from the ElevenLabs guide, since it is the only named model setting on the page: text_normalisation_type takes system_prompt as its default or elevenlabs as the alternative. There is no temperature or turn-timeout value published in that guide at all. If you want those, they are in the platform settings rather than the prompt, and the prompting documentation does not tell you where.

voice agent promptssystem promptcall scriptturn detectionconversation design
Changelog (1)
  • July 31, 2026 — First published.