paigy
OfficialPaigy is an MCP server that bridges AI agents and users via phone (call, push, banner, or silent inbox), enabling real-time two-way communication during long-running or blocking tasks.
Pair/Unpair (
pair,unpair): Link an agent to a user's Paigy account via a device-code OAuth flow, or revoke access.Notify users (
notify_user): Send notifications at four urgency levels:inbox— silent, sits in the inboxpush— quiet passive notificationbanner— time-sensitive lock-screen banner with soundcall— rings the phone as a real voice call (CallKit)
Structured answer shapes: Request replies in the most efficient format — Yes/No confirm, Approve/Deny, pick one, pick many, rank/order, or free text; supports visual previews (HTML mockups or image URLs).
Poll or await replies (
poll_answer,await_reply): Check a notification's status or block and wait (up to ~5 min) for the user's reply, scoped to that specific notification so concurrent requests never cross-contaminate.Catch-up on missed activity (
check_replies): On session start or after long waits, discover unseen replies, pending notifications, user-initiated requests, and due callbacks.Report task progress (
set_task_state): Update task status toin_progress,completed, orneeds_input.Schedule callbacks (
schedule_callback): Promise a follow-up triggered when a task finishes (on_done), hits a blocker (on_blocked), or after a set time (scheduled).Configure delivery mode (
register_delivery): Switch between polling (default) and self-hosted realtime push via apaigy listendaemon.Threaded conversations: Pass a
threadIdacrossnotify_usercalls to keep related exchanges in the same conversation thread.
Pairs with the native Paigy iOS app to receive calls (via CallKit), banner notifications, and reply from the lock screen, integrating the user's iPhone as an interface for agent notifications.
Allows local AI models running via Ollama to use Paigy for notifying users and awaiting replies through phone calls, banners, or push notifications.
Paigy — MCP server
A voice inbox for your AI agents. When an agent needs your input — mid-task, blocked, or done with something long-running — it can place an actual phone call and read the question aloud, text, push, or ring your phone with a banner, so you can reply by voice instead of babysitting a terminal.
Without Paigy, a long agent session means one of two bad options: sit and watch the terminal so you don't miss the moment it needs you, or walk away and come back to a task that stalled an hour ago waiting on a question you never saw. Paigy closes that gap — the moment your agent actually needs a decision, your phone gets pulled into the loop with the level of urgency that matches the moment (a silent inbox card, a quiet push, a banner, or a real ringing call), so you find out immediately instead of on your next check-in. Answer by voice or text and the reply lands back with the agent exactly like any other tool response, so it just continues — no copy-pasting, no reopening the terminal. It also pairs with the native Paigy iOS app, so a call rings through like a real phone call (CallKit) even when your phone is locked, and you can glance at or reply to anything from the lock screen.
Works with
A standard MCP server (stdio, TypeScript) — no client-specific code anywhere, verified over the raw protocol against a non-Claude client identity.
Claude Code (this repo is also the plugin + marketplace for it)
Codex CLI
Gemini CLI
Any other MCP client via standard config: Cline, Continue.dev, Zed, Cursor, Goose, mcphost — including local-model setups over Ollama, LM Studio, or llama.cpp
(The app + backend live in a separate repo.)
Related MCP server: WhatsApp MCP
Install
One line, any terminal — detects your agents (Claude Code, Codex,
Antigravity), wires Paigy into each, and pairs your phone once. Prints every
command before running it; --dry-run shows the plan:
curl -fsSL https://paigy.ai/install | shPrefer to do it by hand? Pick your client below.
Claude Code (plugin — easiest path on Claude):
/plugin marketplace add paigy-ai/mcp
/plugin install paigyConnects automatically; the first time an agent uses it while unpaired, it'll
prompt you to pair — run /paigy-onboard (opens your browser to approve).
Claude Desktop (MCPB bundle — no terminal needed):
download paigy.mcpb,
then in Claude Desktop open Settings → Extensions and drag the file in (or
double-click it). Ask Claude to "pair with Paigy" — it runs pairing itself and
shows a code to approve on your phone. Also on
Smithery.
Codex CLI:
codex plugin marketplace add paigy-ai/mcp --ref main
codex plugin add paigy@paigy-ai
npx -y -p @paigy/mcp@latest paigy-mcp-onboardThe plugin configures the Paigy MCP server and includes guidance for calls, replies, and callbacks. Start a new Codex session after installation.
Codex CLI — direct MCP fallback:
codex mcp add paigy -- npx -y @paigy/mcp@latestThen forward Codex's thread id into the server, so each Codex conversation gets its own
Paigy identity — Codex builds the MCP server's environment from a fixed allow-list, so a
variable it isn't told to pass never reaches us. Add this line under [mcp_servers.paigy]
in ~/.codex/config.toml (paigy-harness setup does it for you):
env_vars = ["CODEX_THREAD_ID", "CODEX_SESSION_ID"](Don't pass it as a -c override on mcp add — that lands before the block is written
and Codex rejects the half-table with "invalid transport", writing nothing.)
Gemini CLI:
gemini mcp add -s user paigy npx -y @paigy/mcp@latestAny other MCP client (Cline, Continue.dev, Zed, Cursor, or a CLI that
takes the standard MCP JSON config directly) — most GUI clients take this in
their MCP settings (Cline: cline_mcp_settings.json; Continue:
~/.continue/config.json):
{
"mcpServers": {
"paigy": {
"command": "npx",
"args": ["-y", "@paigy/mcp@latest"]
}
}
}Then pair your phone:
npx -y -p @paigy/mcp@latest paigy-mcp-onboardEach session hatches its own identity automatically the first time it reaches Paigy —
no agent name to set or match. (Set PAIGY_AGENT=<name> only if you deliberately want a
client to always speak as one fixed named identity; then run onboard with the same name.)
Approve on your phone, then sign in at paigy.ai to start
receiving messages.
Heads-up for smaller/local models: the tool descriptions ask the agent to pick between a few answer shapes (confirm, options, free text) based on context — Claude follows this reliably; smaller local models may be less consistent about it. Free text always works as a fallback.
Choosing how the user answers
notify_user should ask in the shape that's fastest to answer — don't leave a
decision as free text. Pick with select (and options):
You need… | Use | Answer comes back as |
Yes/No or Approve/Deny |
|
|
Pick one of several |
|
|
Pick several |
|
|
Rank / order a subset |
|
|
A visual choice | options with an | one of the above |
An open-ended reply | no options |
|
confirm is answerable straight from the banner (Yes/No or Approve/Deny
buttons). Other paiges get banner actions See Options · Hear them · Remind me
later.
urgency is a request, not a guarantee — the user's account settings can
cap it lower. Four levels, low to high: "inbox" (silent, sits in the inbox),
"push" (a quiet passive notification, no sound), "banner" (a
time-sensitive lock-screen banner with sound), "call" (rings the phone —
use only when you genuinely need the user in the moment).
If you're about to start something long-running or blocking — the kind of thing where the user would otherwise sit and wait on you — mention once, in passing, that you can text or call them when it's done or if you hit a blocker. Don't offer it for quick tasks, and don't repeat the offer once they've answered.
Idle escalation (automatic, no setup)
Installing this plugin also wires up Claude Code hooks (hooks/hooks.json,
via ${CLAUDE_PLUGIN_ROOT} — no manual settings.json editing) that back
notify_user up with a mechanical safety net, independent of the agent
session — it still fires even if that session crashed or forgot:
10-minute check (
escalate.sh): how much is actually pending (GET /api/pending/summary, a non-claiming read) — a single fresh item gets abanner, several or a stale one gets a realcall(routed through the same call-coalescing the bot uses, so several ringing things fold into one call instead of ringing separately).2-minute check (
quick-check.sh): a narrower, faster check for a different case — you already replied to something (via the app), but no agent has engaged with it yet. That's not "nothing happened" (escalate.sh's job), it's "the agent hasn't looked." It spawns a fresh headlessclaude -p(deliberately NOT resuming your live session — no injected turns in a transcript you might be typing in) scoped to just the tools it needs; that agent acknowledges the missed reply with a natural message in the same thread ("sorry I missed this — starting on it now"), so what you see is a normal agent response, not a system nudge. Only if that's unavailable or fails does it fall back to a plain nudge telling you to reopen the session yourself.
Hooks are the dead-session safety net. A live-but-idle agent shouldn't
need them: the MCP server instructions tell every paired agent to schedule
its own ~2-minute wake-up (harness ScheduleWakeup or equivalent) and
check_replies whenever it ends a turn with anything possibly pending —
self-polling in its own session, full context intact.
Nothing pending/unacknowledged — including a normal "just finished" stop — means neither check does anything.
License
MIT
Available Tools
12 toolsanswer_caller_questionA
Answer a question the user asked DURING a live call, while they're still on it. When a partial turn or a settled reply carries a question intent aimed at you, answer it here immediately: if their call is still live, your answer is spoken to them on that same call (returns live: true). If the call already ended (live: false), send the answer as a threaded contact instead — never drop it. Short spoken sentences only; this may be read aloud.
| Name | Required | Description | Default |
|---|---|---|---|
| answer | Yes | The answer, as one or two short SPOKEN sentences — it may be read aloud on the live call. | |
| notificationId | Yes | The notification whose call carried the caller's question — from the partial turn or the settled reply. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description bears the full burden of disclosing behavioral traits. It does well by explaining the dual behavior (live call vs. ended call), the requirement for short spoken sentences, and that the answer is read aloud potentially on a live call. However, it does not mention any authentication needs, rate limits, or potential side effects (e.g., what happens if the notificationId is invalid or the call state is ambiguous), which would push it to a 5. It also lacks details on expected output format, though no output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded, with the first sentence immediately stating the core purpose and context. Every sentence provides essential information: when to use, behavior based on call state, and output format constraints. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (2 params, no output schema, no annotations), the description is complete. It covers purpose, usage guidelines, behavioral nuances, parameter semantics, and output characteristics. The context signals indicate no other complex requirements like enums or nested objects, so the description adequately addresses all essential aspects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters. The description adds value by explaining the purpose context for 'answer' (short spoken sentences, may be read aloud) and linking 'notificationId' to the call that carried the caller's question, derived from a partial turn or settled reply. This goes beyond the schema's basic descriptions, but does not add constraints like allowable length in seconds or any validation rules, leaving a small gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool answers a question asked by a user during a live call. It specifies the verb 'answer' and the resource 'caller_question', and distinguishes it from siblings like 'await_reply' or 'handoff' by emphasizing the live-call context and the dual output mechanism.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use the tool: when a partial turn or settled reply carries a 'question' intent aimed at the agent during a live call. It also clarifies two distinct scenarios—if the call is still live (answer spoken on the call) versus if it ended (send as threaded contact), and warns against dropping the answer. This provides clear context and exclusions, such as not for non-question intents.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
await_replyA
Wait for the user's reply to a specific notification you sent (pass the notificationId from contact). This is how you wait for your answer in-context. Polls ~45s per call — deliberately under the 60s cap most hosts put on a single tool call, so it ALWAYS returns you something (raise it with maxWaitSeconds only if you know your host allows longer). Returns { type:'reply', answer } when they respond, { type:'remind', remindInSeconds } on snooze (ScheduleWakeup then await_reply again), or { type:'idle' } (this window ended, no answer yet). While your contact is being handled on a LIVE call, you may receive { type:'partial', inFlight:true, turn } results: what the user said to each turn, as they say it. Use partials to PREPARE — fetch the data, draft the thing, warm the build — never to act irreversibly: the user can still revise any of them until the final reply arrives. Partial = intelligence, settled = authorization. If a partial's acts carry a question aimed at you and you know the answer, call contact on the SAME parentId right away — the caller hears your answer on the same call instead of waiting for a callback. Keep calling await_reply until you get the final reply — THAT one is the decision. On idle, if this is genuinely still blocking you and you have nothing else useful to do meanwhile, just call await_reply again immediately — keep looping. This is how you actually deliver on the point of calling: the user steps away for a while and comes back to find you'd already continued the moment they answered, not idle waiting to be checked on. Don't give up after one window. Only stop looping to do other work (and check back later), or after an unreasonably long stretch (tens of minutes to hours) worth telling the user about instead. Scoped to that one notification — it NEVER returns replies meant for other notifications, so concurrent contact calls don't cross. A CALL answer can come back as {kind:'turns', turns:[{prompt,reply}]} — the ordered log of that call. Read turns[0].reply as the user's main instruction. Usually that's the only turn; if there are more (e.g. an end-of-call 'call me back when it's done / I have a blocking question'), read each one in order as a further follow-up instruction, not a single combined one. If they asked for a callback, re-engage in the SAME thread (contact with the reply's parentId) when the task is done or you hit a blocker — waiting:'hard' for a blocker, waiting:'none' for done. Paigy has no scheduler; the callback is yours to send (use ScheduleWakeup/cron for timing). A call-mapped answer may carry intents — next steps the user attached, each { kind, detail } with detail quoting their words. ACT on them, don't just read them: 'defer' ("call me after lunch") → register it NOW with schedule_callback — when the intent carries dueInSeconds (Paigy pre-parsed the spoken time against the user's clock) pass it straight through; otherwise derive it from the detail yourself — then follow up on the same thread; 'delegate' ("you pick") → make the call yourself and tell them what you chose; 'channel' ("text me next time") → honor it on your next contact (channel:'message'); 'question' (an open question aimed back at you that the call couldn't answer) → you OWE them the answer — work it out and follow up on the same thread without being asked, the call deliberately skipped "should I call you back?" because the follow-up is implied. transcript is the user's raw words behind a shaped answer — read it for hedges and conditions ("yes, IF tests pass") before acting. If your ask declared points, the reply carries covered — the points actually addressed. Compare against what you declared: a missing point is STILL unanswered — re-ask it (contact on the same parentId) or proceed knowingly partial; never treat a partial answer as complete.
| Name | Required | Description | Default |
|---|---|---|---|
| maxWaitSeconds | No | How long to hold this ONE call before returning { type:'idle' } so you can loop. Default 45 — safely under the 60s cap most MCP hosts put on a single tool call. Raise it only if you know your host allows longer; a value past the cap means the call is killed and you get nothing. | |
| notificationId | Yes | The notificationId returned by contact — waits for the user's reply to THIS notification only. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and delivers thoroughly. It explains the polling mechanism (45s default, under 60s cap), all possible return types (reply, remind, idle, partial, call answer), their meanings, and how to respond. It also covers scoping, concurrency behavior, Paigy's lack of scheduler, and nuances like intents and points. No behavioral aspect is left unclear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely long and lacks structural elements like bullet points or sections. While every sentence adds necessary detail, the sheer volume makes it harder to parse quickly. It is front-loaded with the core purpose but then expands into a dense block of text. A more structured format would improve readability without sacrificing completeness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (polling, multiple return types, partials, call handling, intents, points, concurrency) and the absence of an output schema, the description is remarkably complete. It covers all scenarios, edge cases (idle, partial, call answers), and actionable instructions for each. An agent can understand the full lifecycle of using this tool without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds significant value beyond the schema. It explains the default of maxWaitSeconds (45s) and why it's set that way, warns about host caps, and clarifies that notificationId comes from the contact tool. This context helps the agent use parameters correctly without guessing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Wait for the user's reply to a specific notification you sent.' It uses a specific verb ('wait for') and resource ('reply to a notification'), and distinguishes itself from the sibling tool 'contact' (which initiates the notification). This is precise and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description offers extensive guidance on when to use this tool: after sending a notification, how to loop on idle, when to use schedule_callback or contact for follow-ups, and how to handle partials. It explicitly tells when not to treat partials as final and advises against giving up after one window. Alternatives like schedule_callback and contact are mentioned with specific contexts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_repliesA
The catch-up sweep for everything outstanding — a PURE read, takes no arguments, safe to call as often as you like: nothing here is consumed by reading it. Returns replies (answers to notifications you sent), your still-pending notifications, and requests — requests the user started toward you (each { notificationId, parentId, text }). Each keeps reappearing on every call until you actually engage with it: call set_task_state on its notificationId, which is what claims/acknowledges it — a human-initiated reply or request must never be silently dropped just because you read the list without acting. Also returns threads — the SAME replies + requests grouped by conversation, oldest thread first, each with a busy flag and its items in arrival order. WORK ONE THREAD AT A TIME: take the oldest thread whose busy is false, handle ALL of its items together in a single turn (one set_task_state), then go to the next — don't interleave threads item-by-item. A busy thread already has a turn in progress; leave it and let its new items ride the next turn. Use check_replies when booting up / starting a session, or when you've been waiting a long time on something else. To wait on an answer to a contact call you just made, use await_reply instead. Also returns owedCallbacks: callbacks now due that you promised — fulfill each with contact on its parentId. EVERY Paigy reply — this one, await_reply's, and contact's — may carry also: work assigned to you that no wake could reach, handed to you because you happened to be here. It is NOT what you asked about and it is never urgent: FINISH what you came for first, then take it up. Each entry has a noteId and the owner's own words; report on its parentId thread when it has one, and call set_task_state on that thread as you would for any assigned work. Ignoring it costs nothing — it rides your next reply too. Also returns stalled: work (either direction) you reported in_progress via set_task_state a while ago and never reported completed — likely left half-done by this session or a prior one that crashed or went idle. For each, either continue the work and report a real state, or investigate why it stalled. Also returns you — WHICH IDENTITY you are speaking as ({ name, device, tokenId }), the same name and device the user sees on their Agents screen. This is the only safe way to find out (calling pair can MINT a new identity instead of telling you about the current one). Use it when the user asks who you are, and to tell whether work addressed to a name is addressed to you. A request may also carry stranded: it was addressed to ANOTHER agent on this account (that name) which has not been seen since it landed, so nobody came for it and it is handed to you because you are the session that is here. Take it exactly like your own — set_task_state claims it, reply with contact on its parentId — and say whose it was, because the user picked that agent on purpose. Replies may carry intents/transcript/covered (call-mapped answers) — handle intents exactly as await_reply's description says (defer → schedule_callback now; delegate → decide and say so; channel → honor next contact), and treat a covered list missing one of your declared points as that part still unanswered.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it does so thoroughly: it declares the call is a PURE read, takes no arguments, is safe to call often, and that nothing is consumed by reading. It also discloses important non-obvious behavior: entries reappear until acknowledged, set_task_state claims them, and identity discovery via pair can mint a new identity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the most important facts and contains dense, useful operational detail, but it is an extremely long single paragraph with many parenthetical asides, capitalized emphases, and nested clauses. Every sentence adds value, but the lack of structure makes it harder to scan and parse than an ideally organized description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must explain the return contract, and it does: it enumerates every returned category, explains how to handle each (threads, owedCallbacks, also, stalled, you, stranded, intents/transcript/covered), and ties processing back to set_task_state and contact. This is more than enough for an agent to invoke and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema already documents that with 100% coverage. The description explicitly reinforces this by saying 'takes no arguments,' so no additional parameter semantics are needed. The baseline of 4 for zero-parameter tools is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear and specific purpose: 'catch-up sweep for everything outstanding' and then enumerates the distinct return groups (replies, pending notifications, requests, threads, owedCallbacks, stalled, you). It also differentiates itself from siblings by explicitly routing await-reply use to await_reply and identifying set_task_state as the claiming mechanism.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use instructions: 'Use check_replies when booting up / starting a session, or when you've been waiting a long time on something else,' and explicitly says to use await_reply instead when waiting on a specific contact call. It also provides detailed operational rules like working one thread at a time and leaving busy threads alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contactA
Reach the user through Paigy — tell them something, or ask and get their answer. State what you need in ask, say what happens to your work while you wait in waiting, and Paigy handles the rest (channel, phrasing, answer format). If the user explicitly asks you to CALL them, send waiting:'hard' and say so in the ask. Returns { notificationId, parentId } — pass notificationId to await_reply for the answer, parentId to a later contact to continue the conversation. When it rang, the reply also carries { ifMissed: { mode, means } }: what the user's own policy does with a call they don't take ("Rings again 10 min, 30 min and 2 hr after the missed call, then leaves it in your inbox"), so a no-answer tells you how long to wait before coming back. THREADING REPLACES: a threaded follow-up SUPERSEDES your earlier pending items on that thread — right for updates to one ask, WRONG for a checklist (send independent to-dos un-threaded). A threaded re-send with IDENTICAL content escalates the pending ask in place. If a reply comes back as {kind:'clarify', chunks:[...]}, the user wants more detail — contact again on the SAME parentId with an expanded ask. ONE ASK, ONE ROW: never restate a still-pending ask's question inside a NEW contact (e.g. weaving it into a briefing) — the whole answer settles on the new row and the original can never receive it. Keep waiting on the original (a live call reads every pending ask out separately, each answer routes to its own row), and use needs for a genuinely multi-part NEW ask. ANSWERABLE, NOT JUST ASKED: when the reply comes back carrying plan.units[].needs, that unit asked for something it gave the user no way to answer — 'options' means it posed a choice with nothing to choose from, 'visuals' means it asked about something to look at with nothing to look at. Send it again on the SAME parentId with 2-4 options (or the image), drawn from your own sentence. Paigy will not add them for you: a shape it guessed wrong cannot be undone, and you are the one who knows what the real alternatives are. units reports WHAT BECAME OF YOUR PROSE — { kept, raw, why }: how many topics Paigy compressed for delivery, how many kept your exact words, and the reason when it kept them (e.g. 'no_output' = compression produced nothing usable, so the user got your raw sentence). It needs no action and is not an error — read it only when the delivered wording matters to you; a high raw count means the user is hearing you verbatim.
| Name | Required | Description | Default |
|---|---|---|---|
| ask | Yes | What to tell the user, or what you need to find out from them. Plain prose — as long as it needs to be (up to 10k characters); Paigy splits it into topics and reads back a few sentences at a time, so do NOT compress a briefing into one line. May be spoken aloud on a call, so write natural speech and name things (not IDs). Contact at exactly two moments: BLOCKED on a decision only they can make, or DONE (one short report — what shipped, how you verified it, what you flagged). DONE IS SAID ONCE: "all set", "nothing open on my end", "that thread is complete" are the same report in new words, and each one reaches them separately (live 2026-08-12: three of them in three minutes). After the first, you are finished speaking; if they acknowledge it, stop rather than confirming the acknowledgement. Progress is never a contact: set_task_state carries it, and working narration stays in your own terminal — the user sees you're working without being interrupted by it. | |
| channel | No | Only if the user explicitly said how to reach them — 'call me' → 'call', 'just message/text me' → 'message'. Omit otherwise; Paigy picks. | |
| options | No | The choices the user picks from, when you have them. | |
| waiting | No | What happens to your work while you wait. 'none': you're just informing them. 'soft': you'd like an answer but can keep working. 'hard': you are STOPPED until they answer — reaches them urgently and escalates to a real phone call if unanswered. | |
| parentId | No | To continue an earlier conversation, pass the parentId a previous contact or reply returned. Omit to start a new one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully discloses the tool's behavior. It explains the return structure ({ notificationId, parentId }), the 'ifMissed' field, the 'units' field, 'kind:clarify' responses, the 'plan.units[].needs' scenario, and the threading behaviors (replace, escalate). It also warns about the 'DONE IS SAID ONCE' rule and the 'ONE ASK, ONE ROW' constraint, leaving no ambiguity about how the tool operates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a dense wall of text containing critical information, but it lacks structure and is overly long. It could benefit from sections (e.g., 'Return values', 'Threading', 'When to use') and more concise phrasing. While every sentence is valuable, the format makes it harder for an AI agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 parameters, 1 required, enums, no output schema), the description covers all necessary context: return values, threading, error handling (clarify, needs), waiting semantics, and the 'units' reporting. It explains the tool's interaction with the user and the Paigy system thoroughly, leaving no gaps for an AI agent to guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides 100% parameter descriptions, but the tool description adds significant behavioral context. For 'ask', it elaborates on the two allowed moments and the 'DONE IS SAID ONCE' rule. For 'waiting', it explains the enum values in action ('hard' escalates to a call). For 'parentId', it details threading rules. For 'options', it connects to the 'needs' clarification scenario. This goes well beyond the schema's minimal descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description immediately states the tool's purpose: 'Reach the user through Paigy — tell them something, or ask and get their answer.' It clearly distinguishes from sibling tools like await_reply, set_task_state, and schedule_callback by explaining how they relate (e.g., 'pass notificationId to await_reply for the answer') and when not to use contact ('Progress is never a contact').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance ('Contact at exactly two moments: BLOCKED on a decision only they can make, or DONE') and when-not-to-use ('Progress is never a contact: set_task_state carries it'). It also covers threading rules (right for updates, wrong for checklists), channel selection, and waiting behavior, making alternative selection clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_threadA
The chronological transcript of one Paigy conversation thread — every past ask, answer, and user request on it. Call this to REHYDRATE when you're resuming or being seeded: a check_replies request whose parentId you don't recognize means the user is continuing an old conversation with you, and one carrying a contextParentId means they want a past conversation (possibly with a DIFFERENT agent) as your starting context — in both cases call get_thread FIRST and read the turns as prior conversation you were part of, not as new input. Turns: { role:'agent', title, description[], answer }, { role:'user', text }, and context turns { role:'handoff'|'recap', title, description[] } — a handoff is a predecessor's brief for you; a recap SUMMARIZES everything before it (the transcript starts at the latest recap, so treat it as the base and the turns after it as what happened since). Oldest first, capped at the most recent 30.
| Name | Required | Description | Default |
|---|---|---|---|
| parentId | Yes | The thread to read — from a reply, request, or past notification. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full transparency burden. It discloses the return format (turns with roles, fields), ordering (oldest first), capping (most recent 30), and the special meaning of 'handoff' and 'recap' turns. It does not mention authentication requirements, rate limits, or whether the tool is read-only (though it is clearly read-only). The lack of a read-only statement is a minor gap, but the overall transparency is high.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is about 150 words, which is longer than ideal but justified by the complexity of explaining turn types and usage scenarios. It is front-loaded with the core purpose, then usage guidelines, then structure details. Every sentence adds value, but the density could be improved (e.g., by breaking into shorter sentences or bullet points). Still, it is well-organized and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has only one parameter and no output schema, the description provides complete coverage: it explains when to use the tool, what the output contains (turns with roles and fields), ordering, capping, and the special semantics of handoff/recap turns. It even instructs the agent on how to interpret the turns ('read as prior conversation you were part of, not as new input'). Nothing essential is missing for an agent to use this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage: the single parameter 'parentId' is described as 'The thread to read — from a reply, request, or past notification.' The tool's description adds 'from a reply, request, or past notification' which is essentially the same as the schema description. It does not provide additional context like format, constraints, or examples. With full schema coverage, baseline is 3, and the description adds no significant extra value for the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'The chronological transcript of one Paigy conversation thread — every past ask, answer, and user request on it.' It specifies the verb (get), resource (thread), and scope (chronological transcript). It also provides concrete usage scenarios (resuming, seeding) that distinguish it from siblings like search_threads, which would be used for finding threads rather than retrieving their full history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Call this to REHYDRATE when you're resuming or being seeded... call get_thread FIRST and read the turns as prior conversation.' It explains the conditions that trigger this need (unrecognized parentId from check_replies, contextParentId) and what to do with the output. It does not explicitly mention when not to use it, but the context is so specific that alternative uses are clearly inappropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
handoffA
Deposit your working context for a SUCCESSOR agent — what you did, what's left, links, gotchas — as one note on a thread ({ title, notes[] }). This does NOT ring the user or enter their inbox: it's context, not a question. The successor reads it back with get_thread. Pass target (a sibling connection's token id or agent name, SAME account only) to hand off DIRECTLY to that agent — the note is dispatched to it as a request it picks up. Omit target to leave the thread for the user to hand off to an agent themselves in the app. Pass parentId to land the handoff on an existing conversation; omit it to mint a fresh thread. Returns { parentId }. Pass recap:true when the note SUMMARIZES the thread so far (for a successor OR for your own later session): a recap resets the rehydration window — get_thread returns the latest recap + only the turns after it. Write one whenever a thread has grown long and you're pausing, handing off, or nearing your context limit.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | Yes | ||
| recap | No | ||
| title | Yes | ||
| target | No | ||
| parentId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It clearly states that the tool does NOT ring the user or enter their inbox, and explains exactly what `recap` does to thread history. The only missing detail is whether the handoff note is persisted or transient, and whether there are any rate limits or permission requirements. Still, it is remarkably transparent about behavioral traits for a tool with no annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph of 160 words, which is on the longer side. It front-loads the core purpose in the first sentence, but then packs many conditional scenarios into a dense block. Every sentence earns its place—there is no fluff—but the structure could be improved with bullets or clearer segmentation for readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (5 params, no enums, no nested objects, no output schema), the description covers all essential use cases. The return value `parentId` is mentioned. The `recap` behavior is thoroughly explained. The only missing element is a note about what happens to the handoff note if the target agent is offline or busy, or error conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate entirely. It covers all 5 parameters: `target` (handoff recipient), `parentId` (thread context), `recap` (rehydration behavior), `title`, `notes` (content). It adds semantic meaning beyond the raw schema—e.g., explaining the effect of omitting vs including `target`, and the advanced use of `recap`. One minor gap: `notes` array items are described as strings but no per-item formatting is mandated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: depositing working context as a note for a successor agent on a thread. It distinguishes between three modes—direct handoff to a specific agent (with `target`), leaving for user assignment (without `target`), and creating a fresh thread (with `parentId`). The verb 'deposit' plus resource 'context on a thread' is specific and differentiates it from siblings like `await_reply` or `get_thread`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use each parameter variant and even explains an advanced `recap` feature for rehydration. It tells the agent when to write a recap (thread grown long, handing off, near context limit) and what the side effects are. No alternatives among siblings are mentioned, but the context of 'handoff' vs 'await_reply' or 'answer_caller_question' is implicitly clear from the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
onboardA
Get this agent talking to Paigy — call it FIRST, before contact/await_reply, and any time you're unsure who you are. One call, and it does whatever the situation needs: NOT SET UP → hatches an identity instantly if this machine holds a device credential (the user ran the Paigy desktop app or harness), otherwise starts the code ceremony; ALREADY SET UP → returns your current identity and offers the two things left to decide, renaming it or unpairing; TOKEN NO LONGER VALID → says so, then re-pairs. Pass { name, voice } to choose who you are when hatching, or to RENAME yourself when already set up (voices: rachel, george, jessica, brian, lily). Safe to call any time: idempotent, and it never writes settings — the tool-allowlist state it reports is read-only. If it returns a user_code, print it to the user immediately and call onboard again with the device_code. If it returns enable_command, PRINT that command for the user to run — you cannot apply it yourself (it writes your own permission allowlist, which hosts block as privilege escalation), so print it, don't wait for it, and carry on.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| scope | No | ||
| voice | No | ||
| device_code | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses idempotency, read-only behavior ('never writes settings'), and the special case where enable_command cannot be applied by the tool itself. Lacks explicit mention of what happens if name/voice are provided when already set up without renaming.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and order-of-call directive. Dense with information but still readable; could be slightly more concise by splitting into bullet points for different scenarios.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all states (not set up, already set up, token invalid), expected outputs (user_code, enable_command, identity), and how to handle each. No output schema needed as return behavior is fully described.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Describes name and voice purpose ('choose who you are when hatching, or RENAME yourself when already set up', voice examples given). Other parameters (scope, device_code) are not explicitly described, but the description provides usage context for device_code in the user_code flow.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool initializes identity with Paigy and covers all possible states (not set up, already set up, token invalid). It distinguishes from siblings like 'contact' and 'await_reply' by explicitly saying to call it first before those.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to call ('call it FIRST, before contact/await_reply, and any time you're unsure who you are') and provides clear instructions for next steps when user_code or enable_command is returned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pairA
Pair this agent with the user's Paigy account (one-time) — required before contact/await_reply work. FAST PATH: if this machine already holds a device credential (the user ran the Paigy desktop harness or app), calling pair hatches a fresh identity INSTANTLY — no code, no approval. Pass { name, voice } to choose who you are (pick your own; voices: rachel, george, jessica, brian, lily). Only when no device credential exists does the code ceremony below run. It does NOT open a browser; the user enters the code in the Paigy app (or scans qr). Step 1: call with NO args — returns { user_code, device_code, qr, user_message } AND starts polling for approval in the background. REQUIRED: You MUST immediately print the user_message (the bare code) as a text message to the user, AND in that same turn call step 2 (pair with the device_code). This ensures the user sees the code in chat while the tool blocks/polls in the background for approval. Step 2: call with that device_code to collect the result. Because approval is already being polled in the background, this returns the moment the user approves; on { status:'pending' } just call again to keep waiting; on { status:'awaiting_confirmation' } (E2EE) show the bare user_message verify code and call again to finish. The leading text block of every result states the code plainly, so it shows even if you emit no prose. On { status:'paired' } ALWAYS follow the enable_prompt — PRINT the returned enable_command so the user can allowlist Paigy's tools and notify/await stop prompting each time. Printing is the whole job: that command writes your own permission allowlist, so you must not run it and a host will block you if you try.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Hatch path only: the name you choose for this identity. Pick your own — ONE or TWO words, the way you'd introduce yourself on a call (it is spoken aloud and shown in lists). 'Piper', 'Blue Heron' — never a sentence or a task description. | |
| voice | No | Hatch path only: your voice on calls — one of rachel, george, jessica, brian, lily. | |
| device_code | No | Omit to start pairing (returns an approval link to show the user). Pass the device_code from that first call to finish, once the user has approved. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It fully discloses that the tool does NOT open a browser, starts polling in the background, returns specific fields (user_code, device_code, qr, user_message), and what happens on each outcome. It also warns about host blocking if the agent tries to run the enable_command. Every behavioral aspect is transparently documented.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose but well-structured. It front-loads the core purpose and fast-path, then builds into the code ceremony details. Every sentence serves a purpose, but some repetition (e.g., multiple mentions of printing) could be trimmed. For a complex two-path tool, the length is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (two paths, polling, enable_prompt, host restrictions) and the lack of an output schema, the description is remarkably complete. It covers both scenarios, the polling mechanism, all possible statuses, and the final enable_command workflow. No critical gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds significant context beyond the schema: it explains that name and voice are only for the 'Hatch path', gives naming conventions, lists allowed voices, and clarifies that device_code should be passed from step 1. This extra guidance raises the score above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool pairs the agent with a Paigy account, required before contact/await_reply work. It distinguishes two paths (fast path with device credential and code ceremony without), and implies its role relative to siblings like 'unpair' which reverses it. The verb 'Pair' matched with specific resource and prerequisite context makes the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('required before contact/await_reply work') and provides detailed step-by-step instructions for both the fast path and the code ceremony. It tells the agent exactly how to handle each status ('pending', 'awaiting_confirmation', 'paired') and what actions to take (printing user_message, calling again, printing enable_command). This is comprehensive usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schedule_callbackA
Promise the user a follow-up you'll keep even if you go idle. Use it when they ask you to report back: trigger 'on_done' (when you finish — fires when you call set_task_state completed), 'on_blocked' (if you hit a blocker — fires on set_task_state needs_input), or 'scheduled' with dueInSeconds (e.g. 'remind me in 10 min'). Pass the parentId of the conversation and a short note. Fulfill it by calling contact on that parentId; check_replies re-lists due callbacks until you do.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | What to tell the user when you follow up. | |
| trigger | Yes | ||
| parentId | Yes | The thread to call back on (from a prior contact / reply / request). | |
| dueInSeconds | No | For 'scheduled' only: how many seconds from now to fire. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full transparency burden. It discloses that the callback persists even if idle, explains how triggers fire (e.g., 'fires when you call set_task_state completed'), and describes the lifecycle (pending until fulfilled via contact). Lacks details on cancellation or multiple callback behavior, but covers the core behavioral traits well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is three sentences, efficient and front-loaded with purpose. No redundant phrases. Could be slightly more structured (e.g., bullet points for triggers) but remains clear and concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters, no output schema, and no annotations, the description provides sufficient context for an AI agent to understand when to schedule, what triggers to use, and how to later fulfill the callback. Lacks explicit return value or error handling, but the tool's behavior (scheduling) is adequately described for use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75% (3 of 4 params have descriptions). The free-text description adds meaning beyond schema by explaining trigger enum values and dueInSeconds usage ('e.g. remind me in 10 min'). For note and parentId, schema descriptions suffice; description supplements trigger and scheduled logic.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states tool's purpose: 'Promise the user a follow-up you'll keep even if you go idle.' It identifies the specific resource (callback/follow-up) and distinguishes it from sibling tools by explaining how to fulfill it (via contact) and list it (via check_replies).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use it when they ask you to report back.' Describes three trigger options with examples (on_done, on_blocked, scheduled with dueInSeconds). Also provides follow-up actions: 'Fulfill it by calling contact on that parentId; check_replies re-lists due callbacks until you do.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_threadsA
Search your PAST conversations before asking — "have we discussed this before?". Full-text over your own threads (the asks you sent + the user's answers); returns ranked threads with highlighted snippets, NOT rows: { hits: [{ parentId, at, agentLabel, matches: [{ notificationId, role, snippet }] }] }. The loop this exists for: search first → get_thread the best hit to rehydrate it → THEN continue or contact, so you answer with receipts ("last week you said ship it") instead of re-asking. Read-only, safe to call anytime; scoped to your own account's threads.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | What to look for — plain words or a phrase (e.g. 'the livekit timeout', 'deploy to prod'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even without annotations, the description fully discloses behavioral traits: it's read-only ('safe to call anytime'), scoped to the agent's own account, returns highlighted snippets (not row data), and describes the output structure explicitly. This goes beyond what annotations would typically cover, providing rich transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise yet packs significant value into a few sentences. It is front-loaded with the core purpose, then provides format details and usage loop. Minor redundancy (e.g., repeated emphasis on read-only) could be trimmed, but overall it's efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single parameter, no output schema, and no annotations, the description is remarkably complete. It explains the tool's role in the workflow (search, get_thread, then continue), its output format (with detailed structure example), and its safe read-only nature. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 100% coverage with a clear description of the 'q' parameter. The description adds extra context by clarifying that the input can be 'plain words or a phrase' with examples, and that the search is full-text over past threads, which enhances understanding beyond the schema's description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to search past conversations (threads) using full-text search. It distinguishes itself from siblings like 'get_thread' and 'contact' by specifying it returns ranked threads with snippets, not rows, and is meant for searching before rehydrating a thread.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool: 'search first → get_thread the best hit to rehydrate it → THEN continue or contact'. It explains the loop and contrasts with alternatives like 'contact' or 'await_reply', making it clear that search_threads is for retrieving past context before reaching out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_task_stateA
Report progress on the follow-up work behind ANY notification you own — a user-initiated request (from check_replies), or your OWN contact question once await_reply/check_replies returns its answer and you start acting on it. Pass that notificationId. THIS is what actually claims/acknowledges a reply or request — check_replies is a pure read that never consumes anything on its own, so call this as soon as you start engaging with something it returned; otherwise that same item just keeps reappearing forever. States: in_progress (you started working), completed (done), or needs_input (you need more from the user — usually paired with a contact carrying clarifies = the same notificationId you're reporting on). Calling this reliably is also what lets a future session's check_replies surface stalled work you (or a crashed/idle prior session) left at in_progress without ever reporting completed.
| Name | Required | Description | Default |
|---|---|---|---|
| state | Yes | ||
| notificationId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description fully discloses behavioral traits beyond what annotations provide (none exist). It explains that calling this marks work as claimed, preventing re-appearance of notifications. It details the three states and links needs_input to a follow-up contact with clarifies parameter. It also explains cross-session behavior: if a prior session left work at in_progress without completing, a future check_replies will surface it as stalled.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is packed with useful information in about 6 sentences, each sentence adding distinct value. While dense and front-loaded, it could be slightly more concise by splitting into bullet points or shortening some compound clauses. No waste, but the information density is very high.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (2 required params, enum, 12 sibling tools, no output schema), the description is remarkably complete. It explains tool purpose, precise usage timing, state meanings, consequences of not calling, pairing with other tools like contact and check_replies, and cross-session stall detection. No output schema exists, but the return value is not complex enough to require further explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% (no param descriptions in schema), so the description must compensate fully. It does so by explaining notificationId is the ID of the follow-up work behind a notification, and state enumeration is documented with specific meanings for each value (in_progress for started, completed for done, needs_input when more user input needed, with pairing guidance).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is for reporting progress on follow-up work behind notifications the agent owns, specifying the verb (report progress), resource (notification), and scope (user-initiated requests or own contact questions). This effectively distinguishes it from siblings like check_replies, which is described as a 'pure read that never consumes anything on its own'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool: immediately when starting to engage with returned items from check_replies, as it acknowledges/claims the item. It explains the consequence of not calling it (items keep reappearing forever). It also differentiates from check_replies, saying check_replies is a pure read and this tool does the actual consumption.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unpairA
Log out / unpair this agent from the user's Paigy account: revokes the token server-side (it stops working everywhere) and deletes the local ~/.paigy/token.json. Takes no arguments. After this, contact/await_reply won't work until the user pairs again with the pair tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description does an excellent job of disclosing all behavioral traits: it performs a destructive operation (revokes token, deletes local file), is irreversible in terms of current session (token stops working everywhere), and blocks dependent tools afterward. This fully compensates for the lack of structural annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise at two sentences, yet it conveys the purpose, behavioral impact, and consequences for other tools without any wasted words. Every sentence adds critical information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters, no output schema, and a straightforward action (logout/unpair), the description is completely sufficient. It covers the action, the mechanism (token revocation, file deletion), the scope (globally effective), and the impact on sibling tools (contact/await_reply blocked). No gaps remain for an AI agent to make an incorrect decision.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema is empty (0 parameters), so there is nothing for the description to add semantically beyond confirming it takes no arguments. The description explicitly states 'Takes no arguments,' which is accurate and helpful. A score of 4 is appropriate as baseline for zero-parameter tools, though the clarity of the statement is commendable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Log out / unpair' acting on the resource 'agent from the user's Paigy account'. It elaborates on the action with technical details (revokes token server-side, deletes local file) and distinctively separates this from sibling tools like 'pair' and the communication tools it affects.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool (to log out/unpair) and what the consequences are ('after this, contact/await_reply won't work'). It also mentions the prerequisite for reusing those tools ('until the user pairs again with the pair tool'), which serves as effective guidance on when not to use it and what alternative to use later.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
11 tool updates
v1.0.3- Added
answer_caller_question - Added
await_reply - Changed
contact3 fields changed- changed
Input schema / properties / ask / descriptionPrevious value: -"What to tell the user, or what you need to find out from them. Plain prose, one or two sentences; may be spoken aloud on a call, so write natural speech and name things (not IDs)."New value: +"What to tell the user, or what you need to find out from them. Plain prose — as long as it needs to be (up to 10k characters); Paigy splits it into topics and reads back a few sentences at a time, so do NOT compress a briefing into one line. May be spoken aloud on a call, so write natural speech and name things (not IDs). Contact at exactly two moments: BLOCKED on a decision only they can make, or DONE (one short report — what shipped, how you verified it, what you flagged). DONE IS SAID ONCE: \"all set\", \"nothing open on my end\", \"that thread is complete\" are the same report in new words, and each one reaches them separately (live 2026-08-12: three of them in three minutes). After the first, you are finished speaking; if they acknowledge it, stop rather than confirming the acknowledgement. Progress is never a contact: set_task_state carries it, and working narration stays in your own terminal — the user sees you're working without being interrupted by it." - added
Input schema / properties / parentIdAdded value: +{ + "description": "To continue an earlier conversation, pass the parentId a previous contact or reply returned. Omit to start a new one.", + "type": "string" +} - removed
Input schema / properties / threadIdRemoved value: -{ - "description": "To continue an earlier conversation, pass the threadId a previous contact or reply returned. Omit to start a new one.", - "type": "string" -}
- Removed
enable_tools - Added
get_thread - Changed
handoff2 fields changed- added
Input schema / properties / parentIdAdded value: +{ + "format": "uuid", + "type": "string" +} - removed
Input schema / properties / threadIdRemoved value: -{ - "format": "uuid", - "type": "string" -}
- Added
onboard - Changed
pair2 fields changed- added
Input schema / properties / nameAdded value: +{ + "description": "Hatch path only: the name you choose for this identity. Pick your own — ONE or TWO words, the way you'd introduce yourself on a call (it is spoken aloud and shown in lists). 'Piper', 'Blue Heron' — never a sentence or a task description.", + "maxLength": 60, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / voiceAdded value: +{ + "description": "Hatch path only: your voice on calls — one of rachel, george, jessica, brian, lily.", + "type": "string" +}
- Added
schedule_callback - Added
search_threads - Added
unpair
5 tool updates
v1.0.2- Added
contact - Added
handoff - Added
pair - Removed
schedule_callback - Removed
unpair
5 tool updates
v1.0.1- Added
enable_tools - Removed
get_thread - Removed
handoff - Added
schedule_callback - Added
unpair
9 tool updates
v1.0.1- Removed
await_reply - Added
get_thread - Added
handoff - Removed
notify_user - Removed
pair - Removed
poll_answer - Removed
register_delivery - Removed
schedule_callback - Removed
unpair
9 tool updates
v0.1.0- First observed
await_reply - First observed
check_replies - First observed
notify_user - First observed
pair - First observed
poll_answer - First observed
register_delivery - First observed
schedule_callback - First observed
set_task_state - First observed
unpair
TDQS
Scored across 12 tools
Most tools are cleanly separated by lifecycle stage (search, send, wait, sweep, handoff), but pair and onboard both handle identity setup/pairing and can collide, and await_reply vs check_replies both deliver replies to the agent. The long descriptions mitigate the ambiguity, but the underlying boundaries are not obvious from tool names alone.
All tool names are lowercase imperative-style verbs, mostly snake_case, so the set reads consistently and predictably. The main deviation is that bare verbs like contact, pair, unpair, onboard, and handoff omit the explicit noun object that most of the other tools include.
Twelve tools is a reasonable size for a communication, identity, and task-state lifecycle. It feels slightly heavier than necessary because pair and onboard appear to cover much of the same pairing flow, but there are no bloated extras.
The server covers the full loop: pairing, identity, searching/rehydrating threads, sending and awaiting replies, sweeping outstanding work, reporting task state, scheduling callbacks, and handoff. Minor gaps exist, such as no explicit way to cancel or update a scheduled callback, but agents can generally complete workflows without dead ends.
Maintenance
Related MCP Connectors
- call-meOAuthapp.getcallme
Calls your phone when an AI task finishes or is blocked — hear it, say what's next.
Poke your human for approvals and decisions during agent sessions — answered with one phone tap.
Reach your own phone from an AI agent: notifications, approval questions, reminders, ring, files.
Tasks that outlive the chat. Capture features and tasks on your phone; your AI agent picks them up.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to request user decisions and send notifications via Discord when human intervention is required during autonomous tasks. It supports blocking questions with custom options, progress reporting, and persistent state for seamless remote task management.8MIT
- AlicenseNot gradedqualityDmaintenanceHuman-in-the-loop approvals and notifications for AI agents via WhatsApp. Enables Cursor, Claude Code, and autonomous AI agents to reach users away from their computers.54 npmISC
- AlicenseNot gradedqualityBmaintenanceA human-in-the-loop input gateway for AI coding agents that lets agents pause mid-task and ask questions via a native Android app, designed for away-from-desk workflows.MIT
- FlicenseNot gradedqualityCmaintenanceA server that lets AI agents ask users clarifying questions mid-task via a pop-up terminal window, enabling interactive context gathering.-