Agent design

How to fix an overloaded voice-agent prompt

An overloaded prompt asks the model to remember policy, track where the call is, decide on actions and keep a speaking style, all at once. Fix it by resolving contradictions, separating instructions from facts, moving enforceable rules into code and giving the model only what the current turn needs. Measure correctness and latency before you call it an improvement.

By Mirai Minds · Updated

Find the failure before you shorten the text

Collect failed turns and write down what went wrong in observable terms. “The prompt is too long” is too vague to act on. The agent might repeat a question after getting the answer, ignore a correction, claim a tool succeeded when it timed out, or keep selling after the caller asked to stop.

Map each failure to the instruction, missing state or tool behaviour that should have prevented it. If the same rule appears in several contradictory forms, editing only the last one keeps the contradiction.

On Mirai, the agent’s logs help with this step. GET /v2/agents/{id}/logs returns one row per event on the agent’s calls: tool runs and their errors, the variables each call received, the post-call analysis, and a tool_missing warning when the model asked for a tool the agent doesn’t have. That warning usually means the prompt names a tool you never added. GET /v2/agents/{id}/logs/summary counts errors and warnings by part, so you can see where to look first.

Separate five kinds of content

Prompt content Better home
Role, speaking style and shared stop behaviour A short, stable instruction core
The current goal and the next missing fact The current task, or the current node’s prompt
Confirmed details and their revisions Typed application state
Policy documents and large tool payloads Retrieved on demand, or reduced to the fields needed
Permissions, idempotency and action prerequisites Checks on your server

The prompt can explain a permission to the model while your code enforces it. In a workflow, a guarded transition gives you an explicit place to check prerequisites; see the guard concept. Tool output and retrieved text are data. Treat them as data even when they contain imperative sentences.

Some things don’t belong in the prompt at all, because the engine already does them. Mirai’s prompting guide lists them: the opening line is spoken before the model runs, refusals already end the call when end_call is on, barge-in and silence are handled, and placeholders are filled from the call’s variables. “Wait for the user to finish speaking” only spends tokens.

Resolve a contradiction with an explicit priority

Here is an intentionally flawed, fictional appointment prompt:

Always finish booking. Never end without an appointment.
Respect the caller if they want to stop.
Ask for the date, then ask for the time. Always follow that order.
Do not repeat questions. Confirm every detail repeatedly.
If booking times out, try again until it works.
Always sound confident and say the booking is handled.

A bigger context window won’t fix these conflicts. “Always finish” fights with stopping. A rigid question order ignores what the caller already said. Retrying until it works ignores whether the booking system already committed the first attempt.

Replace it with a scoped instruction set:

Role: Help the caller arrange an appointment. Keep replies brief
and natural in the caller's language.

Priority: A request to stop or speak to a person overrides booking.
Never claim an action succeeded without a matching tool result.

Current task: Collect the missing appointment preference.
Use validated state for facts already provided. Ask one focused
question about what is missing. If the caller corrects a fact,
submit the correction before asking the next question.

Do not create an appointment in this step. The application will
offer available slots and collect confirmation in later steps.

This is an example transformation, not an evaluated production prompt. The full workshop includes the state contract and the tests that go around it. Mirai’s prompting guide adds a rule that applies here: a prompt must never promise an action no tool performs. Transfer to a person is not available yet, so “the team will call you back” is the honest line.

Make state changes invalidate old assumptions

Store a revision number for the appointment preference, and link availability results and confirmations to it. If “Tuesday” becomes “Thursday”, bump the revision and drop the results that depended on Tuesday. Keep the caller’s turn as evidence so a reviewer can see why it changed.

An interruption should cancel stale audio and generation. A late tool response should only apply if its operation and revision still match the current task. Adding “remember interruptions” to the prompt guarantees neither.

For tool timeouts, tell a rejected request apart from one whose outcome is unknown. Check the unknown one before you retry with the same operation key. The architecture guide explains where these checks belong.

Measure the whole call after a rewrite

Count rendered input tokens with the deployed tokenizer, including templates and tool definitions. Run the old and new versions on the same scenarios with the same generation settings. Keep the examples that teach hard behaviour. Mirai’s prompting guide recommends two to four turns of the hardest moment done right, because models copy tone from examples more reliably than from adjectives.

Track task completion, unsupported success claims, invalid tool arguments, repeated questions, turns to recover from a correction, first useful output and total call duration. Separate the effect of prompt layout on caching from changes in instruction quality. Our context guide has observed prefix-layout results, and they don’t tell you how this rewrite performs.

A small regression set you can share

Start with the 12 authored cases. For each run, keep the starting state, the input event, the model’s reply, the tools it requested, the resulting state and a reviewer’s pass or fail with a reason. Repeat runs where the model is stochastic, and keep deterministic state-machine tests separate from language-quality checks.

Report critical failures one by one, with the sample size and how many repeats you ran, so a duplicate-booking failure doesn’t vanish into a good average. Add real failures to the set once identifying details are removed. To feed real call outcomes into this loop, receive them through webhooks with final_results: true, which delivers the transcript in one event.

Common questions

How many tokens should a voice-agent system prompt contain?

There is no universal right size. Mirai accepts up to 12,000 characters, and the prompt is on the latency path, so a long one adds delay well before that limit. Remove contradictions and irrelevant branches first, then measure.

Will a shorter prompt always improve latency?

No. Cache reuse, reply length, queueing and task complexity matter too. A shorter prompt that causes extra clarification turns or wrong tool calls can make the whole call slower.

Should I move every rule into a separate node?

No. Keep shared speaking rules in one stable core, enforce permissions in code, pass reference facts in as needed, and add nodes where the workflow needs explicit steps or recovery.

How do I find out what an agent got wrong on real calls?

Read the transcripts and the agent's logs. GET /v2/agents/{id}/logs lists tool errors, tools the model asked for that the agent doesn't have, the variables each call received and the post-call analysis results.

Sources and API references

References reviewed on . Measurement dates and experimental limits are stated in the article. Check current API and runtime documentation when integrating.

Try the sandbox