Refactor mailbox protocol and add status tracking
Move the protocol documentation to references/ and expand it with read receipts and thread IDs. Update SKILL.md to reference the new location and add a YAML frontmatter block. Remove the outdated MAILBOX.md file.
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
# Mailbox Protocol
|
||||
|
||||
The mailbox is the file-based communication system for the monkey swarm. It enables agents to send messages to each other and the orchestrator without shared memory or a live connection.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```text
|
||||
mail/
|
||||
dir/ ← agent directory (registry of active agents)
|
||||
<agent-id>/
|
||||
inbox/ ← messages received by this agent
|
||||
inbox/.read/← read receipts (marks processed messages)
|
||||
drafts/ ← messages composed by this agent (staging area)
|
||||
sent/ ← sent message copies (archive)
|
||||
```
|
||||
|
||||
Each agent has its own mailbox under `mail/<agent-id>/`. The orchestrator typically uses `orchestrator` as its ID.
|
||||
|
||||
### Read Receipts Directory (`inbox/.read/`)
|
||||
|
||||
The `inbox/.read/` directory tracks which inbox messages have been processed. This prevents context bloat: the orchestrator can tell an agent "only read messages without a receipt," and agents can safely archive read mail without losing delivery confirmation.
|
||||
|
||||
## Agent Directory (`mail/dir/`)
|
||||
|
||||
`mail/dir/` is the registry of active swarm agents. Every agent writes its own entry when it starts, so other agents (and the orchestrator) can discover who is running and how to reach them.
|
||||
|
||||
### Registering
|
||||
|
||||
When an agent starts, it writes a file to `mail/dir/`:
|
||||
|
||||
```bash
|
||||
cat > mail/dir/<agent-id>.txt << 'EOF'
|
||||
id: <agent-id>
|
||||
role: <short role name>
|
||||
archetype: <specialist|surveyor|researcher|planner|interfacer>
|
||||
task: <one-line description>
|
||||
status: active
|
||||
EOF
|
||||
```
|
||||
|
||||
Example — `mail/dir/monkey-a3f7.txt`:
|
||||
|
||||
```text
|
||||
id: monkey-a3f7
|
||||
role: API integration specialist
|
||||
archetype: specialist
|
||||
task: Implement OAuth2 flow in auth module
|
||||
status: active
|
||||
```
|
||||
|
||||
### Status Values
|
||||
|
||||
The `status:` field tracks an agent's current state. The orchestrator uses it to know who's working, who's done, and who needs attention.
|
||||
|
||||
| Status | Meaning |
|
||||
| -------- | ---------------------------------------------------------------------- |
|
||||
| `active` | The agent is currently working on its task. |
|
||||
| `paused` | The agent is idle (waiting for input, blocked, or between work units). |
|
||||
| `done` | The agent has completed its task and is ready to exit. |
|
||||
| `error` | The agent encountered a problem it can't resolve on its own. |
|
||||
| `cancel` | The agent's task has been cancelled by the orchestrator. |
|
||||
|
||||
**Status transitions:**
|
||||
|
||||
- Agents update their own status by rewriting `mail/dir/<agent-id>.txt`.
|
||||
- Set `status: done` when you're finished so the orchestrator can clean up.
|
||||
- Set `status: paused` if you're waiting for a response — don't loop on an empty inbox.
|
||||
- Set `status: error` with details in the file body when you need human or orchestrator help.
|
||||
|
||||
### Discovering Agents
|
||||
|
||||
Agents can scan `mail/dir/` to find who else is in the swarm:
|
||||
|
||||
```bash
|
||||
# List active agents
|
||||
ls mail/dir/
|
||||
|
||||
# Read agent details
|
||||
cat mail/dir/monkey-a3f7.txt
|
||||
```
|
||||
|
||||
Use this to find the right recipient when you need to send mail but don't know which agent ID handles a given role.
|
||||
|
||||
### Cleanup
|
||||
|
||||
When an agent finishes its work, it removes its own entry:
|
||||
|
||||
```bash
|
||||
rm mail/dir/<agent-id>.txt
|
||||
```
|
||||
|
||||
The orchestrator can also clean up stale entries when a swarm run is complete.
|
||||
|
||||
## Sending Mail
|
||||
|
||||
To send a message to another agent:
|
||||
|
||||
1. **Write a draft** — create the message in your drafts folder:
|
||||
|
||||
```text
|
||||
mail/<your-id>/drafts/01_subject-line.txt
|
||||
```
|
||||
|
||||
The prefix number (`01_`) gives ordering; use sequential numbers for related messages.
|
||||
|
||||
2. **Move it to the target's inbox** — atomically deliver by renaming:
|
||||
|
||||
```bash
|
||||
mv mail/<your-id>/drafts/01_subject-line.txt \
|
||||
mail/<target-id>/inbox/01_subject-line_<hash>.txt
|
||||
```
|
||||
|
||||
The trailing `<hash>` is a short random suffix (e.g. `a3f7`) to avoid filename collisions.
|
||||
|
||||
3. **Keep a copy** — copy the message to your `sent/` folder for record-keeping:
|
||||
|
||||
```bash
|
||||
cp mail/<target-id>/inbox/01_subject-line_<hash>.txt \
|
||||
mail/<your-id>/sent/01_subject-line_<hash>.txt
|
||||
```
|
||||
|
||||
4. **Use `mv` for delivery, `cp` for copy** — the inbox copy is the delivered message. Your sent copy is for your records.
|
||||
|
||||
## Receiving Mail
|
||||
|
||||
- **Check inbox at startup** — read all files in `mail/<your-id>/inbox/` that have no read receipt.
|
||||
- **Check inbox between work units** — scan for new files after completing a logical step.
|
||||
- **Process all pending mail** — read every file in the inbox in filename order.
|
||||
- **Write a read receipt** — for each message you process, create a receipt:
|
||||
|
||||
```bash
|
||||
touch mail/<your-id>/inbox/.read/<inbox-filename>
|
||||
```
|
||||
|
||||
The receipt is a marker file (can be empty) with the same name as the inbox file. Its presence signals that the message was read and processed.
|
||||
|
||||
- **Unread-only polling** — on subsequent inbox checks, skip files that have a receipt in `inbox/.read/`. This prevents re-reading old messages into your context window.
|
||||
- **Archive after reading** — move processed mail to `mail/<your-id>/sent/` for record-keeping, or delete it to save context tokens. The read receipt remains as proof of delivery.
|
||||
|
||||
### Unread Inbox Query
|
||||
|
||||
To find unread messages:
|
||||
|
||||
```bash
|
||||
# List messages that have no receipt
|
||||
for msg in mail/<your-id>/inbox/*.txt; do
|
||||
[ -f "mail/<your-id>/inbox/.read/$(basename "$msg")" ] || echo "$msg"
|
||||
done
|
||||
```
|
||||
|
||||
## Mail Format
|
||||
|
||||
Each `.txt` file is a single message with a simple format:
|
||||
|
||||
```text
|
||||
To: <recipient-id>
|
||||
From: <sender-id>
|
||||
Subject: <brief description>
|
||||
Thread: <thread-id>
|
||||
Status: <status>
|
||||
---
|
||||
<message body>
|
||||
```
|
||||
|
||||
### Header Fields
|
||||
|
||||
| Header | Required | Description |
|
||||
| --------- | -------- | ------------------------------------------------------------------- |
|
||||
| `To` | Yes | Recipient agent ID. |
|
||||
| `From` | Yes | Sender agent ID. |
|
||||
| `Subject` | Yes | Brief description of the message content. |
|
||||
| `Thread` | No | Groups related messages. See [Thread Protocol](#thread-protocol). |
|
||||
| `Status` | No | Message status for tracking. See [Message Status](#message-status). |
|
||||
|
||||
The `---` separator distinguishes headers from the body. The body can be any plain text, code, file paths, or structured data.
|
||||
|
||||
### Thread Protocol
|
||||
|
||||
The `Thread:` header groups related messages into a conversation. Use a thread ID whenever you're responding to, continuing, or referencing a prior exchange.
|
||||
|
||||
**Thread ID conventions:**
|
||||
|
||||
- Format: a short, human-readable prefix + ID, e.g. `bd-123`, `task-refactor-auth`, `review-4f2a`
|
||||
- The sender of the first message in a thread chooses the thread ID
|
||||
- Replies use the same thread ID; new conversations get new thread IDs
|
||||
- Omit `Thread:` for standalone messages that won't have replies (e.g., fire-and-forget status updates)
|
||||
|
||||
**Thread-based inbox management:**
|
||||
|
||||
- To read a thread, read all messages sharing the same `Thread:` value
|
||||
- To check for replies to your message, grep your inbox for the thread ID:
|
||||
|
||||
```bash
|
||||
grep -l "Thread: bd-123" mail/<your-id>/inbox/*.txt
|
||||
```
|
||||
|
||||
### Message Status
|
||||
|
||||
The `Status:` header on a message tracks its position in the delivery lifecycle. Unlike the agent `status:` field in `mail/dir/`, this is per-message.
|
||||
|
||||
| Status | When to use |
|
||||
| ----------- | -------------------------------------------------------------------- |
|
||||
| (omitted) | Default. New messages sent to an inbox have no status yet. |
|
||||
| `sent` | Sender has delivered the message. |
|
||||
| `delivered` | Recipient has received the message (set after reading). |
|
||||
| `read` | Recipient has read and processed the message (set before archiving). |
|
||||
| `ack` | Recipient acknowledges the message with an explicit reply. |
|
||||
| `done` | The message's purpose is fulfilled; no further action needed. |
|
||||
| `cancelled` | The orchestrator or sender cancelled the message's intent. |
|
||||
| `error` | Processing failed; details in the message body. |
|
||||
|
||||
**Status update flow:**
|
||||
|
||||
- Sender writes the message with no `Status:` (or `Status: sent`)
|
||||
- Recipient reads the message, writes a read receipt, then optionally updates the status:
|
||||
- If the message requires a reply: send a reply with `Status: ack` in the same thread
|
||||
- If the message is informational only: archive it, status becomes implicit `read`
|
||||
- If the message's task is complete: update the message or send `Status: done` in the reply
|
||||
|
||||
**Status and read receipts work together:** The read receipt proves the message was seen. The `Status:` header communicates the semantic outcome. Use both for critical messages; use read receipts alone for fire-and-forget delivery confirmation.
|
||||
|
||||
## Rules
|
||||
|
||||
- **Register before you work.** Write your entry to `mail/dir/` as one of your first actions so others can find you.
|
||||
- **Unregister when done.** Remove your `mail/dir/` entry before you exit so stale agents don't linger.
|
||||
- **Update your status.** Set `status: done` in your directory entry when you finish. The orchestrator polls `mail/dir/` to know who's still working.
|
||||
- **Your inbox is your signal channel.** The orchestrator uses it to redirect you, cancel work, or provide new context mid-run.
|
||||
- **Keep messages short.** If you have a lot to say, write a file and send a pointer in the mail.
|
||||
- **Always move, never copy.** A message in your drafts is a work-in-progress. Once moved, it's delivered.
|
||||
- **Don't read other agents' inboxes.** Only read your own. If you need to share data with another agent, send it to them — don't peek at their conversations.
|
||||
- **Use read receipts for context management.** Only poll unread messages. This prevents re-reading old mail into your context window on every check.
|
||||
- **Use threads for conversations.** Group related messages so you can read a thread as a unit and skip unrelated noise.
|
||||
- **Check before and between.** The inbox is how you learn you've been redirected. Missing mail = missing orders.
|
||||
Reference in New Issue
Block a user