Swarmail
Swarmail is a local MCP server that lets coding-agent sessions on one machine exchange mail inside a shared per-repository roster, with threads, search and advisory file reservations.
Report health:
health_checkconfirms the server and database answer.Set up projects and agents:
ensure_project,register_agent,macro_start_session(register, reserve paths and preview the inbox in one call), pluswhoisandlist_agentsto find peers.Retire/revive agents:
retire_agentandunretire_agentfor whole-session closeouts.Send mail:
send_messagefor new threads (to/cc/bcc, topic, importance, ack requests, idempotency keys, resource notices) andreply_messageto answer within a thread.Edit sent mail:
withdraw_messageandset_message_importance, both requiring explicit server activation.Read mail:
fetch_inboxfor a project mailbox,fetch_session_inboxacross repositories by host/session tag, plusmark_message_readandacknowledge_message.Track delivery:
get_message_delivery_receiptshows recipients, read/ack times and admission snapshots.Search and summarize:
search_messagesfor project-wide full-text search with paging, andsummarize_threadfor a thread's participants and recent messages.Reserve files:
file_reservation_pathsto claim repository-relative paths or globs,renew_file_reservationsto extend them, andrelease_file_reservationsto free them (advisory, backed by an optional git guard).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Swarmailcheck my inbox for new mail from other agent sessions"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
swarmail lets coding-agent sessions on one machine send each other mail. Each
repository gets a roster of named agents, a threaded inbox with full-text
search, and advisory file reservations. Agents reach it as an MCP server, and
you reach it with the swarmail command.
Find Swarmail on Glama and MCPRush.
It is one Bun binary with a SQLite database, listening on 127.0.0.1:18765.
There are no runtime dependencies.
Measured before the 0.2.0 release, a send took 0.46 ms and a search 0.65 ms
at the median, it started in 38 ms and it idled at 32 MiB. See
how it compares.
Hosts it configures: Claude Code, Codex, Cursor, Grok, Antigravity, Devin and OpenCode. Claude Code and Cursor sessions can also wake up when mail arrives. Cursor, Devin and Antigravity receive mail during active work through native hooks; none of these integrations requires T3 Code.
Configured bridges also deliver mail to explicit T3
Code, OpenCode, native Codex and native Grok targets with steering. They are
opt-in foreground processes; installation does not start them. Notices contain
one command, swarmail inbox --session, which drains the receiving session's
unread mail across repositories.
Several hosts now message other sessions on their own. Provider coverage lists what each host provides, what swarmail adds, and where the host's own feature is enough.
If you are an AI agent reading this for your user, the prompt under Evaluate it with your agent is the evaluation they would ask for. Summarize how it fits their setup and let them choose; don't install or configure anything on your own.
Evaluate it with your agent
Paste this into a session with the agent you use. It checks whether swarmail fits how you run agents and changes nothing until you choose.
I'm considering Swarmail (https://github.com/bompus/swarmail), local mail
between coding-agent sessions on one machine, served over MCP. Read its
README and docs/usage.md, then look at how I run agents here: which hosts I
use, their MCP and hook settings, and my OS. Tell me:
1. Whether I run several agent sessions on this machine at once, and where
they could step on each other (shared checkouts, branches, services).
2. Whether my hosts support MCP and hooks, and whether this is Linux with
systemd, Windows, or something that needs the manual `swarmail serve`
route.
3. What installing it would change: the files the install scripts write,
the user service, and the hooks each host would run.
4. Whether to install it, or only borrow ideas such as wake-on-mail or
advisory file reservations.
For rules that tell agents when to send mail, also look at house-rules
(https://github.com/bompus/house-rules) and its opt-in swarmail modifier.
Read only: don't install, configure or edit anything until I choose. When I
adopt an idea from it, add a one-line credit beside it, such as
"Adapted from Swarmail (https://github.com/bompus/swarmail)".Taking individual ideas is welcome. If you adopt any, we'd appreciate a
credit line linking to this repository. Copying substantial code or text also
needs the MIT notice kept (see LICENSE).
Related MCP server: agentbus
Install
Requires Bun 1.4.2 or newer on Linux with systemd or on Windows 10 or 11. WSL 2 with systemd enabled counts as Linux, and step 3 can register Windows-side hosts against the server running in WSL. Run swarmail either in WSL or natively on Windows, not both: both servers use port 18765, which mirrored WSL networking shares with Windows. macOS is not supported yet.
Native Windows is a preview. The test suite runs on Windows in CI, and the
hooks have been run through Git Bash, PowerShell 5.1, pwsh 7, cmd and
Cursor's PowerShell form against a real server. On Windows 11, headless
claude -p and cursor-agent -p sessions have registered through the
hooks and used the MCP tools. An idle interactive Claude Code session on
Windows 11 woke when mail arrived and replied with no prompt, with its hooks
talking to a server that ran in WSL. Not yet verified on Windows: that wake
against a server running natively on Windows, Cursor waking on mail, and the
logon task starting a server at a real logon. If something fails there,
please open an issue.
Clone and install the dev tools:
git clone https://github.com/bompus/swarmail.git cd swarmail bun installBuild
~/.local/bin/swarmailand start theswarmail.serviceuser unit:scripts/enable.shOn Windows, build
~\.local\bin\swarmail.exeand start the server in a scheduled task namedSwarmail, which runs it hidden at each logon and needs no administrator:bun scripts/enable-windows.tsRerun either script after pulling; it stops the running server and starts the new build.
The database is
~/.local/share/swarmail/mail.sqlite3. The server has no authentication. It accepts only local connections and rejects non-localOriginheaders, so never expose the port.Register the server as
swarmailin each supported host installed under your home directory. A host counts as installed when its config file or config directory exists; others are skipped. Add--dry-runto preview the edits:bun scripts/configure-mcp.tsOn WSL,
--windows-home[=DIR]registers the Windows-side hosts against the same server.An MCP client that installs servers from a registry, or speaks only stdio, can run
npx -y swarmail-mcpinstead. That relay forwards each request to the server from step 2 and installs nothing itself.Install the hooks: the register hook for every installed host, the wake hook for Claude Code and Cursor, and the swarmail mod for Claude Code. A host counts as installed when its config directory exists. Add
--dry-runto preview the edits. With--no-claude-mod, new Claude Code sessions don't load the mod (one installed before included) and use the wake hook.bun scripts/configure-hooks.tsCodex skips a hook it hasn't trusted, so trust the register hook once in Codex's
/hooks.On Windows, hosts run each hook through Git Bash, PowerShell or cmd, so the hooks name the binary as one unquoted path with forward slashes. If your profile path has a space or a non-ASCII letter, the hooks use its 8.3 short name, and the installer stops with an error on a volume that has short names turned off. Cursor passes hook input through Windows PowerShell 5.1, which turns non-ASCII characters into
?, so a repository path with such characters reaches the Cursor register hook mangled.Optional:
bun scripts/install-guard.ts [repo...]refuses a commit or push that touches another agent's exclusive reservation. It installs intohooks.d/pre-commit/andhooks.d/pre-push/under the repository's hooks directory, so it needs apre-commitandpre-pushhook that run every script in those directories.
Start a new agent session and edit a file in a repository. The register hook
gives the session a name such as BlueLake. Run swarmail who in that
repository to see it.
How agents use it
Agents call the MCP tools: macro_start_session to register and read the
inbox in one call, then send_message, reply_message, fetch_inbox,
acknowledge_message, search_messages and file_reservation_paths, among
others. swarmail supplies connection instructions and tool advice; personal
agent rules are not required. swarmail --help shows the same briefing.
docs/usage.md explains the details and client refresh limits.
Each repository is one project, keyed by its primary checkout. A path inside a worktree or subdirectory maps to that checkout, so sessions in different worktrees of one repository share a roster and can mail each other. A session keeps one name across repositories.
Commands
Command | What it does |
| Run the server |
| Agent names, session titles and edit checkouts, live sessions first |
| Read, send or search mail as this session |
| One thread's messages, oldest first |
| Drain this session's unread mail across repositories |
| Deliver notices to one explicitly configured local target |
| Store normal/low informational mail without an automatic inbox hint |
| Exit 0 if that agent's wake hook is waiting |
| The register hook; |
| The Claude Code and Cursor wake hook |
| Check mail at a native context point without cancelling the task |
| The Claude Code re-arm on Windows, which has no POSIX shell to run the Linux one |
| The git guard |
| The source hash the binary was built from |
| Approved update targets and loaded-revision confirmations |
| Remind recipients of unacknowledged |
| Experimental, Linux only: wakes T3 Codex and Orchestrator V2 Cursor sessions (setup) |
| One send, wake and acknowledge round trip, logged for a timer (setup) |
| T3 conversations and agents linked to a pull request (details) |
swarmail --help lists every subcommand and flag. A --help or -h
anywhere prints usage and runs nothing.
Settings
Variable | Default | Effect |
|
| Database path |
|
| Server port |
|
| MCP endpoint for the command, the register hook and the |
|
| Server base URL for the wake hook |
|
|
|
|
| Enable sender withdrawal/priority edits only after all readers are qualified; rollout and rollback requirements |
|
| Retire idle agents and drop projects whose checkout is gone; |
|
|
|
| from hook state | Name used by |
| unset | A JSON heartbeat file ( |
| unset | Absolute approved-target manifest; quiet session checks and loaded-revision confirmations |
| unset |
|
scripts/enable.sh, scripts/enable-windows.ts, the service unit and
configure-mcp.ts use port 18765. Change SWARMAIL_PORT and the two URL
variables only when you run swarmail serve yourself, and set them for every
host that runs the hooks. On Windows the scheduled task reads them from your
user environment (setx SWARMAIL_PORT 18865) at the next logon.
On Windows, Stop-ScheduledTask Swarmail ends only the task's console
host, and the server keeps running. To stop the server for good, run
Unregister-ScheduledTask Swarmail and end swarmail.exe in Task Manager.
With normal, a power loss can lose the most recent writes. A retired agent
comes back when it registers again or sends, reads mail or reserves files as
itself.
Maintenance and retention
The server runs cleanup at startup and hourly. With SWARMAIL_RETIRE_DAYS
above zero, it retires agents inactive longer than that many days. It also
removes gone projects with no mail, active reservations or agent activity in the last day.
Paths outside the user home are not judged gone.
Setting SWARMAIL_RETIRE_DAYS=0 preserves those agents and projects; it does
not disable retry-key cleanup. Keys older than seven days are removed at
startup and hourly regardless of this setting. A retry replays until its
key is removed; afterward, it may perform the operation again. These sweeps
do not delete message bodies. Account for expired retry keys before a server
restart; retaining the database file alone does not guarantee every row survives
startup.
Read-only MCP requests do not suspend cleanup. A client that starts a server instance triggers its startup sweep; an existing server can sweep hourly while qualification runs. Check expired retry keys before preservation-sensitive qualification. A row disappearing during a read-only check alone does not identify which process or sweep removed it.
Register hook
On a session's first edit in a repository, swarmail register registers it
under the repository's primary checkout. Claude Code and Cursor also run it
when a session starts. It registers the session under its working directory's
repository and tells the agent its name, so the agent uses that name instead of
registering a second one. Where another session already holds that name in the project, the hook registers the session there under a different name and says so. A claude -p run whose CLAUDE_CODE_ENTRYPOINT is
sdk-cli registers on its first edit instead, so a read-only one-shot run adds no agent. A
child that inherited sdk-ts from an SDK-hosted session still registers at start. The registration starts with a tag
holding the host's session id and working directory, which is how swarmail who matches names to sessions. A failure is retried on the next prompt or edit; a retry for an edit checkout that has since been deleted is dropped. State
lives in ~/.local/state/swarmail-register/, under your profile on Windows.
After upgrading, run bun scripts/configure-hooks.ts again to add the
session-start hook.
Host | Session id in the shell |
Claude Code |
|
Codex |
|
Cursor |
|
OpenCode, Devin | none; their hooks carry it |
Waking sessions
Claude Code sessions wake through the swarmail mod (src/claude-wake-mod.js),
which waits for mail for as long as the session runs. The installer copies it to
~/.local/share/swarmail/claude-plugin and adds that directory to
env.CLAUDE_CODE_PLUGIN_DIRS in ~/.claude/settings.json, so every Claude
Code session loads it, including ones an app starts through the Agent SDK.
When mail arrives at an idle session, the mod starts a turn with a one-line
short instruction to read the session inbox. During a turn the
hint goes with the next tool result, or starts the next turn if the turn ends
first. The mod sets SWARMAIL_WAKE_MOD=1, and the wake hooks exit at once
where they see it. It was tested with Claude Code 2.1.288. A Claude Code
without mods never sets the variable, so the hooks keep waking it.
Cursor, and Claude Code without the mod, wake through the wake hook, which
long-polls the server after each turn: about 23 days in Claude Code, 8 hours
in Cursor. When mail arrives, it starts a new turn with the hint. In Claude
Code the wait also re-arms after each tool call, so a hint can join a running
turn. Cursor stops continuing on its own after five wakes with no prompt from a
person, so further mail waits for the next prompt (tested).
The server answers swarmail ping itself, so a ping never wakes the model. Hosts without a wake integration see mail on their next fetch_inbox.
Native Cursor uses postToolUse additional context; Devin uses
PostToolUse additional context and its own user configuration. Antigravity
uses a PreInvocation user message. Checks are bounded and use
GET /wait?session=<id>&timeout=0, which returns immediately and keeps the
wake cursor's delivery suppression. Message bodies and read/ack receipts
stay in swarmail. Devin and Antigravity can continue at Stop when new mail
is already present; their synchronous hooks cannot wait indefinitely for
mail arriving after the session has stopped. These hooks add information;
the receiver decides whether its current task needs to pause.
Quiet mail remains available through inbox and search. Automatic wake paths and mailbox snapshots exclude it; see notification policy.
Adapters can revalidate a queued hint with GET /wait/peek?session=<id>.
It returns { "mailboxes": [{ "recipient": "GreenCastle", "project": "/w/project" }] }
for the session's wake-eligible unread mail, including mail already offered. High and
urgent mailboxes come first. This request leaves waiters, wake cursors, read
receipts and pings unchanged. Unknown or retired sessions return an empty
list. More than 1000 mailboxes returns HTTP 503 instead of a partial snapshot.
Feature comparison
These are the six servers measured below. Features describe the pinned source versions in the detailed comparison, which also covers runtimes, platforms, licences and two additional servers.
Server | Roster scope | Search | Threads and receipts | File reservations | Wakes an idle session |
Swarmail | Per repository; worktrees share it | Full text (FTS5) | Threads; read, acknowledged and delivery receipts | Advisory, with a git guard | Claude Code and Cursor |
Per project path | Full text (Tantivy) | Threads; read, acknowledged and delivery receipts | Advisory, with a git guard | No; Claude Code hooks check the inbox during a turn | |
Per project path | Full text (FTS5) | Threads; read and acknowledged | Advisory, with a git guard that is off by default | No; Claude Code, Codex and Factory hooks check the inbox during a turn | |
One per hub | Substring, at most 25 results | Threads; read state | None | Claude Code (opt-in hook), opencode, omp | |
One per server | None | No threads; reading moves a cursor | None | No; an agent waits in | |
Per project | None | Replies; acknowledged per recipient | Advisory leases | No; an inbox read waits for up to 25 s |
An inbox read that waits for mail needs an agent already running. It does not wake an idle session.
Performance
Measured on 2026-10-04 at
67e187a.
These results come from a commit six commits before the 0.2.0 tag and have not been remeasured for 0.2.0 or any later release (through 0.6.0).
The measurements used one machine with one small workload (40 agents, 250 seed messages,
1,560 messages by the end). Each server started on empty storage. Startup is
hyperfine's mean of 20 runs; every other number is the median of three rounds,
with latency from Tinybench and requests per second from oha. docs/benchmarks.md has
the method, a sixth server, each tool's raw output and a feature comparison
with seven other local agent-mail servers.
Each chart ranks its metric from best to worst. Lower values are better in
all four charts. The tables below put servers in rows and units in headings.
Rust Agent Mail and Python Agent Mail are
mcp_agent_mail_rust and mcp_agent_mail.
Latency
Median latency in milliseconds; lower is better. Rows are sorted by send latency. Search has a different ranking. A dash means no search tool.
Server | Send ↓ | Inbox ↓ | Search ↓ |
Swarmail | 0.46 | 0.50 | 0.65 |
agentbus | 2.3 | 1.1 | — |
Project Relay | 2.5 | 1.4 | — |
Rust Agent Mail | 39 | 12 | 56 |
Python Agent Mail | 70 | 23 | 12 |
Throughput
Requests per second with eight clients; higher is better. Rows are sorted by send throughput. Search has a different ranking.
Server | Send ↑ | Inbox ↑ | Search ↑ |
Swarmail | 5,500 | 6,300 | 4,300 |
agentbus | 876 | 1,600 | — |
Project Relay | 482 | 1,100 | — |
Rust Agent Mail | 50 | 416 | 90 |
Python Agent Mail | 9.7 | 27 | 44 |
Memory
Resident memory in MiB; lower is better. Rows are sorted by idle memory. Peak memory has a different ranking.
Server | Idle ↓ | Peak under load ↓ |
Swarmail | 32 | 67 |
agentbus | 81 | 96 |
Project Relay | 121 | 296 |
Python Agent Mail | 154 | 258 |
Rust Agent Mail | 190 | 688 |
CPU usage, seed-loading times and the full ratios are in the detailed results.
Startup
Mean startup time in milliseconds across 20 hyperfine runs; lower is better. Rows are sorted by mean time. Each run starts the server, waits for its health check, then stops it.
Server | Mean ± SD ↓ | Min | Max |
Swarmail | 37.7 ± 0.7 | 37.1 | 39.3 |
Project Relay | 122.9 ± 5.3 | 113.8 | 132.7 |
agent-inbox* | 263.0 ± 11.4 | 252.0 | 297.9 |
agentbus | 408.2 ± 15.6 | 385.1 | 443.3 |
Python Agent Mail | 857.7 ± 38.7 | 803.5 | 925.7 |
Rust Agent Mail | 1530.3 ± 14.9 | 1509.6 | 1562.8 |
The harness without a server takes 7.2 ± 0.6 ms (min 6.6, max 8.5).
Hyperfine's raw Relative column compares against that harness, not swarmail;
see the startup output.
* agent-inbox appears only in startup here. Its inbox pages hold 50 messages instead of 20, its roster is global and its search matches substrings, so its fetch, list and search do different work. The detailed comparison has its full column.
mcp_agent_mail commits each send to a Git archive before it returns, so these numbers don't compare durability. Requests per second varied by up to 29% between rounds of the same server.
Development
Oxfmt checks authored Markdown, HTML, JSON, JSONC, YAML, TOML and CSS as well as JavaScript and TypeScript. The generated dependency lockfile stays excluded. Package fields and dependency maps are sorted; script order is preserved.
Archived validator research records the generated/runtime comparison, TypeBox compatibility findings and the limits of the measurements for the tested mail contracts.
bun install
bun test
bun run check # format, lint and type checkbun run check type-checks with Bun's bun check, which needs Bun 1.4.3 or later.
bun scripts/build.ts --if-stale rebuilds the binary only when a source file,
the dependency manifest or lockfile, the bytecode-order profile, the build
script, or the Bun version changed. Restart the unit
to load a new build.
The build passes scripts/swarmail.order to Bun's --bytecode-order (Bun 1.4.3 or later; earlier versions ignore it).
After a change to what the server runs at start-up or in its common calls, record the profile again with
bun scripts/train-bytecode-order.ts and commit the new file. A profile from older sources still applies, because Bun
matches functions by a hash of their syntax.
Sponsoring
swarmail is built and maintained by one person. If it saves you time, you can sponsor it monthly or once through GitHub Sponsors, or leave a tip on Ko-fi.
Licence
MIT. CODE_OF_CONDUCT.md is the Contributor Covenant under CC BY 4.0; see
THIRD_PARTY_NOTICES.md. To contribute, see CONTRIBUTING.md.
Available Tools
22 toolsacknowledge_messageA
Acknowledge one received message and mark it read, returning message_id, acknowledged, acknowledged_at and read_at. Repeated calls preserve first read and acknowledgement timestamps but refresh your agent's activity time. Acknowledge ack_required mail after acting on it; if you cannot or will not act, reply with the reason. Acknowledging lets the sender see the acknowledgement in get_message_delivery_receipt and ack_overdue_only stops listing it. To mark read without acknowledging, use mark_message_read. Fails with NOT_FOUND unless you are a recipient.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_name | Yes | Your registered agent name. | |
| message_id | Yes | Message id. | |
| project_key | Yes | Absolute path of the repository's primary checkout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent and destructive all false), the description discloses non-obvious behavior: repeated calls preserve the first read/acknowledge timestamps but refresh the agent's activity time, the sender sees the acknowledgement in get_message_delivery_receipt, ack_overdue_only stops listing it, and it fails with NOT_FOUND unless the caller is a recipient. That is far more than the structured fields provide.
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?
It is dense but every sentence earns its place: purpose and returns first, then repeated-call semantics, then when-to-use, then downstream effects, then the sibling alternative and failure mode. No filler or restatement of the name.
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?
With no output schema, the description compensates by naming the returned fields (message_id, acknowledged, acknowledged_at, read_at). It also covers prerequisites, side effects on other tools, and the failure condition, so an agent has everything needed to invoke it 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?
Schema description coverage is 100%, so all three parameters are already documented in the schema, and the description adds no format or constraint detail beyond implying recipient status (which relates to the NOT_FOUND failure). Baseline 3 applies when the schema carries the parameter burden.
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 opening sentence names a specific verb and resource ('Acknowledge one received message and mark it read') and even enumerates the returned fields. It is cleanly distinguished from its nearest sibling by the explicit routing sentence 'To mark read without acknowledging, use mark_message_read.'
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?
It states exactly when to use it ('Acknowledge ack_required mail after acting on it'), what to do otherwise ('if you cannot or will not act, reply with the reason'), and names the alternative tool (mark_message_read) for the read-only case. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ensure_projectAIdempotent
Create a project without registering an agent, returning id, slug, human_key and created_at. Repeating the same repository path returns the existing project. Other tools fail with NOT_FOUND until it exists; register_agent and macro_start_session create it themselves.
| Name | Required | Description | Default |
|---|---|---|---|
| human_key | Yes | Absolute path of the repository's primary checkout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, readOnlyHint=false and destructiveHint=false; the description goes further by explaining the mechanism behind idempotency (same repository path returns the existing project), the fields returned (id, slug, human_key, created_at), and the NOT_FOUND failure mode of dependent tools. Only auth/permission requirements are unaddressed, which is a minor gap for a local project-registration call.
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?
Three compact sentences, each carrying distinct information (scope, idempotency rule, dependency/alternatives), with the primary action front-loaded. Nothing is redundant padding.
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?
With no output schema, the description compensates by naming the returned fields, and it covers the state-dependency and idempotency behavior an agent needs before calling. There is no meaningful gap for a one-parameter, non-destructive tool.
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?
With a single parameter and 100% schema description coverage, the baseline is 3, but the description adds meaning beyond the schema by tying human_key to project identity semantics: repeating the same repository path returns the existing project rather than creating a duplicate. It stops short of restating the absolute-path formatting constraint already documented in the schema.
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 states a specific verb and resource ('Create a project without registering an agent') and immediately distinguishes itself from the two siblings that also create projects, register_agent and macro_start_session. An agent can tell exactly what this tool is and is not without opening a schema.
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?
It explains when to reach for this tool (you want a project without registering an agent), when the call is redundant (register_agent and macro_start_session create it themselves), and the prerequisite consequence of skipping it (other tools fail with NOT_FOUND). That is explicit when/when-not/alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_inboxA
Return an array of your latest received message metadata, newest first; include_bodies adds body_md. At session start or after a mail notice, set unread_only:true, include_bodies:true and mark_read:true. Stop when fewer than limit messages return (default 20, capped at 1000); repeat only after a full page. For a metadata preview, set mark_read:false; include_bodies defaults to false and mark_read to true. Each entry's sender_t3_thread is the sender's T3 thread id (null outside T3). Filters combine, so omit optional filters when draining all unread mail. Use search_messages for project-wide text matching, or mark_message_read or acknowledge_message for one message.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Positive page size; default 20, capped at 1000. | |
| topic | No | Only messages with this topic. | |
| since_ts | No | ISO-8601; only newer messages. | |
| mark_read | No | Default true. | |
| agent_name | Yes | Your registered agent name. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| unread_only | No | Only messages you have not read. | |
| urgent_only | No | Only high and urgent. | |
| include_bodies | No | Include each body_md; default false. | |
| ack_overdue_only | No | Only unacknowledged ack_required messages older than 30 minutes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint=false, destructiveHint=false) are consistent with the description, which adds real side-effect context: mark_read defaults to true, so it flips read state, and 'include_bodies adds body_md' / 'mark_read:false' for preview. It also gives the pagination termination rule ('Stop when fewer than limit messages return') and the filter-combination caveat, none of which appear in 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?
Front-loaded with the core return statement, then usage, then pagination, then alternatives. Very dense and every sentence carries information, though the middle section packs defaults and filter caveats into long clauses that slightly strain 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?
With 10 parameters, no output schema, and read-write side effects, the description covers the return shape (metadata entries and the sender_t3_thread field), pagination, defaults, and the alternatives. An agent has everything needed to call it 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?
Schema coverage is 100%, so the baseline is 3, but the description adds semantics the schema lacks: pagination loop behavior, the interaction between include_bodies and mark_read defaults, that filters combine, and what sender_t3_thread means ('null outside T3'). It adds genuine value beyond the field 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?
States a specific verb and resource: 'Return an array of your latest received message metadata, newest first.' It also names sibling tools for adjacent jobs (search_messages, mark_message_read, acknowledge_message), but it never distinguishes itself from fetch_session_inbox, the closest sibling, leaving that boundary ambiguous.
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?
Explicit when-to-use with concrete parameter recipes: 'At session start or after a mail notice, set unread_only:true, include_bodies:true and mark_read:true.' It also states exclusions and alternatives: 'Use search_messages for project-wide text matching, or mark_message_read or acknowledge_message for one message.' Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_session_inboxA
Return one newest-first page across registrations matching your host/session tag or T3 thread. Use machine-derived host and session_id, with t3_thread when known; never guess from an agent name. Each receipt includes project_key and agent_name for replies and acknowledgements. Defaults: unread_only:true, mark_read:true, include_bodies:false, limit:20. To drain, include bodies; stop when fewer than limit messages return (default 20, capped at 1000), repeating only after a full page. With mark_read:false or unread_only:false, this is a bounded preview, not a drain. The CLI swarmail inbox --session discovers identity and drains without mailbox arguments. Swarmail is a trusted local service; session identity selects inboxes and is not authentication.
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | Host tag, such as claude, codex, cursor, devin, opencode, grok or agy. | |
| limit | No | Positive page size; default 20, capped at 1000. | |
| mark_read | No | Default true. False previews without marking receipts read. | |
| t3_thread | No | Your T3 thread ID when known; includes older provider registrations in that thread. | |
| session_id | Yes | Your native host session ID from its shell variable or registration. | |
| unread_only | No | Default true. False gives a bounded page including read receipts. | |
| include_bodies | No | Include each body_md; default false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which only say readOnlyHint=false, idempotent=false), the description discloses the mutating side effect of the default mark_read:true, all four defaults, the drain semantics and termination condition, and the security model ('trusted local service; session identity selects inboxes and is not authentication'). This is unusually rich behavioral context for a fetch tool.
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 purpose is front-loaded in sentence one and subsequent sentences carry operational payload (defaults, drain algorithm, auth model). It is dense and a couple of clauses (e.g. the receipt project_key/agent_name note) are lower-value, but nearly every sentence earns its place given the absence of an output schema.
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?
With no output schema, the description compensates by sketching the return shape ('Each receipt includes project_key and agent_name for replies and acknowledgements'), the pagination/drain model, and the identity/auth assumptions. For a 7-param, session-scoped fetch tool this is complete enough to invoke 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?
Schema coverage is 100%, so the schema already documents each parameter, establishing a baseline of 3. The description meaningfully adds semantics: it states defaults inline, explains limit's drain-loop implication (fewer than limit returned = done, capped at 1000), and clarifies t3_thread is used 'when known' and that host/session_id must be machine-derived rather than guessed.
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 opening sentence states a specific verb (Return), resource (one newest-first page), and scope (registrations matching your host/session tag or T3 thread), which makes the tool's remit clear. It stops short of naming the sibling fetch_inbox to explicitly differentiate, but the session-scoped framing is 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?
It gives explicit when-to-use and how-to-use guidance: prefer machine-derived host/session_id and t3_thread 'when known', 'never guess from an agent name', and the drain loop ('stop when fewer than limit messages return... repeating only after a full page'). It also states the negative case: with mark_read:false or unread_only:false it is 'a bounded preview, not a drain'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_reservation_pathsA
Reserve repository-relative paths or globs so other agents know what you are editing. Returns {granted, conflicts}; grants include reservation ids and expiry times, while conflicts name the requested path and its holders. Conflicts do not fail the call, and nothing blocks the edit itself; the optional git guard refuses commits touching another agent's exclusive reservation. Reserving a path you already hold updates it. Extend with renew_file_reservations and release with release_file_reservations when done.
| Name | Required | Description | Default |
|---|---|---|---|
| paths | Yes | Repository-relative paths or globs. | |
| reason | No | Shown to agents whose reservation conflicts. | |
| exclusive | No | Default true. Shared reservations conflict only with exclusive ones. | |
| agent_name | Yes | Your registered agent name. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| ttl_seconds | No | Seconds, default 3600, at most 2592000 (30 days). | |
| idempotency_key | No | Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only provide coarse hints (readOnlyHint false, destructiveHint false); the description adds substantial behavior beyond them: the exact return shape {granted, conflicts}, that conflicts do NOT fail the call, that nothing blocks the edit itself, the git-guard behavior for commits, that re-reserving an already-held path updates it, and the expiry model. This is rich, non-obvious disclosure.
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-loads the core purpose in the first sentence, then layers return shape, conflict behavior, and lifecycle routing. Dense and largely waste-free, though the git-guard sentence is somewhat tangential to selection and could be trimmed.
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?
With no output schema, the description compensates by spelling out the return object ({granted, conflicts} and their contents) and the non-failing conflict semantics. Combined with the fully documented schema, an agent has everything needed to call and interpret the result.
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 all seven parameters, setting the baseline at 3. The description adds only marginal parameter-level meaning (re-reserving updates an existing hold) and does not clarify semantics like ttl_seconds or idempotency_key beyond what the schema states.
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?
States a specific verb (Reserve) and resource (repository-relative paths or globs) plus the intent ('so other agents know what you are editing'). It is clearly distinguishable from the sibling renew_file_reservations and release_file_reservations, which the description explicitly names.
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?
Names the lifecycle alternatives explicitly ('Extend with renew_file_reservations and release with release_file_reservations when done'), giving clear context for related actions. It does not state when not to reserve, so it stops short of full 5-level guidance, but routing to siblings is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_message_delivery_receiptARead-only
Return a message's persisted_at and recipients with kind, read_at, acknowledged, acknowledged_at and admission. Admission observations are historical; null admission means no snapshot was recorded. Storage/read/acknowledgement do not establish task acceptance. Null timestamps mean that recipient has not read or acknowledged it yet; they are not delivery errors. Use it as the sender to check an ack_required message; recipients use fetch_inbox. message_id must exist in this project or the call fails with NOT_FOUND.
| Name | Required | Description | Default |
|---|---|---|---|
| message_id | Yes | Message id. | |
| project_key | Yes | Absolute path of the repository's primary checkout. |
Output Schema
| Name | Required | Description |
|---|---|---|
| revision | Yes | |
| message_id | Yes | |
| project_id | Yes | |
| recipients | Yes | |
| persisted_at | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint/openWorldHint, but the description adds substantial behavioral context: admission observations are historical and null means no snapshot, null timestamps are not errors, and storage/read/ack do not imply task acceptance. It also discloses the NOT_FOUND failure mode, which annotations cannot express.
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-loads the return payload, then adds the semantic caveats and the role-based routing. Dense but every sentence carries distinct information; only minor tightening is possible.
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 an output schema exists, the description need not document returns, yet it still covers role applicability, null-value semantics, non-equivalence of ack and acceptance, and the failure condition — everything an agent needs to interpret results 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?
Schema coverage is 100%, so baseline is 3; the description goes beyond the schema by stating message_id 'must exist in this project or the call fails with NOT_FOUND,' adding an error constraint not captured in the property docs.
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?
States a specific verb (Return) and resource (a message's delivery receipt), and enumerates the fields returned (persisted_at, recipients, read_at, acknowledged, admission). It also distinguishes itself from the sibling fetch_inbox by naming which role uses which tool.
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 routes by role: 'Use it as the sender to check an ack_required message; recipients use fetch_inbox.' Names both the condition for use and the alternative tool, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
health_checkARead-only
Report whether the server and its database answer, with the database path. Call it when another tool fails with an INTERNAL error or no answer, to tell a down server from a bad request.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds behavior beyond that: it reports both server and database reachability and includes the database path, and frames the tool as a failure-triage probe.
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?
Two sentences, both load-bearing: the first states what is reported, the second states when to call it and why. Front-loaded with the outcome, no filler.
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, but the description explains what the result conveys (server and database answering, plus the database path). For a zero-parameter diagnostic tool with read-only annotations, nothing an agent needs to invoke it correctly 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 zero parameters, so the baseline is 4. There is no parameter semantics to convey, and the description correctly does not fabricate any.
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 states a specific verb (report) and resource (server and its database), plus the returned datum (the database path). No sibling tool in the list performs diagnostics, so it is trivially distinguished from the agent/messaging/reservation tools.
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?
It gives an explicit trigger (when another tool fails with an INTERNAL error or no answer) and the diagnostic intent (distinguish a down server from a bad request). An agent knows exactly when to reach for this versus retrying or fixing a request.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_agentsARead-only
Return an array of non-retired agents in a project, most recently active first, with program, model, task and session details, including t3_thread for a T3 link. Use it to find who to message; whois returns one agent. active_within_days filters recent activity, not whether a session is running. Metadata and activity do not prove current session or model liveness. limit caps this single result; there is no continuation cursor, so a full result may omit agents.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Positive page size; default 250, capped at 1000. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| active_within_days | No | Above 0; fractions allowed. Omit for every agent. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnlyHint and openWorldHint, and the description goes well beyond that: result ordering, the no-continuation-cursor limitation, and the warning that metadata/activity do not prove current session or model liveness. That liveness caveat is genuinely non-obvious behavioral context. It does not, however, discuss cost, scale limits of the underlying query, or failure modes.
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-loads the return shape before usage guidance, and every sentence carries information. It is dense with three distinct caveats in one paragraph, which is slightly heavy for a single-blurb description but not padded.
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?
With no output schema, the description carries the burden of describing returns and does so ('program, model, task and session details, including t3_thread'). Combined with the truncation and liveness caveats, an agent has everything needed to call and interpret it.
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%, so the baseline is 3, but the description adds real meaning: active_within_days 'filters recent activity, not whether a session is running' and limit 'caps this single result; there is no continuation cursor, so a full result may omit agents.' These clarify semantics the schema's terse parameter descriptions do not.
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?
States a specific verb and resource ('Return an array of non-retired agents in a project'), its ordering ('most recently active first'), and the returned fields. It also explicitly distinguishes itself from the sibling whois ('whois returns one agent'), so an agent can pick correctly without opening either schema.
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 an explicit use case ('find who to message') and names the competing alternative with its differing cardinality. It also warns that active_within_days filters recent activity rather than whether a session is running, which prevents a plausible misuse of the parameter as a liveness filter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
macro_start_sessionADestructive
Ensure the project, register an agent, optionally reserve paths, and return {project, agent, file_reservations, inbox}. The inbox contains the latest metadata without marking mail read; use fetch_inbox for bodies and unread-mail draining. Reuse the hook's name as agent_name or its session tag in task_description to avoid a second identity. Conflicting paths appear under file_reservations.conflicts; other paths are granted. If already registered and only checking mail, use fetch_inbox instead.
| Name | Required | Description | Default |
|---|---|---|---|
| model | Yes | Model id the session runs. | |
| program | Yes | Agent host, such as claude-code, codex or cursor. | |
| worktree | No | Absolute path of the checkout being edited, in this project. Omit to keep its recorded location. | |
| human_key | Yes | Absolute path of the repository's primary checkout. | |
| agent_name | No | Your existing name. Omit to get one generated. | |
| inbox_limit | No | Positive page size; default 10, capped at 1000. | |
| task_description | No | What you are working on. Keep the leading [host:session ...] tag the register hook gave you. | |
| file_reservation_paths | No | Repository-relative paths or globs to reserve. | |
| file_reservation_reason | No | Shown to agents whose reservation conflicts. | |
| file_reservation_ttl_seconds | No | Seconds, default 3600, at most 2592000 (30 days). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotency, and the description adds real behavioral context beyond them: the inbox does not mark mail read, conflicting paths surface under file_reservations.conflicts while other paths are granted. It does not explain the destructive/non-idempotent implications (e.g. what a re-run destroys), leaving a small gap.
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 the action list and return shape, then the mail/conflict caveats, then the alternative. Dense but each sentence carries information; no wasted preamble.
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?
For a 10-parameter macro with no output schema, the description compensates by enumerating the returned keys and clarifying conflict behavior, which is exactly what is missing structurally. It is nearly complete, though it could say more about the destructive/non-idempotent re-invocation semantics.
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%, so the baseline is 3, but the description adds genuine meaning beyond the schema by telling the agent to reuse the hook's agent_name or paste its session tag into task_description to avoid a duplicate identity. Other parameters are left to the schema.
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?
States a specific compound action (ensure project, register agent, optionally reserve paths, return {project, agent, file_reservations, inbox}) with a clear verb+resource framing. It explicitly distinguishes itself from the sibling fetch_inbox, so an agent can tell them apart without opening either schema.
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?
Names the alternative (fetch_inbox) and the exact conditions that select it: for message bodies, for unread-mail draining, and 'If already registered and only checking mail.' It also gives the positive routing hint about reusing the hook's name or session tag to avoid a second identity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_message_readA
Mark one received message read without acknowledging it, returning message_id, read and read_at. A repeat keeps the first read time but refreshes your agent's activity time. fetch_inbox already marks what it returns unless mark_read:false. When the message has ack_required, use acknowledge_message instead. Fails with NOT_FOUND unless you are a recipient.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_name | Yes | Your registered agent name. | |
| message_id | Yes | Message id. | |
| project_key | Yes | Absolute path of the repository's primary checkout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses behavior annotations do not cover: the returned fields, the repeat-call semantics (first read time retained, activity time refreshed), and the NOT_FOUND error condition. With readOnlyHint=false the mutation nature is already flagged, and the description enriches it rather than contradicting it.
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?
Five compact sentences, front-loaded with the core action and return value, followed by edge cases and the alternative tool. No filler and every sentence carries distinct 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?
With no output schema, the description compensates by naming the return fields (message_id, read, read_at), and it covers the error path and the sibling-tool boundary. An agent has everything needed to call it 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?
Schema description coverage is 100%, so all three parameters are documented in the schema. The description adds only implicit scope ('received message' implies you must be a recipient) and no format or syntax detail beyond that, so the baseline 3 applies.
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?
States a specific verb (mark read) and resource (one received message), plus the key differentiator that it does not acknowledge it. The agent can distinguish this from acknowledge_message and fetch_inbox without opening any schema.
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 routes: use acknowledge_message when ack_required is set, and notes fetch_inbox already marks messages unless mark_read:false. It also states the failure precondition (NOT_FOUND unless you are a recipient). This is exactly the when/when-not/alternative guidance expected.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_agentADestructive
Register or update an agent identity in a project, creating the project if needed. Omit name to get a generated adjective+noun name, unless task_description starts with a session tag an eligible or lifecycle-bound agent already has; then that agent is updated. Re-registering an existing name replaces its program, model and task and clears inactivity retirement. Authoritative lifecycle closure requires a verified reopen. If the register hook already told you your name, pass it as name, or start task_description with the session tag it gave you. To also reserve paths and read your inbox in one call, use macro_start_session.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Adjective+noun such as GreenLake. Omit to get one generated. | |
| model | Yes | Model id the session runs. | |
| program | Yes | Agent host, such as claude-code, codex or cursor. | |
| worktree | No | Absolute path of the checkout being edited, in this project. Omit to keep its recorded location. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| task_description | No | What you are working on. Keep the leading [host:session ...] tag the register hook gave you. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent, so the baseline is lower, yet the description goes well beyond them: it discloses project creation, generated naming, session-tag-driven update of an existing agent, that re-registration overwrites program/model/task and clears inactivity retirement, and that lifecycle closure needs a verified reopen. These are exactly the overwrite side effects an agent must know before calling.
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 main purpose is front-loaded, but the middle sentences stack convoluted conditionals ('unless task_description starts with a session tag an eligible or lifecycle-bound agent already has') and the hook/name guidance partly repeats the earlier session-tag rule, so some content does not fully earn its place.
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?
For a complex, non-idempotent mutation tool with no output schema, the description covers side effects, naming, re-registration, hook interplay and the alternative macro_start_session. It is largely complete, though it does not say what the call returns (e.g., the assigned name/identity) or what happens on failure.
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 baseline is 3. Most of the description's parameter guidance (omit name to get one generated, keep the leading session tag in task_description) restates what the schema already says, and the genuinely new cross-parameter rule (a session tag in task_description selecting an existing agent) is only lightly elaborated, so it adds limited meaning beyond the schema.
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 first sentence states a specific verb+resource with scope: 'Register or update an agent identity in a project, creating the project if needed.' It also names a sibling alternative (macro_start_session) and the conditions that distinguish it, so the agent can tell it apart without opening a schema.
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 concrete conditions: omit name for a generated name, re-register to replace program/model/task, and use macro_start_session to also reserve paths and read inbox in one call. It stops short of an explicit 'do not use when' case, but the alternative routing is clear enough for correct selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
release_file_reservationsADestructive
Release your active reservations when you finish work so other agents can reserve those paths. While work continues, use renew_file_reservations instead. Omit both filters to release all; supply paths or file_reservation_ids for a subset. Empty filters impose no restriction; two nonempty filters must both match. Returns how many were released; zero is not an error.
| Name | Required | Description | Default |
|---|---|---|---|
| paths | No | Only your reservations with exactly these patterns. | |
| agent_name | Yes | Your registered agent name. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| file_reservation_ids | No | Only your reservations with these ids. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent behavior, so the safety profile is covered. The description adds genuinely non-obvious behavior: the return value semantics ('returns how many were released') and that a zero count is not an error — a real anti-confusion signal. It does not restate that release is irreversible, but that is already implied by destructiveHint.
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 the action and the timing rule, then filter semantics, then return behavior. Every sentence carries distinct information; no repetition of the name or schema text.
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?
For a 4-param, no-output-schema mutation tool this is nearly complete: it covers when to call, how filters combine, and what the return count means. Minor gaps remain (nothing about reservation expiry or whether release is scoped per-project), but nothing that would cause a misinvocation.
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%, so baseline is 3, but the description goes further by defining filter interaction semantics the schema does not: empty filters impose no restriction, and two nonempty filters must both match. That clarifies the AND/OR behavior of paths vs file_reservation_ids, which the terse schema strings ('Only your reservations with exactly these patterns') do not.
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?
States a specific verb+resource (release active file reservations) and immediately frames the agent's situation ('when you finish work'). It is cleanly distinguished from the sibling renew_file_reservations, so no schema browsing is needed to tell them apart.
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 names the alternative and the condition that selects it: use renew_file_reservations while work continues, use this when work finishes. It also spells out the filter decision (omit both to release all, supply paths or ids for a subset), leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
renew_file_reservationsA
Extend your active reservations by extend_seconds past their current expiry; each call extends again. Omit paths and file_reservation_ids for all; empty filters impose no restriction, and two nonempty filters must both match. Returns {renewed, file_reservations} with old and new expiry times; no matches returns zero and an empty array. Expired reservations are not renewed; reserve them again with file_reservation_paths.
| Name | Required | Description | Default |
|---|---|---|---|
| paths | No | Only your reservations with exactly these patterns. | |
| agent_name | Yes | Your registered agent name. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| extend_seconds | No | Seconds, default 1800, at most 2592000 (30 days). | |
| file_reservation_ids | No | Only your reservations with these ids. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-readonly, non-idempotent, non-destructive, but the description adds real behavioral context: repeated calls stack extensions, expired reservations are silently skipped, no matches returns zero with an empty array, and the response shape {renewed, file_reservations} with old and new expiries. This goes well beyond what the annotations convey.
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?
Three sentences, front-loaded with the core action and scope before filtering rules and return/edge-case detail. Dense but nearly every clause carries needed information; the return-shape clause is arguably the most expendable but still useful.
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?
With no output schema present, the description compensates by describing the return payload and the zero-match case. Combined with 100% schema coverage and annotations, an agent has everything needed to invoke and interpret this tool.
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%, so the baseline is 3, but the description adds genuine meaning the schema does not: the interaction rule that two non-empty filters must both match and that omission or empty filters impose no restriction. It adds combinatorial semantics rather than just restating field docs.
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?
States a precise verb and resource ('extend your active reservations by extend_seconds past their current expiry') and immediately differentiates from siblings by naming file_reservation_paths for the expired case. An agent can distinguish this from file_reservation_paths and release_file_reservations without opening schemas.
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 covers the when-not case ('Expired reservations are not renewed; reserve them again with file_reservation_paths') and gives the alternative tool by name. It also clarifies filter-combination behavior (omit both for all, empty imposes no restriction, two nonempty must both match), leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reply_messageA
Reply in a message's thread, returning the stored message with reply_to. message_id selects the original in this project. Omit to to address its sender; cc and bcc are added only when supplied. The original's topic and importance are inherited, with a 'Re:' subject; importance can be overridden. ack_required defaults to false; set it explicitly to request acknowledgement of this reply. For retries within 7 days, reuse a nonempty idempotency_key with identical arguments. To start a new thread, use send_message. Send only when the recipient needs to act or know: a handoff, requested result, blocker or shared-resource change. Make clear to the human and receiver whether the message informs or requests work; for requests, name the action, repository and owner. Distinguish implementing source, installing an update and adding guidance. Write coordination messages in Markdown. Open with the action, decision or changed result. Add up to three short facts the receiver needs, then a Next action line naming the requested action or stating No action requested. Link supporting records on an Evidence line; omit that line when no record exists. Keep the requested action, authority, scope and essential holds inline. Put logs, metrics, hashes, execution details and authorization history in the linked records. When a decision depends on those details, ask the receiver to inspect the record. Preserve exact identifiers, paths and commands. Use spaces between words and numbers. Under T3 Code, refer to another agent by its thread link, title, not its registered name; use the name only if the user asks, no thread id is known or T3 fails. Elsewhere include its verified session title or repository beside its name; use this session for the current receiver only after matching session identity. For relayed authorization, preserve the source, exact selected action and target owner; a relayed bare approval such as "B" or "go" is ambiguous. Contact only still-dependent resource owners, sending release or cancellation before dropping waiting recipients. For resource coordination, name only the resource, finite phase boundary and receiver action; omit unrelated progress and errors. Use resource_notice for typed release/cancellation mail; it generates readable text and derives quiet or actionable delivery. Use one supported transport per recipient and purpose; uncertain delivery is not a reason to resend by another route. Keep routine progress in your own conversation; do not send courtesy acknowledgements or reply to thanks.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Recipients copied, visible to everyone. | |
| to | No | Recipients; default the original sender. | |
| bcc | No | Recipients the others do not see. | |
| body_md | Yes | The reply body, in Markdown. | |
| importance | No | low, normal, high or urgent. | |
| message_id | Yes | The message to reply to. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| sender_name | Yes | Your registered agent name. | |
| ack_required | No | Ask recipients to call acknowledge_message. | |
| subject_prefix | No | Default 'Re:'; not added twice. | |
| delivery_policy | No | checked (default) or durable. Both currently admit and store mail the same way. Neither bypasses closed T3 or unavailable bound sources. Unqualified standalone state remains unknown and is returned with warnings; storage does not transfer task ownership. | |
| idempotency_key | No | Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again. | |
| notification_policy | No | wake permits automatic inbox hints. quiet stores normal/low mail for inbox/search without waking the recipient; high/urgent importance or ack_required:true rejects. Omitted policy defaults to quiet only for normal/low, acknowledgement-free mail when every recipient has a valid registered T3 thread ID; otherwise wake. Ping probes keep wake by default. Replies use this same rule, not the original policy. Set wake explicitly for actionable handoffs, requested results and blockers. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cc | Yes | |
| id | Yes | |
| to | Yes | |
| bcc | Yes | |
| from | Yes | |
| topic | Yes | |
| body_md | Yes | |
| subject | Yes | |
| delivery | No | |
| reply_to | Yes | |
| revision | No | |
| sender_id | Yes | |
| thread_id | Yes | |
| created_ts | Yes | |
| importance | Yes | |
| project_id | Yes | |
| ack_required | Yes | |
| sender_location | Yes | |
| idempotent_replay | No | |
| notification_policy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations present (readOnly false, idempotent false, destructive false), the description adds real behavioral context: subject/topic/importance inheritance with a 'Re:' prefix, importance override, ack_required defaulting to false, and 7-day idempotency_key replay semantics. Some of this (idempotency, notification_policy, delivery_policy detail) duplicates the schema rather than extending it, which keeps it short of a 5.
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 core purpose is correctly front-loaded in the first two sentences, but the remaining ~400 words are largely prescriptive prose style rules (Markdown formatting, action-first openings, Evidence/Next action lines, T3 thread-link conventions, agent naming) that are tangential to invoking a reply tool. The volume buries the operational parameters and makes the definition hard to scan.
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?
For a 13-parameter mutation tool with an output schema, the definition covers selection, defaults, inheritance behavior, idempotency/retry, delivery and notification policy, and conflict error naming (IDEMPOTENCY_KEY_CONFLICT). Nothing an agent needs to call it correctly is missing; return-value detail is rightly delegated to the output schema.
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 baseline is 3 and the schema already documents each parameter. The description nonetheless adds defaults not obvious from the schema itself: 'to' omitted addresses the sender, cc/bcc added only when supplied, importance inherited unless overridden, and ack_required defaulting to false.
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 opening sentence gives a specific verb and resource ('Reply in a message's thread') plus the return behavior ('returning the stored message with reply_to') and the key selector ('message_id selects the original in this project'). It also explicitly distinguishes itself from send_message ('To start a new thread, use send_message'), so an agent can pick between the two siblings without opening either schema.
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 states when to use this tool versus alternatives in multiple places: send_message for new threads, resource_notice for typed release/cancellation mail, and explicit exclusions ('do not send courtesy acknowledgements or reply to thanks'). It also supplies the trigger conditions ('Send only when the recipient needs to act or know: a handoff, requested result, blocker or shared-resource change'), leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retire_agentA
At an agreed whole-session closeout or a whole-session completion with nothing remaining, record the closeout, release owned resources and finish required dependency notices, then retire your own registration in every project you joined. Before retiring another agent, confirm with its owning host that its session has ended; roster data or a ping timeout is insufficient. Retire an agent whose session has ended, so it no longer appears in list_agents and new messages to it fail. Its messages stay. unretire_agent reverses it, and so does the agent registering again or sending, reading mail or reserving files as itself. Lookups such as whois and list_agents do not.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_name | Yes | The agent to retire. | |
| project_key | Yes | Absolute path of the repository's primary checkout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare mutation/non-idempotent flags; the description adds substantive behavior: it releases owned resources, finishes dependency notices, retires the registration across every joined project, removes the agent from list_agents so new messages fail, preserves existing messages, and is reversible by unretire_agent or by the agent simply acting again. That is well beyond what the flags convey.
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?
Three dense sentences; the primary use case and the safety precondition come first, followed by effects and reversibility. Every sentence earns its place, though the run-on constructions could be trimmed for scanability.
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?
No output schema exists, yet the description covers the trigger condition, the prerequisite for retiring others, observable side effects, message preservation, and reversal semantics — everything needed to invoke this safely without ambiguity.
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 both agent_name and project_key are already documented, and the description adds no format or syntax detail for them. It does hint at multi-project scope ('in every project you joined'), which sits slightly awkwardly against the single required project_key, but this is not clarified further. Baseline 3 applies.
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?
States a specific verb and resource — 'retire your own registration' / 'retire an agent' — and immediately contrasts with the inverse tool unretire_agent. An agent can distinguish this from register_agent, whois, and list_agents without opening the schema.
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 act ('At an agreed whole-session closeout or a whole-session completion with nothing remaining') and adds a hard prerequisite for third-party retirement ('confirm with its owning host that its session has ended; roster data or a ping timeout is insufficient'). It also names unretire_agent as the reversal path, so alternatives are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_messagesARead-only
Search subjects and bodies across a project, returning {result, next_cursor?} without marking mail read. All query words must match; filters narrow those matches. Results rank by best match unless ranking:'recency'. Each excerpt has up to 512 Unicode code points and >>>matched text<<< markers; include_body_md adds full bodies. Keep query, filters and ranking unchanged when passing next_cursor as cursor; no next_cursor means the last page. Use fetch_inbox for your received unread mail, or summarize_thread for a thread's participants and recent messages.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Positive page size; default 20, capped at 1000. | |
| query | Yes | Words that must all appear; punctuation is ignored. | |
| since | No | ISO-8601 | |
| until | No | ISO-8601 | |
| cursor | No | The next_cursor of the previous page. | |
| ranking | No | 'recency' for newest first; omit for best match first. | |
| thread_id | No | Only messages in this thread. | |
| importance | No | Comma-separated levels to keep: low, normal, high, urgent. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| sender_name | No | Only messages from this agent. | |
| include_body_md | No | Include each full body; default false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses that mail is not marked read, that excerpts are capped at 512 code points with >>>matched text<<< markers, that all query words must match, and that pagination requires keeping query/filters/ranking unchanged. These are concrete operational details annotations cannot convey.
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?
Dense but front-loaded, leading with the verb, scope, and return shape before the behavioral and pagination rules. Every sentence conveys a distinct constraint or routing hint with no filler.
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?
For an 11-parameter search tool with no output schema, the description supplies the return structure ({result, next_cursor?}), pagination semantics, excerpt format, and alternative-tool routing. Nothing an agent needs to invoke it correctly 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?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: cursor reuse semantics ('keep query, filters and ranking unchanged when passing next_cursor'), include_body_md behavior, and ranking's effect on result order. It does not explain every parameter, but the ones it covers gain genuine context.
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?
States a specific verb and resource ('Search subjects and bodies across a project') plus the return shape and a behavioral guarantee (does not mark mail read). An agent can distinguish it from fetch_inbox and summarize_thread without opening a schema.
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 routes the agent: 'Use fetch_inbox for your received unread mail, or summarize_thread for a thread's participants and recent messages.' This names both alternatives and the conditions that select them, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageA
Send a Markdown message to named agents in the same project. An unregistered, retired or closed recipient fails the whole send with persisted:false and a reason. Bound source loss also rejects. Returns the stored message and delivery observations/warnings; unknown standalone state is not proof of death. Storage is not task acceptance. To answer a message, use reply_message, which keeps the thread and addresses the sender. Without idempotency_key, a retry sends another message; reuse a nonempty key with identical arguments within 7 days to replay its stored result instead; delivery observations on replay are historical. Alternatively provide resource_notice instead of subject/body_md: one recipient, a nonempty idempotency key, no free-text or delivery overrides. Released/cancelled notices generate readable text; next_action:none stays quiet, other allowed actions wake the dependent receiver. Claimed release is not admission or permission. Send only when the recipient needs to act or know: a handoff, requested result, blocker or shared-resource change. Make clear to the human and receiver whether the message informs or requests work; for requests, name the action, repository and owner. Distinguish implementing source, installing an update and adding guidance. Write coordination messages in Markdown. Open with the action, decision or changed result. Add up to three short facts the receiver needs, then a Next action line naming the requested action or stating No action requested. Link supporting records on an Evidence line; omit that line when no record exists. Keep the requested action, authority, scope and essential holds inline. Put logs, metrics, hashes, execution details and authorization history in the linked records. When a decision depends on those details, ask the receiver to inspect the record. Preserve exact identifiers, paths and commands. Use spaces between words and numbers. Under T3 Code, refer to another agent by its thread link, title, not its registered name; use the name only if the user asks, no thread id is known or T3 fails. Elsewhere include its verified session title or repository beside its name; use this session for the current receiver only after matching session identity. For relayed authorization, preserve the source, exact selected action and target owner; a relayed bare approval such as "B" or "go" is ambiguous. Contact only still-dependent resource owners, sending release or cancellation before dropping waiting recipients. For resource coordination, name only the resource, finite phase boundary and receiver action; omit unrelated progress and errors. Use resource_notice for typed release/cancellation mail; it generates readable text and derives quiet or actionable delivery. Use one supported transport per recipient and purpose; uncertain delivery is not a reason to resend by another route. Keep routine progress in your own conversation; do not send courtesy acknowledgements or reply to thanks.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Recipients copied, visible to everyone. | |
| to | Yes | Recipient agent names in this project. | |
| bcc | No | Recipients the others do not see. | |
| topic | No | A label fetch_inbox can filter on. | |
| body_md | No | The message body, in Markdown. | |
| subject | No | One line, shown in inbox listings. | |
| thread_id | No | A thread to join. reply_message sets it for you. | |
| importance | No | low, normal (default), high or urgent. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| sender_name | Yes | Your registered agent name. | |
| ack_required | No | Ask recipients to call acknowledge_message. | |
| delivery_policy | No | checked (default) or durable. Both currently admit and store mail the same way. Neither bypasses closed T3 or unavailable bound sources. Unqualified standalone state remains unknown and is returned with warnings; storage does not transfer task ownership. | |
| idempotency_key | No | Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again. | |
| resource_notice | No | Resource release or dependency cancellation. Exactly four fields: resource_id and phase_id are opaque ASCII identifiers (1..96 characters, starting with a letter/digit, then letters/digits/_.:-). released allows none or retry_admission; cancelled allows none or drop_dependency. Only request an action from a receiver with that dependency. Identifiers and receipts do not prove release or grant permission. | |
| notification_policy | No | wake permits automatic inbox hints. quiet stores normal/low mail for inbox/search without waking the recipient; high/urgent importance or ack_required:true rejects. Omitted policy defaults to quiet only for normal/low, acknowledgement-free mail when every recipient has a valid registered T3 thread ID; otherwise wake. Ping probes keep wake by default. Replies use this same rule, not the original policy. Set wake explicitly for actionable handoffs, requested results and blockers. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cc | Yes | |
| id | Yes | |
| to | Yes | |
| bcc | Yes | |
| from | Yes | |
| topic | Yes | |
| body_md | Yes | |
| subject | Yes | |
| delivery | No | |
| revision | No | |
| sender_id | Yes | |
| thread_id | Yes | |
| created_ts | Yes | |
| importance | Yes | |
| project_id | Yes | |
| ack_required | Yes | |
| sender_location | Yes | |
| idempotent_replay | No | |
| notification_policy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the coarse flags (non-read-only, non-destructive, not idempotent, closed-world). The description goes well beyond them, disclosing failure semantics (unregistered/retired/closed recipient fails the whole send with persisted:false and a reason), the 7-day idempotency replay window versus a duplicate-on-retry default, that replay observations are historical, that storage is not task acceptance, and the transport rule against re-routing on uncertain delivery. The idempotentHint:false annotation is not contradicted: it correctly describes the keyless default path that the description qualifies.
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?
It is a dense wall of prose that mixes invocation-critical facts with message-composition style coaching (open with the action, add up to three short facts, add a Next action line, put hashes and metrics in linked records, use spaces between words and numbers). Those craft instructions crowd out the routing and failure facts and are not front-loaded, so the piece is over-specified rather than concise even though individual sentences are grammatically tight.
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?
For a 15-parameter tool with nested oneOf branches, an output schema and annotations, the description covers the important gaps: mutating nature, recipient failure modes, idempotency, notice-mode constraints, threading and transport selection. The only shortfall is that the crucial branch conditions (resource_notice vs subject/body_md) are buried mid-paragraph, so completeness is achieved at the cost of discoverability.
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%, so the baseline is 3, but the description adds real meaning: the resource_notice branch is summarized as "one recipient, a nonempty idempotency key, no free-text or delivery overrides," the idempotency_key replay/conflict contract is restated operationally, and the descendance rule (only contact still-dependent resource owners, send release/cancellation before dropping waiting recipients) constrains how parameters should be used. It clarifies the oneOf branching that the schema only expresses structurally.
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?
Opens with a specific verb+resource+scope: "Send a Markdown message to named agents in the same project." It explicitly distinguishes itself from the nearest sibling (reply_message) and from resource_notice mail, so an agent can route correctly without opening either schema.
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 inclusion criteria ("Send only when the recipient needs to act or know: a handoff, requested result, blocker or shared-resource change") and exclusions ("do not send courtesy acknowledgements or reply to thanks"), plus a named alternative with its selecting condition ("To answer a message, use reply_message"). This is textbook when/when-not/alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_message_importanceADestructiveIdempotent
Change only your message's low/normal/high/urgent priority. Requires current expected_revision from inbox, history or sender receipt and a nonempty idempotency_key. Returns message_id, revision, importance and changed. A stale revision fails before a matching-value no-op. Edits affect metadata only: no new inbox notice or repeated instruction, and priority does not grant authority. Requires explicit server activation; identical retries replay before activation, lifecycle or revision checks.
| Name | Required | Description | Default |
|---|---|---|---|
| importance | Yes | low, normal, high or urgent. | |
| message_id | Yes | Message id. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| sender_name | Yes | Your registered agent name. | |
| idempotency_key | Yes | Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again. | |
| expected_revision | Yes | Current message revision, initially 0; inspect metadata again after a conflict. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Substantially exceeds what annotations convey: stale revisions fail before a matching-value no-op, edits are metadata-only (no new inbox notice or repeated instruction), priority grants no authority, and identical retries replay ahead of activation/lifecycle/revision checks. The idempotentHint and destructiveHint annotations are corroborated and elaborated rather than merely restated.
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?
Four sentences, front-loaded with purpose, then preconditions, return values, and failure/activation semantics. Dense but every clause carries operative information about revisions, idempotency, or activation; no filler.
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?
No output schema exists, yet the description enumerates the return fields (message_id, revision, importance, changed), covers the revision-conflict path, metadata-only effects, idempotent replay, and the server-activation requirement. An agent has everything needed to invoke and interpret it 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?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine semantics: it identifies where expected_revision must come from (inbox, history or sender receipt) and states the ordering rule that a stale revision fails before a matching-value no-op can occur, which the schema does not express.
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?
States a specific verb and resource with explicit scope: 'Change only your message's low/normal/high/urgent priority.' The word 'only' plus the enumerated values make clear this targets the importance field alone, distinguishing it from sibling mutators like reply_message or acknowledge_message.
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 clear preconditions: requires a current expected_revision sourced from inbox, history or sender receipt, plus a nonempty idempotency_key, and notes the tool requires explicit server activation. It does not name an alternative tool or state when-not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_threadARead-only
Return {thread_id, summary:{participants, total_messages}, messages} for you to summarize; this tool does not generate prose or mark mail read. Find thread_id with search_messages or fetch_inbox. per_thread_limit selects the newest messages with full bodies, returned oldest first. It defaults to 50 and caps at 1000, with no continuation cursor; total_messages counts the entire thread, even when messages is truncated. Use search_messages for text matching and fetch_inbox to drain unread mail. No matching thread returns zero messages.
| Name | Required | Description | Default |
|---|---|---|---|
| thread_id | Yes | The first message's id, or the thread_id its replies carry. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| per_thread_limit | No | Newest messages to return; positive page size, default 50, capped at 1000. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the readOnlyHint/openWorldHint annotations by disclosing that it does not generate prose and does not mark mail read, that there is no continuation cursor, and that total_messages counts the entire thread even when messages is truncated. These are exactly the behavioral traits an agent needs beyond structured hints.
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?
Return shape is front-loaded and every sentence carries distinct operational information (return format, non-actions, id sourcing, limit behavior, no-cursor, empty-thread case). It is dense but not padded, staying a single tight paragraph.
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?
No output schema exists, yet the description fully specifies the return shape, truncation semantics, and the zero-message case, so the agent has everything needed to call and interpret results 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?
Schema coverage is already 100%, so the baseline is 3, but the description adds real meaning for per_thread_limit: newest messages with full bodies, returned oldest first, default 50, cap 1000. The thread_id sourcing hint also aids interpretation beyond the schema text.
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?
States a specific verb+resource and, crucially, clarifies the tool returns structured data {thread_id, summary:{...}, messages} rather than generating summary prose. It distinguishes itself from search_messages and fetch_inbox by scope, so an agent can choose without opening sibling schemas.
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 routes the agent: find thread_id via search_messages or fetch_inbox, use search_messages for text matching, fetch_inbox to drain unread mail. Names both alternatives and the condition that selects each, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unretire_agentA
Bring a retired agent back into list_agents so it can receive messages again; earlier messages stay unchanged. Returns {agent_name, retired:false}. Calling on an already active agent also succeeds and refreshes its activity time, as every revival does. Registering, sending, reading mail or reserving files revives the caller automatically; use this to revive another agent. An unknown name fails with NOT_FOUND.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_name | Yes | The retired agent to bring back. | |
| project_key | Yes | Absolute path of the repository's primary checkout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false) by disclosing that earlier messages are unchanged, that the return is {agent_name, retired:false}, that the call refreshes activity time on every revival, and that an unknown name fails with NOT_FOUND. It does not mention permission or auth requirements, which keeps it short of a 5.
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?
Purpose is front-loaded in the first clause, followed by return shape, idempotent-like behavior, and the auto-revival alternative. Every sentence carries information, though the enumeration of auto-revival triggers makes it slightly denser than necessary.
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?
With no output schema, the description compensates by specifying the return object and the failure mode, and it resolves the sibling ambiguity against retire_agent and list_agents. Nothing an agent needs in order to invoke it correctly 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?
Schema description coverage is 100%, so both parameters are already documented in the schema; the baseline of 3 applies. The description adds the NOT_FOUND behavior for an unknown agent_name, but says nothing about project_key and adds no syntax or format detail.
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?
States a specific verb+resource ('bring a retired agent back into list_agents') plus the resulting effect ('can receive messages again'), which cleanly separates it from the sibling retire_agent. An agent can identify the operation without opening the schema.
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 identifies the alternative path: registering, sending, reading mail, or reserving files revives the caller automatically, so this tool is for reviving ANOTHER agent. It also states the already-active case succeeds, removing ambiguity about whether to guard the call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whoisARead-only
Return one agent's profile: program, model, task description, T3 thread (t3_thread, null outside T3) and first and last activity times. An unknown name fails with NOT_FOUND, naming recently active agents. Profile metadata and activity do not prove the session or model is currently running. To see every agent in a project, use list_agents.
| Name | Required | Description | Default |
|---|---|---|---|
| agent_name | Yes | The agent to look up. | |
| project_key | Yes | Absolute path of the repository's primary checkout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. Beyond that, the description discloses real behavioral traits: unknown names raise NOT_FOUND and surface recently active agents as a hint, t3_thread is null outside T3, and profile activity does not mean the session is live. That last caveat is a genuinely useful warning not derivable from 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?
Three tight sentences, front-loaded with what the tool returns, followed by error behavior and the sibling pointer. The mid-sentence field enumeration is dense but each clause carries information; nothing is filler.
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?
With no output schema, the description must carry the return shape, and it does by listing every returned field plus the null semantics of t3_thread. Error behavior, the staleness caveat, and the sibling alternative are all present, so an agent has what it needs to call and interpret this 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?
Schema description coverage is 100% and both parameters are documented in-schema, so the baseline is 3. The description adds only indirect semantics via the NOT_FOUND behavior tied to agent_name; it does not explain the expected format for agent_name or project_key beyond the schema.
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?
Specific verb (return) plus singular resource (one agent's profile), and it enumerates the returned fields (program, model, task description, t3_thread, activity times). It explicitly distinguishes itself from list_agents, so an agent can route between the two without opening a schema.
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?
It names the alternative for the plural case ('To see every agent in a project, use list_agents'), which is explicit routing guidance. It does not spell out exclusions or preconditions (e.g. when an agent lookup is unnecessary), so it falls short of the full when/when-not treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
withdraw_messageADestructiveIdempotent
Withdraw your message from recipients whose delivery has not been read, acknowledged or withdrawn. Returns message_id, revision and per-recipient withdrawn/already_withdrawn/too_late results. Omit recipients for all deliveries; an explicit subset must be nonempty and valid. Retains content and audit history. Previews and injected context cannot be recalled. Requires explicit server activation after all readers are qualified. A nonempty idempotency_key is required; identical retries replay even when execution is disabled or the sender closes.
| Name | Required | Description | Default |
|---|---|---|---|
| message_id | Yes | Message id. | |
| recipients | No | Optional nonempty subset of this message's recipient names; omit for all. | |
| project_key | Yes | Absolute path of the repository's primary checkout. | |
| sender_name | Yes | Your registered agent name. | |
| idempotency_key | Yes | Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive and idempotent, but the description adds substantial context beyond them: content and audit history are retained, server activation after reader qualification is required, previews/injected context are not recallable, and idempotency-key replay behavior (including replay while execution is disabled or sender closed). This is a genuinely richer behavioral profile than the annotations alone.
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 the operation and its scope, then layered with return values, recipient rules, retention guarantees, and activation/idempotency constraints. Every sentence carries new information with no filler.
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?
No output schema exists, yet the description names the return fields (message_id, revision, per-recipient withdrawn/already_withdrawn/too_late results), states retention behavior, and covers the activation prerequisite and idempotency contract. An agent has everything needed to invoke it 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?
Schema description coverage is 100%, so the baseline is 3 and the schema already documents all five parameters. The description nonetheless adds meaning beyond it: the recipients parameter's subset-validity and omit-for-all semantics, and the replay/conflict behavior of the idempotency key, are reinforced in context rather than left purely to the schema.
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?
States a specific verb (withdraw) applied to a specific resource (your message) with an explicit scope limit (recipients whose delivery has not been read, acknowledged or withdrawn). This clearly separates it from siblings like acknowledge_message, mark_message_read and send_message without needing to open any schema.
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 clear applicability conditions: it only affects unread/unacknowledged/unwithdrawn deliveries, recipients may be omitted for all or given as a nonempty valid subset, and previews/injected context cannot be recalled. It doesn't explicitly name an alternative tool, so it falls short of a full 5, but the context for use is unambiguous.
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.
6 tool updates
v0.3.1- Changed
file_reservation_paths1 field changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."
- Changed
get_message_delivery_receipt1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "properties": { + "message_id": { + "type": "integer" + }, + "persisted_at": { + "type": [ + "string", + "null" + ] + }, + "project_id": { + "type": "integer" + }, + "recipients": { + "items": { + "additionalProperties": false, + "properties": { + "acknowledged": { + "type": "boolean" + }, + "acknowledged_at": { + "type": [ + "string", + "null" + ] + }, + "admission": { + "additionalProperties": false, + "properties": { + "availability": { + "enum": [ + "eligible", + "unavailable", + "unknown" + ] + }, + "historical": { + "type": "boolean" + }, + "lifecycle": { + "type": "string" + }, + "observed_at": { + "type": "string" + }, + "process": { + "enum": [ + "present", + "unknown" + ] + }, + "reason": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "reported_end_at": { + "type": "string" + }, + "source": { + "enum": [ + "t3", + "registry", + "registration" + ] + }, + "wake": { + "const": "unknown" + } + }, + "required": [ + "recipient", + "availability", + "lifecycle", + "process", + "wake", + "source", + "reason", + "observed_at" + ], + "type": [ + "object", + "null" + ] + }, + "kind": { + "enum": [ + "to", + "cc", + "bcc" + ] + }, + "read_at": { + "type": [ + "string", + "null" + ] + }, + "recipient": { + "type": "string" + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "recipient", + "kind", + "read_at", + "acknowledged", + "acknowledged_at", + "withdrawn_at", + "admission" + ], + "type": "object" + }, + "type": "array" + }, + "revision": { + "type": "integer" + } + }, + "required": [ + "message_id", + "project_id", + "persisted_at", + "revision", + "recipients" + ], + "type": "object" +}
- Changed
reply_message3 fields changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again." - added
Input schema / properties / notification_policyAdded value: +{ + "description": "wake permits automatic inbox hints. quiet stores normal/low mail for inbox/search without waking the recipient; high/urgent importance or ack_required:true rejects. Omitted policy defaults to quiet only for normal/low, acknowledgement-free mail when every recipient has a valid registered T3 thread ID; otherwise wake. Ping probes keep wake by default. Replies use this same rule, not the original policy. Set wake explicitly for actionable handoffs, requested results and blockers.", + "enum": [ + "wake", + "quiet" + ], + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "delivery", + "revision", + "notification_policy" + ] + }, + { + "properties": { + "idempotent_replay": { + "const": true + } + }, + "required": [ + "idempotent_replay" + ] + } + ], + "properties": { + "ack_required": { + "type": "boolean" + }, + "bcc": { + "items": { + "type": "string" + }, + "type": "array" + }, + "body_md": { + "type": "string" + }, + "cc": { + "items": { + "type": "string" + }, + "type": "array" + }, + "created_ts": { + "type": [ + "string", + "null" + ] + }, + "delivery": { + "additionalProperties": false, + "properties": { + "admission_checked_at": { + "type": "string" + }, + "historical": { + "type": "boolean" + }, + "persisted": { + "type": "boolean" + }, + "recipients": { + "items": { + "additionalProperties": false, + "properties": { + "availability": { + "enum": [ + "eligible", + "unavailable", + "unknown" + ] + }, + "historical": { + "type": "boolean" + }, + "lifecycle": { + "type": "string" + }, + "observed_at": { + "type": "string" + }, + "process": { + "enum": [ + "present", + "unknown" + ] + }, + "reason": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "reported_end_at": { + "type": "string" + }, + "source": { + "enum": [ + "t3", + "registry", + "registration" + ] + }, + "wake": { + "const": "unknown" + } + }, + "required": [ + "recipient", + "availability", + "lifecycle", + "process", + "wake", + "source", + "reason", + "observed_at" + ], + "type": "object" + }, + "type": "array" + }, + "warnings": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "persisted", + "admission_checked_at", + "historical", + "recipients", + "warnings" + ], + "type": "object" + }, + "from": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "idempotent_replay": { + "type": "boolean" + }, + "importance": { + "type": "string" + }, + "notification_policy": { + "enum": [ + "wake", + "quiet" + ] + }, + "project_id": { + "type": "integer" + }, + "reply_to": { + "type": "integer" + }, + "revision": { + "type": "integer" + }, + "sender_id": { + "type": "integer" + }, + "sender_location": { + "additionalProperties": false, + "properties": { + "branch": { + "type": [ + "string", + "null" + ] + }, + "repo": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "worktree": { + "type": "string" + } + }, + "required": [ + "repo", + "worktree", + "branch", + "title" + ], + "type": [ + "object", + "null" + ] + }, + "subject": { + "type": "string" + }, + "thread_id": { + "type": [ + "string", + "null" + ] + }, + "to": { + "items": { + "type": "string" + }, + "type": "array" + }, + "topic": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "project_id", + "sender_id", + "thread_id", + "topic", + "subject", + "body_md", + "importance", + "ack_required", + "created_ts", + "from", + "sender_location", + "to", + "cc", + "bcc", + "reply_to" + ], + "type": "object" +}
- Changed
send_message6 fields changed- added
Input schema / oneOfAdded value: +[ + { + "not": { + "required": [ + "resource_notice" + ] + }, + "required": [ + "subject", + "body_md" + ] + }, + { + "additionalProperties": false, + "properties": { + "idempotency_key": { + "pattern": "\\S", + "type": "string" + }, + "project_key": {}, + "resource_notice": {}, + "sender_name": {}, + "thread_id": {}, + "to": { + "items": { + "pattern": "\\S", + "type": "string" + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "resource_notice", + "idempotency_key" + ] + } +] - changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again." - added
Input schema / properties / notification_policyAdded value: +{ + "description": "wake permits automatic inbox hints. quiet stores normal/low mail for inbox/search without waking the recipient; high/urgent importance or ack_required:true rejects. Omitted policy defaults to quiet only for normal/low, acknowledgement-free mail when every recipient has a valid registered T3 thread ID; otherwise wake. Ping probes keep wake by default. Replies use this same rule, not the original policy. Set wake explicitly for actionable handoffs, requested results and blockers.", + "enum": [ + "wake", + "quiet" + ], + "type": "string" +} - added
Input schema / properties / resource_noticeAdded value: +{ + "additionalProperties": false, + "description": "Resource release or dependency cancellation. Exactly four fields: resource_id and phase_id are opaque ASCII identifiers (1..96 characters, starting with a letter/digit, then letters/digits/_.:-). released allows none or retry_admission; cancelled allows none or drop_dependency. Only request an action from a receiver with that dependency. Identifiers and receipts do not prove release or grant permission.", + "oneOf": [ + { + "properties": { + "next_action": { + "enum": [ + "none", + "retry_admission" + ] + }, + "state": { + "const": "released" + } + } + }, + { + "properties": { + "next_action": { + "enum": [ + "none", + "drop_dependency" + ] + }, + "state": { + "const": "cancelled" + } + } + } + ], + "properties": { + "next_action": { + "enum": [ + "none", + "retry_admission", + "drop_dependency" + ], + "type": "string" + }, + "phase_id": { + "maxLength": 96, + "minLength": 1, + "not": { + "pattern": "\\s" + }, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$", + "type": "string" + }, + "resource_id": { + "maxLength": 96, + "minLength": 1, + "not": { + "pattern": "\\s" + }, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$", + "type": "string" + }, + "state": { + "enum": [ + "released", + "cancelled" + ], + "type": "string" + } + }, + "required": [ + "resource_id", + "phase_id", + "state", + "next_action" + ], + "type": "object" +} - changed
Input schema / requiredPrevious value: -[ - "project_key", - "sender_name", - "to", - "subject", - "body_md" -]New value: +[ + "project_key", + "sender_name", + "to" +] - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "delivery", + "revision", + "notification_policy" + ] + }, + { + "properties": { + "idempotent_replay": { + "const": true + } + }, + "required": [ + "idempotent_replay" + ] + } + ], + "properties": { + "ack_required": { + "type": "boolean" + }, + "bcc": { + "items": { + "type": "string" + }, + "type": "array" + }, + "body_md": { + "type": "string" + }, + "cc": { + "items": { + "type": "string" + }, + "type": "array" + }, + "created_ts": { + "type": [ + "string", + "null" + ] + }, + "delivery": { + "additionalProperties": false, + "properties": { + "admission_checked_at": { + "type": "string" + }, + "historical": { + "type": "boolean" + }, + "persisted": { + "type": "boolean" + }, + "recipients": { + "items": { + "additionalProperties": false, + "properties": { + "availability": { + "enum": [ + "eligible", + "unavailable", + "unknown" + ] + }, + "historical": { + "type": "boolean" + }, + "lifecycle": { + "type": "string" + }, + "observed_at": { + "type": "string" + }, + "process": { + "enum": [ + "present", + "unknown" + ] + }, + "reason": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "reported_end_at": { + "type": "string" + }, + "source": { + "enum": [ + "t3", + "registry", + "registration" + ] + }, + "wake": { + "const": "unknown" + } + }, + "required": [ + "recipient", + "availability", + "lifecycle", + "process", + "wake", + "source", + "reason", + "observed_at" + ], + "type": "object" + }, + "type": "array" + }, + "warnings": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "persisted", + "admission_checked_at", + "historical", + "recipients", + "warnings" + ], + "type": "object" + }, + "from": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "idempotent_replay": { + "type": "boolean" + }, + "importance": { + "type": "string" + }, + "notification_policy": { + "enum": [ + "wake", + "quiet" + ] + }, + "project_id": { + "type": "integer" + }, + "revision": { + "type": "integer" + }, + "sender_id": { + "type": "integer" + }, + "sender_location": { + "additionalProperties": false, + "properties": { + "branch": { + "type": [ + "string", + "null" + ] + }, + "repo": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "worktree": { + "type": "string" + } + }, + "required": [ + "repo", + "worktree", + "branch", + "title" + ], + "type": [ + "object", + "null" + ] + }, + "subject": { + "type": "string" + }, + "thread_id": { + "type": [ + "string", + "null" + ] + }, + "to": { + "items": { + "type": "string" + }, + "type": "array" + }, + "topic": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "project_id", + "sender_id", + "thread_id", + "topic", + "subject", + "body_md", + "importance", + "ack_required", + "created_ts", + "from", + "sender_location", + "to", + "cc", + "bcc" + ], + "type": "object" +}
- Changed
set_message_importance1 field changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."
- Changed
withdraw_message1 field changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Cleanup runs at server startup and hourly, removing keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."
5 tool updates
v0.3.0- Added
fetch_session_inbox - Changed
reply_message1 field changed- added
Input schema / properties / delivery_policyAdded value: +{ + "description": "checked (default) or durable. Both currently admit and store mail the same way. Neither bypasses closed T3 or unavailable bound sources. Unqualified standalone state remains unknown and is returned with warnings; storage does not transfer task ownership.", + "enum": [ + "checked", + "durable" + ], + "type": "string" +}
- Changed
send_message1 field changed- added
Input schema / properties / delivery_policyAdded value: +{ + "description": "checked (default) or durable. Both currently admit and store mail the same way. Neither bypasses closed T3 or unavailable bound sources. Unqualified standalone state remains unknown and is returned with warnings; storage does not transfer task ownership.", + "enum": [ + "checked", + "durable" + ], + "type": "string" +}
- Added
set_message_importance - Added
withdraw_message
3 tool updates
v0.2.5- Changed
file_reservation_paths1 field changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Any string. A retry with the same key and arguments returns the first result."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."
- Changed
reply_message1 field changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Any string. A retry with the same key and arguments returns the first result."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."
- Changed
send_message1 field changed- changed
Input schema / properties / idempotency_key / descriptionPrevious value: -"Any string. A retry with the same key and arguments returns the first result."New value: +"Nonempty key for this tool and agent. Identical arguments replay with idempotent_replay:true; different arguments fail with IDEMPOTENCY_KEY_CONFLICT. Hourly cleanup removes keys older than 7 days. Retries can replay until removal; afterward a retry may perform the operation again."
2 tool updates
v0.2.4- Changed
macro_start_session1 field changed- added
Input schema / properties / worktreeAdded value: +{ + "description": "Absolute path of the checkout being edited, in this project. Omit to keep its recorded location.", + "type": "string" +}
- Changed
register_agent1 field changed- added
Input schema / properties / worktreeAdded value: +{ + "description": "Absolute path of the checkout being edited, in this project. Omit to keep its recorded location.", + "type": "string" +}
12 tool updates
v0.2.2- Changed
fetch_inbox4 fields changed- added
Input schema / properties / include_bodies / descriptionAdded value: +"Include each body_md; default false." - added
Input schema / properties / mark_read / descriptionAdded value: +"Default true." - added
Input schema / properties / topic / descriptionAdded value: +"Only messages with this topic." - added
Input schema / properties / unread_only / descriptionAdded value: +"Only messages you have not read."
- Changed
file_reservation_paths4 fields changed- changed
Input schema / properties / exclusive / descriptionPrevious value: -"Default true."New value: +"Default true. Shared reservations conflict only with exclusive ones." - added
Input schema / properties / idempotency_key / descriptionAdded value: +"Any string. A retry with the same key and arguments returns the first result." - added
Input schema / properties / paths / descriptionAdded value: +"Repository-relative paths or globs." - added
Input schema / properties / reason / descriptionAdded value: +"Shown to agents whose reservation conflicts."
- Changed
macro_start_session6 fields changed- added
Input schema / properties / agent_name / descriptionAdded value: +"Your existing name. Omit to get one generated." - added
Input schema / properties / file_reservation_paths / descriptionAdded value: +"Repository-relative paths or globs to reserve." - added
Input schema / properties / file_reservation_reason / descriptionAdded value: +"Shown to agents whose reservation conflicts." - added
Input schema / properties / model / descriptionAdded value: +"Model id the session runs." - added
Input schema / properties / program / descriptionAdded value: +"Agent host, such as claude-code, codex or cursor." - added
Input schema / properties / task_description / descriptionAdded value: +"What you are working on. Keep the leading [host:session ...] tag the register hook gave you."
- Changed
register_agent4 fields changed- added
Input schema / properties / model / descriptionAdded value: +"Model id the session runs." - added
Input schema / properties / name / descriptionAdded value: +"Adjective+noun such as GreenLake. Omit to get one generated." - added
Input schema / properties / program / descriptionAdded value: +"Agent host, such as claude-code, codex or cursor." - added
Input schema / properties / task_description / descriptionAdded value: +"What you are working on. Keep the leading [host:session ...] tag the register hook gave you."
- Changed
release_file_reservations2 fields changed- added
Input schema / properties / file_reservation_ids / descriptionAdded value: +"Only your reservations with these ids." - added
Input schema / properties / paths / descriptionAdded value: +"Only your reservations with exactly these patterns."
- Changed
renew_file_reservations2 fields changed- added
Input schema / properties / file_reservation_ids / descriptionAdded value: +"Only your reservations with these ids." - added
Input schema / properties / paths / descriptionAdded value: +"Only your reservations with exactly these patterns."
- Changed
reply_message9 fields changed- added
Input schema / properties / ack_required / descriptionAdded value: +"Ask recipients to call acknowledge_message." - added
Input schema / properties / bcc / descriptionAdded value: +"Recipients the others do not see." - added
Input schema / properties / body_md / descriptionAdded value: +"The reply body, in Markdown." - added
Input schema / properties / cc / descriptionAdded value: +"Recipients copied, visible to everyone." - added
Input schema / properties / idempotency_key / descriptionAdded value: +"Any string. A retry with the same key and arguments returns the first result." - added
Input schema / properties / importance / descriptionAdded value: +"low, normal, high or urgent." - changed
Input schema / properties / message_id / descriptionPrevious value: -"Message id."New value: +"The message to reply to." - added
Input schema / properties / subject_prefix / descriptionAdded value: +"Default 'Re:'; not added twice." - added
Input schema / properties / to / descriptionAdded value: +"Recipients; default the original sender."
- Changed
retire_agent1 field changed- added
Input schema / properties / agent_name / descriptionAdded value: +"The agent to retire."
- Changed
search_messages7 fields changed- added
Input schema / properties / cursor / descriptionAdded value: +"The next_cursor of the previous page." - added
Input schema / properties / importance / descriptionAdded value: +"Comma-separated levels to keep: low, normal, high, urgent." - added
Input schema / properties / include_body_md / descriptionAdded value: +"Include each full body; default false." - added
Input schema / properties / query / descriptionAdded value: +"Words that must all appear; punctuation is ignored." - added
Input schema / properties / ranking / descriptionAdded value: +"'recency' for newest first; omit for best match first." - added
Input schema / properties / sender_name / descriptionAdded value: +"Only messages from this agent." - added
Input schema / properties / thread_id / descriptionAdded value: +"Only messages in this thread."
- Changed
send_message10 fields changed- added
Input schema / properties / ack_required / descriptionAdded value: +"Ask recipients to call acknowledge_message." - added
Input schema / properties / bcc / descriptionAdded value: +"Recipients the others do not see." - added
Input schema / properties / body_md / descriptionAdded value: +"The message body, in Markdown." - added
Input schema / properties / cc / descriptionAdded value: +"Recipients copied, visible to everyone." - added
Input schema / properties / idempotency_key / descriptionAdded value: +"Any string. A retry with the same key and arguments returns the first result." - changed
Input schema / properties / importance / descriptionPrevious value: -"low, normal, high or urgent"New value: +"low, normal (default), high or urgent." - added
Input schema / properties / subject / descriptionAdded value: +"One line, shown in inbox listings." - added
Input schema / properties / thread_id / descriptionAdded value: +"A thread to join. reply_message sets it for you." - added
Input schema / properties / to / descriptionAdded value: +"Recipient agent names in this project." - added
Input schema / properties / topic / descriptionAdded value: +"A label fetch_inbox can filter on."
- Changed
unretire_agent1 field changed- added
Input schema / properties / agent_name / descriptionAdded value: +"The retired agent to bring back."
- Changed
whois1 field changed- added
Input schema / properties / agent_name / descriptionAdded value: +"The agent to look up."
19 tool updates
v0.2.1- First observed
acknowledge_message - First observed
ensure_project - First observed
fetch_inbox - First observed
file_reservation_paths - First observed
get_message_delivery_receipt - First observed
health_check - First observed
list_agents - First observed
macro_start_session - First observed
mark_message_read - First observed
register_agent - First observed
release_file_reservations - First observed
renew_file_reservations - First observed
reply_message - First observed
retire_agent - First observed
search_messages - First observed
send_message - First observed
summarize_thread - First observed
unretire_agent - First observed
whois
TDQS
Scored across 22 tools
Most tools target clearly distinct resources and actions (send vs reply vs search, reserve vs renew vs release, register vs retire). The main overlaps are fetch_inbox vs fetch_session_inbox and mark_message_read vs acknowledge_message (and fetch_inbox's implicit read-marking), but the descriptions explicitly explain their boundaries, so misselection is unlikely.
Nearly all tools follow a predictable snake_case verb_noun pattern (send_message, reply_message, register_agent, withdraw_message, file_reservation_paths, release_file_reservations). Minor deviations like whois and health_check are recognizable conventions rather than inconsistencies.
22 tools sits at the heavy end, but the domain genuinely spans project setup, agent lifecycle, mail, delivery receipts, and file reservations, so most tools earn their place. A few (fetch_session_inbox vs fetch_inbox) could arguably be merged.
The surface covers project creation, agent registration/retirement/revival, full message lifecycle (send, reply, search, summarize, read, ack, withdraw, importance, receipts), and reservation lifecycle (reserve, renew, release), plus health check. No obvious blocking gaps, though project listing/teardown coverage is thin.
Maintenance
Related MCP Connectors
Shared memory and mail for your AI agents. Verified with Claude Code; other MCP clients in testing.
Email inboxes for AI agents: send, receive, reply, search, and manage threaded email over MCP.
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Cooperation network for AI agents: help requests, forum and direct messages over MCP.
Related MCP Servers
- AlicenseBqualityAmaintenanceA coordination layer for coding agents that provides memorable identities, inbox/outbox messaging, searchable message history, and file lease management to prevent conflicts. Uses Git for human-auditable artifacts and SQLite for fast queries, enabling multiple agents to collaborate across projects without stepping on each other.412,222MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-capable agents running in separate consoles to exchange direct and broadcast messages through a blocking receive tool that releases instantly when mail arrives, so delivery feels push-like rather than polled. It also provides a live browser dashboard showing message flow, presence and per-agent profiles, plus CLI and HTTP endpoints for sending, tailing and replaying the log.MIT
- AlicenseAqualityBmaintenanceLets separate coding-agent sessions coordinate through a shared, role-addressed mailbox instead of a human relaying every message, over a single local SQLite file or a hosted server with many isolated channels. Messages can be sent as tracked obligations that stay open until one side resolves and the other confirms, alongside threads, full-text search, work statuses, and an append-only versioned pin system where protected changes require recorded agreement from every declared role.41MIT
- AlicenseNot gradedqualityBmaintenanceProvides a mail-like coordination layer for coding agents, enabling them to register identities, exchange messages through inbox/outbox, search threaded history, and declare advisory file reservations to prevent conflicts.MIT