The mailbox delivers
Handing a task to another agent used to record it and nothing more: nothing started that agent, and nothing told it. create_task now tries to start the assignee in the background and returns immediately.
- The database that prompted this release had 77 messages sent and 77 unread, claim_task never once called, and the single mailbox task ever created still pending hours later. The reaper only sweeps running tasks, so it could not see that the assignment was there — it simply sat unread while whoever made it waited for work that was never going to begin.
- create_task now tries to start the assignee in the background and hands your turn straight back. Where the launch succeeds the other agent gets going, and you collect the outcome with check_task whenever you are ready; where it does not, the result says whether the task was queued for a claim or failed outright.
- Delivery runs under dispatch’s policy, by the same code — the same denylists in the same order, the trust boundary, the argv baseline, the wait ceiling and the network label. Work cannot reach an agent on easier terms by being assigned instead of dispatched.
- The result says which actually happened. delivery: "dispatched" means the launch was attempted and the task is not waiting for a claim; read status to see whether it is running, completed or failed, and it carries the network enforcement that was applied — which matters most for Antigravity, where “no network” cannot be enforced at all and the result now says so. delivery: "queued" means Cempala started nothing, and names why: unassigned, not_requested, agent_not_dispatchable, cli_unavailable, self_assigned, nested_delivery, start_failed, or claimed_elsewhere.
- Delivery goes one hop. An agent working a delivered task can still create tasks, but those are recorded rather than started. One handoff is a handoff; a chain that delivers every time it is delivered to spends real provider quota without bound.
- The row is the unit of work. Because delivery runs on the task’s own row, that row is settled from the agent’s output whether or not the agent ever calls complete_task — and if it does call it, its own verdict stands. Every reconciliation path only writes a row still marked running, so the first writer to reach a terminal state owns it. The same guard means a claim_task that lands first wins, and nothing is spawned over it.
- Work assigned to someone Cempala cannot start is still surfaced. Any MCP client can join the mailbox, but only the four mapped CLIs can be spawned, and nothing in MCP lets a server interrupt an agent that is not currently asking it something. So the reply to a call the agent did make now carries an inbox: its unread message count, the true number of tasks waiting for it, and up to ten of them described well enough to act on — id, description, folder, and who asked. It rides on every tool, not just the mailbox ones, on any call the agent identified itself on; it is absent when there is nothing waiting, so its presence is the signal.
- Policy is now decided before the task row is written, and the row is inserted already carrying its verdict. A pending row is claimable the instant it exists, so recording first and judging afterwards published work whose denial had not been decided yet. Judging first removes that window rather than guarding it. An allowed verdict hands back a capability bound to the exact task, prompt, canonical folder and resolved command line it judged, so approved work cannot be swapped for something else after the fact.
- Delivery was verified end to end against all four supported CLIs on a real machine: each picks up an assigned task and completes it with nobody claiming it by hand, each reporting the network enforcement its own argv actually imposes. Alongside that, 386 unit tests, the installer and uninstaller suites, six-target builds, and smoke tests on matching hardware. CI also moved off the retired Node 20 runtime.