variables.
An agent runs either one prompt (system_prompt) or a graph of steps (flow).
See Node-based agents for the graph.
Base URL https://sandbox.voice.miraiminds.co. All endpoints require
Authorization: Bearer sk_live_….
Tools
Addtools to connect your APIs before, during, or after a call. On-call HTTP
tools can run synchronously or in the background, with the result returned to
the voice agent when ready. See Tools for setup, conditions, secrets,
callbacks, and examples.
Knowledge bases
Addknowledge to let the agent answer callers from your website, files, text
and FAQ pairs. It names up to five knowledge bases and how the agent uses them.
See Knowledge bases for sources, modes and limits.
Node-based agents
Addflow to run the conversation as a graph: nodes with their own
instructions, and transitions the model takes when their conditions are met.
With a flow, system_prompt and first_message are optional and unused, and
only pre_call and post_call tools are allowed. See
Node-based agents for the schema and a worked example.
The agent object
Fields
Server-set and read-only:
id, object, created_at, updated_at.
Analysis
analysis reads each finished call once more, after the hangup, so it never
slows the conversation. Turn it on with "enabled": true and describe what you
want in prompt, success_criteria and output_schema. Add templates and
the agent also picks the message template to send next, such as a WhatsApp or
SMS template, and fills in its variables from the conversation. See
Call analysis for every field, the result and two worked
examples.
Calls from
calls_from sets the number the agent’s outbound calls and campaigns ring from when they do not choose one. Send { "pool_id": "pool_…" } for a phone pool, or { "phone_number_id": "phn_…" } for one of your numbers, never both. null unsets it. See phone numbers and pools for the order a call’s number is chosen in.
Voice
voice.language is recorded, not yet appliedThe field is validated, stored and echoed back, and it travels with the call
payload. Today, though, the voice renders in the agent’s top-level language.
If you set both to the same value, you get what you expect. If you set them
differently, the top-level one wins until per-voice rendering ships.voice_id in the
console. See Voices.
One call can use a different voice and languages without changing the agent:
send call_settings on the call, on a campaign
contact, or from a pre-call tool.
Ending a call
The agent gets anend_call tool. When it fires, the agent speaks message and
hangs up.
If you define an explicit
end_call entry in tools, that entry controls whether
the tool is available, including its condition. Its builtin.enabled,
builtin.message, and builtin.confirm settings override the corresponding
agent settings when supplied. See Tools.
Voicemail
Either way the call ends with
status: voicemail and fires a
call.voicemail event. Voicemail detection is
available on every tier. See tiers.
Background sound
An agent speaking out of complete silence is the most obvious sign that nobody is there.background_sound plays room ambience under the voice for the whole
call.
Before you turn it on, note two things:
- The bed is in the call recording too, because it is what the callee heard. If you run your own transcription over recordings, test it first.
- It does not touch what the agent hears. Ambience is mixed into the outbound audio only, so your callers’ speech recognition is unchanged.
Behavior
behavior sets how the agent takes turns with the caller: when it answers, and
what makes it stop talking. In the console it is Agent Studio → Behavior →
Interruptions, with the Adaptive interruptions switch at the top.
Adaptive interruptions
Withadaptive_interruptions on, the default for every agent, the agent uses
Mirai’s turn-taking:
- It knows when the caller has finished speaking, and answers then.
- When the caller pauses in the middle of a thought, it waits and says a short “hmm” so they know it is still listening.
- When the caller asks for a moment (“give me a minute”), it holds until they come back.
- While it speaks, it ignores voices much quieter than the caller’s, such as someone else in the room. Those voices do not stop it, and their words are not passed to the agent.
- If an interruption turns out to be nothing, it picks up the line it was cut off on.
Mirai’s turn-taking is available when the agent uses Mirai’s own LLM. An agent
on another LLM provider follows the fixed rules, even with
adaptive_interruptions on.Fixed rules
Setadaptive_interruptions to false and the agent follows fixed rules. The
interruptions preset sets how much the caller has to say to stop it, and
pass-through words never stop it.
A clear stop word such as “stop” or “ruko” interrupts at every setting except
never.
The preset and the pass-through words still apply while
adaptive_interruptions is on. The console shows them only when the switch is
off, and switching it on there sets interruptions back to normal.
On a node-based agent, a node with allow_interrupt: false
is never interrupted whatever this setting is, and never applies to every node.
Pass-through words
Callers often say a short word while the agent talks, to show they are listening. The built-in acknowledgements, “haan”, “ji”, “ok”, “hmm” and their equivalents, never interrupt at any setting. Add the words your own callers use withpass_through:
- An entry is literal text, never a pattern.
- Unicode is normalised (NFC), spaces at either end are trimmed, and runs of spaces inside collapse to one.
- After that, each entry is 1 to 40 characters and at most 4 words.
- Duplicates are removed ignoring case. The first spelling and the order are kept.
- At most 30 entries remain.
nullis saved as[].
[" Theek ", "theek", "bilkul"] is saved as ["Theek", "bilkul"].
A list outside these limits is refused with 400 invalid_request, and the
message names the field:
A
pass_through that is not an array, or an entry that is not a string, gets
the JSON decoder’s message instead.
A Realtime session started from the agent does not use
pass_through yet.
Change behavior with PATCH
PATCH merges behavior field by field: the fields you send change and the
others keep their values, unlike other nested objects, which are replaced
whole. pass_through is a list, so the list you send replaces the saved one.
To add a word, read the agent, add the word to behavior.pass_through and send
the whole list. Send [] or null to clear the list, or "behavior": null to
go back to the defaults. The change takes effect on the next call and is saved
with each agent revision.
This request moves an agent to the fixed rules, with a firmer preset and three
words of its own:
- cURL
- Python
- Node.js
200 OK (excerpt)
{ "behavior": { "adaptive_interruptions": true, "interruptions": "normal" } }.
The pass-through words stay.
Create an agent
- cURL
- Python
- Node.js
201 Created and the full agent object.
Get an agent
- cURL
- Python
- Node.js
200 OK and the agent object. You get 404 not_found if
the agent was deleted, if the ID does not exist, or if it exists in another
workspace. All three cases return the same response, so a 404 never hints that
the ID is real. None of these cases returns 403; that status only means your
key has been revoked. See errors.
List agents
200 OK
GET /v2/agents/{id} returns, prompts included. There is no trimmed summary
form, so a page of agents with long prompts makes a large response. Page through
with limit instead of pulling everything at once.
Deleted agents are excluded. See pagination.
Update an agent
voice,
end_call, voicemail, background_sound, analysis and tools are replaced wholesale,
so to change end_call.message, send the whole end_call object. behavior
is the one exception: it is merged field by field, though a pass_through
list you send replaces the saved list. See
Change behavior with PATCH. flow is replaced wholesale too: send the whole graph,
or use PUT /v2/agents/{id}/flow.
"flow": null turns a node-based agent back into a single-prompt agent.
- cURL
- Python
- Node.js
200 OK and the updated agent object.
Delete an agent
204 No Content.
The delete is soft: the agent stops appearing in GET /v2/agents and can no
longer be used for new calls, but historical calls keep resolving their
agent_id. Calls already in flight are not affected.
Read an agent’s logs
200 OK
Page with
next_cursor until has_more is false. See
pagination.
A variables row’s detail holds the values the call received, such as a
customer’s name or order number. Treat logs like the call data they come from,
and keep your API key on your server.
Rows about variables and results start from calls made on 14 October 2026.
Rows about tools the model asked for but the agent doesn’t have start from
15 October 2026.
Count errors and warnings
since it counts the last
24 hours. These are the counts on Agent Studio’s section labels.
200 OK
Writing a good prompt
A single-prompt agent does one job, start to finish, usually in under two or three minutes. The prompting guide covers this in detail. In short:- Name the job in the first line. “Confirm order
{{order_id}}. Nothing else.” - Cap reply length explicitly. “One or two short sentences.” Long turns are the single biggest driver of perceived latency.
- State the ending condition. “When the customer confirms or refuses, thank
them and call
end_call.” Without this the model keeps talking. - Put per-call data in
variables, not the prompt. One agent can then run thousands of calls without being re-created. - Write in the language you will speak. A Hindi call driven by an English prompt code-switches badly. Write the Hindi lines in Devanagari.