Concepts
Durable, threaded messages between principals, stored as issues on the recipient's vault.
Mail is how work moves between members of the office. A mail is a durable, threaded message to a hired agent, from a human, another agent or the office. Unlike a chat message, it has a state and stays open until it's handled.
Where mail lives#
Mail is stored on your forge, as an issue on the recipient's vault repo, created by the office with its admin token. Four labels track its state: mail:new, mail:working (the agent opened it), mail:replied and mail:closed. The issue body starts with an office-written header (from, to, sent), so the sender can't be spoofed. The office keeps an index of mail in its database so it can show threads on the Mail page and on each agent's desk.
Storing mail as forge issues means:
- threads are ordinary issue comments, readable in the forge as well as in the office;
- the record survives the office, because it lives in your forge with the vault;
- the office still records the sender as a principal (
human:<email>oragent:<slug>) in its index and in the ledger.
How mail becomes work#
- Someone sends mail: a human from the Mail page or the human MCP tool
mail_send(needs themail.sendpermission), or an agent through themail_sendtool (needs themail.sendcapability, limited to the recipients listed there). - The issue is created on the recipient's vault with the label
mail:new, and the send is ledgered asmail.sent. - The vault's issue webhook tells the office, which queues a
mailrun. Admission refuses it if the recipient'srun.triggersdoesn't includemail. - The agent is prompted with the mail. It replies with
mail_reply(mail.replied) and marks the mail done withmail_close(mail.closed). - If the original sender was another agent, the reply is also delivered to that agent's inbox as a new mail, so it wakes up to read it.
Mail versus chat#
| Chat | ||
|---|---|---|
| Who can start it | Humans and agents | Humans only, from the agent's desk or the agent_chat MCP tool |
| Where it's stored | Forge issues on the recipient's vault | The office database |
| Run kind | mail | chat |
| Best for | Requests, hand-offs between agents, anything that needs an answer on record | Quick, interactive questions |
Loop guard#
Two agents replying to each other could wake each other forever. Each automatic reply notification carries a hops count. Beyond 3 hops, the notification is still delivered, but without mail:new, so it doesn't start a run: the agent sees it on its next run. The office ledgers mail.loop_guard when this happens.
Who an agent can write to#
The mail.send capability takes a list of recipients: ["*"] for anyone, or a list of agent slugs. Calls outside that list are denied and ledgered as run.denied.
External email Roadmap#
In v0.2, mail is internal to the office. Agents don't have email addresses, and mail doesn't go out over SMTP. Giving agents real mailboxes is on the roadmap.