Tools
Seven MCP tools connect your agents and you through AgentCall. Use them for decisions, approvals, progress updates and the other calls your rules ask an agent to make. Agents can also check for a call you requested.
On this page
At a glance
The server lives at /api/mcp. Every tool is scoped to the account that authorized the connection; your agent can request calls only on that account’s devices.
- Agent → human
request_human requests a ring; converse speaks and listens; say gives an update; end_call finishes the call.
- Human → agent
check_in checks for a callback request; stand_by waits for one.
- Missed calls
leave_voicemail saves a message after an eligible attempt, when you have enabled it.
Blocking tools wait for one ring, reply or callback request. “No reply wait” means the tool does not wait for a human response; it still needs time to process. See timing and limits.
Results below are illustrative alternatives, with one JSON object per line. Conversation text, IDs and dates are examples; some contextual note fields are omitted. A saved message or reported delivery does not prove that you heard it.
Agent → human
request_human
Waits for an answerRequest a ring on enrolled devices and wait for an answer, a decline or the ring timeout.
- Arguments
reasonRequired · string · ≤ 500 characters- The reason for the call: an update, a decision or another purpose you defined. Shown in the app, never in the lock-screen notification.
openingOptional · string · ≤ 600 characters- Strongly recommended. The complete first spoken turn: introduce the agent, project and purpose, then include the question or update the human should respond to. Speech can be prepared while the call rings. After connection, listen with an empty
conversemessage rather than immediately speaking again. urgencyOptional- One of
low,normalorhigh. Urgency does not bypass your quiet hours or Do not disturb. projectOptional · string · ≤ 128 characters- Strongly recommended. Name the work or project so you can identify the agent in History and route callbacks to it.
idempotency_keyOptional · string · ≤ 80 characters- Reuse a key to guard against a repeated ring within the ten-minute window. A
busyattempt releases the key so it can be retried.
- Returns
request_human — possible results {"status":"connected","call_id":"1789300000000","opening_queued":true,"next":"Your opening is already queued for playback. Call converse with message: \"\" and this call_id to listen for the human’s reply. Do not repeat the opening or send another message before listening; queued does not mean heard. The one exception is an opening that was only an introduction — if it did not contain the question or update the human should answer, send that now in one short message, without repeating the introduction."} {"status":"no_answer","delivered":1,"timedOut":true} {"status":"no_answer","delivered":0,"declined":true} {"status":"no_answer","delivered":-1,"timedOut":true,"voicemail":"enabled — call leave_voicemail with a short spoken-style message summarizing what you needed and what you'll do"} {"status":"busy"} {"status":"duplicate","note":"this idempotency_key was already used — the call was already placed"} {"status":"silenced","reason":"quiet_hours","until":"2026-09-14T08:00:00.000Z","voicemail":true} {"status":"silenced","reason":"dnd","voicemail":false} {"status":"rate_limited"}connected: follownext(the same fieldcheck_inandstand_byanswer with). Whenopening_queuedis true, the opening is already in the call transcript for playback; callconversewithmessage: ""to listen. This does not prove playback or hearing. An opening that was only an introduction is the one exception: its question or update still has to be sent once. The result normally includescall_idwhen the call’s start timestamp is available.no_answer: inspectdelivered,timedOut,declinedand anynote. A decline is an explicit refusal; do not repeat the same request.deliveredreports push delivery:-1is unknown,0means none delivered, and a positive number is the reported count. An open app can receive a ring without push. Zero alone does not diagnose missing enrollment.busy: another call occupies the line; wait before retrying.duplicatemeans the key was already claimed.rate_limitedmeans this request did not ring. These results do not create a missed-call voicemail opportunity.silenced: calling availability prevented the ring.reasonidentifies quiet hours or Do not disturb;untilcan identify the quiet-hours end. An explicitly requested callback has its own one-use invitation; this is not an agent override.
Opening, then listen — tool call arguments {"name":"request_human","arguments":{"project":"research","reason":"Review the findings","opening":"This is your research assistant. The review is complete. Which finding should we discuss first?"}} {"name":"converse","arguments":{"message":"","call_id":"1789300000000"}}For
no_answer, the enabled-voicemail hint is a string. Forsilenced,voicemailis a boolean. Follow the returned invitation and the voicemail requirements.- When to use
- Follow your human’s rules: a research update, completed checks, a decision, a preference or an approval. Speak concisely. If no opening was supplied, introduce the agent, project and purpose in the first
conversemessage. When an opening is confirmed queued, wait for the human with an emptyconversemessage. An explicit nonemptyconverseorsaystill queues its words when another spoken message is intentional. - Named calls
- Pass
call_idtoconverse,sayandend_call. A confirmed mismatch returnsnot_your_callwithout saying or ending anything. This optional check uses a session snapshot; if the snapshot cannot be read, the server falls back to legacy behavior. It is not an atomic ownership guarantee.
converse
Waits for one replySpeak a message and receive the human’s reply as a transcript. An empty message listens without speaking.
- Arguments
messageRequired · string · ≤ 2,000 characters- What to say aloud. Use an empty string to listen only.
call_idOptional · string · ≤ 32 characters- Pass the ID returned by request_human. See the named-call check below that tool.
- Returns
converse — reply and ended-call results {"transcript":"Use option B, and keep the change reversible.","interrupted":true} {"transcript":"Send me the research summary.","interrupted":false,"ended":true} {"event":"silence"} {"event":"call_ended"} {"event":"call_ended","reason":"client_gone"} {"error":"not_your_call","note":"That call is over — the id you named is not the call that is live now. Nothing was said or ended. If you still need your human, call request_human for a new call."}transcriptis one merged turn. Words received while the agent was thinking are prepended, and a short adaptive quiet window closes the turn.interrupted: truemeans you cut the agent’s message off. It should respond to your words instead of resuming its script. The returned transcript contains your words. History can retain the full agent message and mark an estimated interruption point.- A transcript with
ended: truekeeps your last words alongside the fact that the line is down. Use those words and continue the work; do not discard them or keep asking questions through the ended call. silence: re-prompt once or end the call. A barecall_endedcarries no new words. Already-spoken late or buffered words can still be returned, so later results are not guaranteed to be identical.reason: "client_gone"means the phone’s connection dropped. It does not mean you chose to hang up; the question may still be open.
- Conversation
The pickup hello. If the first reply is only “Hi” or “Hello,” you may have spoken while picking up, before hearing the question. The agent should ask it again.
Put farewells in
end_call. A goodbye sent throughconversewaits for another reply and leaves the call open.
say
No reply waitGive a short, useful progress update during a call without asking for an answer.
- Arguments
messageRequired · string · ≤ 600 characters- The update, written to be spoken aloud.
call_idOptional · string · ≤ 32 characters- Pass the ID returned by request_human. See the named-call check below that tool.
- Returns
say — accepted and unspoken results {"ok":true,"spoken":true} {"ok":true,"spoken":false,"note":"no call was live, so nothing was spoken — your human did not hear this. Call request_human if you still need them."} {"error":"not_your_call","note":"That call is over — the id you named is not the call that is live now. Nothing was said or ended. If you still need your human, call request_human for a new call."}spoken: truemeans the store accepted the message for an eligible ringing or live call. It is not a device playback acknowledgement.spoken: falsemeans the words were not spoken through an eligible call; do not assume you heard them.- When to use
- Before work that takes more than about twenty seconds: “I’ll compare those sources and bring you the differences.” Keep updates useful, without filler. Progress lines appear muted in the transcript.
end_call
No reply waitEnd the call with an optional closing message, then return to the work.
- Arguments
closing_messageOptional · string · ≤ 600 characters- A concise farewell, accepted for speech when the call is live.
call_idOptional · string · ≤ 32 characters- Pass the ID returned by request_human. See the named-call check below that tool.
- Returns
end_call — closing-message results {"ok":true} {"ok":true,"spoken":true} {"ok":true,"spoken":false,"note":"the call was already over, so your closing message was not spoken. The call is ended either way."} {"error":"not_your_call","note":"That call is over — the id you named is not the call that is live now. Nothing was said or ended. If you still need your human, call request_human for a new call."}Without a nonempty closing message, the result is
{"ok":true}. With one,spokenreports whether it was accepted while the call was live. A ringing or already-ended call cannot speak the farewell. Neither successful shape proves you heard it.- When to use
- End promptly when the conversation concludes or you ask the agent to hang up. Put the goodbye here instead of in
converse. If the agent has no other work and should stay reachable, it can call stand_by afterwards.
Human → agent
The server can speak to an agent only when the agent calls a tool. It cannot interrupt the agent’s work. These tools collect requests you made in the app; see Callbacks for the full flow.
check_in
No reply waitCheck whether your human has requested a call, and collect an eligible request.
- Arguments
projectOptional · string · ≤ 128 characters- Strongly recommended. Name the work or project so you can identify the agent in History and route callbacks to it.
- Returns
check_in — callback results {"pending":"none"} {"pending":"call_requested","message":"Your human says: \"Include the latest findings\"","next":"call request_human now"}On
call_requested, callrequest_humanand address the attached note.messageappears only when the human included a note.- When to use
- Check at natural task boundaries and before a long operation, following your human’s instructions. When work is finished, use
stand_byif you should remain reachable. - Targeting
check_inandstand_byconsume a request for the exact agent type and project, or an “any agent” request. They do not consume one addressed to another agent.
stand_by
Waits for a requestWait up to four minutes for a callback request, then return control to the agent.
- Arguments
projectOptional · string · ≤ 128 characters- Strongly recommended. Name the work or project so you can identify the agent in History and route callbacks to it.
- Returns
stand_by — callback or timeout results {"pending":"call_requested","message":"Your human says: \"Include the latest findings\"","next":"call request_human now"} {"pending":"none","next":"call stand_by again to remain reachable"}- When to use
- When you step away or want an agent to stay reachable after its work. The agent must issue another
stand_bycall to keep waiting; the server does not restart it automatically. - What happens
- The server checks about every two seconds. After collecting a request, the agent must call
request_human, and the device must receive and answer that call. Supplyingprojectkeeps project-specific presence fresh while waiting. Omitting it does not establish that presence on the Agents page.
request_human results and eligible converse, say and end_call results can also carry pending: "call_requested". These paths only peek; check_in and stand_by collect the request. Early errors and voicemail results do not universally include this field.Missed calls
leave_voicemail
No reply waitSave one spoken-style message after an eligible missed or silenced call, when voicemail is enabled.
- Arguments
messageRequired · string · ≤ 1,500 characters- Who the agent is, which project, what it wanted to share and what it will do meanwhile.
projectOptional · string · ≤ 128 characters- Strongly recommended. Name the work or project so you can identify the agent in History and route callbacks to it.
- Returns
leave_voicemail — saved and refused results {"ok":true,"delivered":2,"note":"voicemail saved — a notification was accepted for delivery"} {"ok":true,"delivered":0,"note":"voicemail saved in History — no device could be notified"} {"ok":true,"delivered":-1,"note":"voicemail saved in History — we could not tell whether any device was notified"} {"ok":false,"error":"voicemail_disabled — your human has not enabled voicemail"} {"ok":false,"error":"rate_limited — wait a minute"} {"ok":false,"error":"no_missed_call — leave_voicemail only follows an unanswered request_human by this agent (within 15 minutes)"} {"ok":false,"error":"voicemail_not_saved — history is unavailable right now"} {"ok":false,"error":"voicemail_already_left — one voicemail per missed call"} {"ok":false,"error":"empty_message — a voicemail needs something the human can hear"}ok: truemeans the message was saved in History.deliveredis how many of your devices the push service accepted a notification for —0means none,-1means the device lookup itself failed and we cannot say. None of those numbers prove the message was read: a saved message, an accepted notification, and listening to the message are separate events, so read the note.- When to use
- Only after an eligible unanswered or declined ring, or a
silencedresult that explicitly offers voicemail. It must come from the same agent and project within the configured 15-minute window, with at most one message per eligible attempt. Voicemail must remain enabled. - In the app
- The text is stored in History. Speech is synthesized when you press Play; voicemail audio is not stored. When delivered, the “New voicemail” notification opens the transcript, where you can request a callback. Busy, duplicate and rate-limited requests do not independently entitle an agent to leave a message.
Turn semantics and timeouts
Each blocking tool waits for a single ring, reply or callback request, rather than the entire conversation. Windows below describe the current defaults or configured values; server work and connectivity affect when an outcome is observed.
- Ring
- Up to 180 seconds.
request_humancan returnno_answeron timeout or decline. Ring notifications use the same expiry window. - Reply silence
- About 60 seconds. Human speech or agent audio can hold the silence timer off, within the invocation’s work budget.
- Turn settling
- 2 seconds when a reply reads complete; 6.5 seconds when unfinished; capped at 20 seconds.
- Phone gap
- 45 seconds without phone contact can end the call as
client_gone. Lifecycle checks detect the gap; it is not a precise real-time alarm or proof of a deliberate hang-up. - Agent gap
- 300 seconds while working, or 45 seconds while blocked waiting for a reply. Blocked waits refresh their heartbeat in slices of at most five seconds and during turn settling.
- Stand-by
- Up to 240 seconds per invocation, checking every two seconds. The agent calls again to continue waiting.
- MCP progress
- Every ten seconds while blocked, only when the client supplies
_meta.progressToken. Whether progress extends the client’s timeout depends on the client. - Tool timeout
- Keep fixed client timeouts at least 300 seconds; the existing Codex configuration is
tool_timeout_sec = 300. The function limit is 300 seconds; Redis-backedconversebudgets at most 270 seconds for its work. - Busy line
- One live call per account. A ring holds the line for its window, with an internal claim buffer. An answered call occupies it while either side was heard from within 90 seconds; abandoned claims can be reclaimed. This is separate from disconnection grace.
- Rate budget
- Ten ring or voicemail attempts per minute per account, sharing one budget. This is not a promise of ten displayed rings.
- Expiry
- Idempotency keys: ten minutes, released on busy. Pending callbacks: thirty minutes. Voicemail eligibility: 15 minutes.
What the agent sees at connect
The server publishes instructions and adds your standing call rules to the request_human and check_in descriptions. Rules are quoted as preference text, with carriage returns and tabs normalized to spaces. This reference explains the tools; it is not a verbatim copy of every description.
Here is an illustrative instruction block with two example rules. Saved rules tell an active agent when to call, including routine updates; saving an hourly rule does not create a recurring-call scheduler inside AgentCall.
AgentCall connects you to your human by real phone call. Call request_human
when a decision, approval, or notification warrants their attention; call
check_in at natural task boundaries to learn whether your human wants a
call; call stand_by (blocking, re-callable) to stay reachable in REAL TIME
when your human steps away or your work is done.
An opening is your complete first spoken turn, including its question or
update. When connected with opening_queued: true, use converse with
message: "" and the returned call_id to listen. Do not immediately queue
another introduction. Queued audio is not proof the human heard it.
Without an opening, introduce yourself and ask in the first converse.
YOUR HUMAN'S STANDING CALL RULES (quoted verbatim from their settings —
follow them; they define when to call, beyond your own judgment):
> Call me when a task is finished and ask what's next.
> Always call before touching production.