Local-first durable mailboxes for AI agent-to-agent communication
A single Rust binary for AI agent-to-agent messaging: peer-to-peer, durable, and resumable without requiring Kafka, Redis, Postgres, or a cloud account.
Aerial currently ships as one Rust binary with:
watch its mailbox and be woken when mail
arrives — optionally running an --exec hook — instead of pollingHomebrew packaging is available as aerial-local. An MCP adapter over the
daemon protocol is available through the hidden aerial mcp stdio subcommand —
see MCP.
Install the CLI:
brew tap dcdeniz/aerial brew trust dcdeniz/aerial brew install dcdeniz/aerial/aerial-local
Run the daemon:
aerial up
In another shell, register two agents:
aerial join engineer aerial join researcher
Send a message:
aerial send --from engineer --to researcher --body "Please inspect the architecture."
Read the recipient mailbox:
aerial read researcher
Ack a delivered envelope:
aerial ack --agent researcher <envelope-id>
View prompt/message history:
aerial log --limit 20
Or use the bundled flow macros:
aerial exchange --from engineer --to researcher --body "Please inspect the architecture." aerial status researcher aerial drain researcher
The default history view is intentionally compact:
Agent 28y49uhrfquf -> Agent 14u1rj13ru1 "Message First 50 Characters ...."
Use --json on history when an agent or tool needs structured output.
The canonical command names still exist as serve, register, tell,
inbox, done, and history; the shorter aliases are meant for day-to-day
agent use.
Agents that speak MCP can drive the daemon through a hidden stdio adapter:
aerial mcp --socket .aerial/aerial.sock
It exposes primitive tools — register, tell, inbox, done, and
history — plus flow macros — status, drain, and exchange. Every call is
dispatched to the running daemon, so the adapter keeps no separate mailbox
state; the daemon stays the single source of truth. See docs/MCP.md
for the tool reference, client configuration, and an example session.
Delivery is durable and pull-based: a message sent to an agent waits in that agent's mailbox until the agent reads and acks it. To avoid polling, an agent (or its supervisor) can keep a cheap connection open and be woken when mail arrives.
Stream arrival events as JSONL:
aerial watch researcher
Each new envelope emits one line:
{"event":"message","agent":"researcher","id":"..."}
The mailbox stays the source of truth — an event is only a notification that a pending envelope exists, so a dropped or duplicated wake never loses a message. A watcher that attaches while mail is already pending is replayed one event per waiting envelope, so late subscribers miss nothing.
Run a command on each arrival instead of printing events:
aerial watch researcher --exec "codex ..."
The hook runs through the shell on every new message, with AERIAL_AGENT,
AERIAL_MESSAGE_ID, and AERIAL_SOCKET set in its environment. The spawned
process is responsible for reading its inbox and acking what it handles — the
wake is only the trigger.
For autonomous local work, use the higher-level supervisor. It watches an agent's mailbox, runs a worker for each pending message, and acknowledges the message only when the worker exits successfully:
aerial agent exec researcher -- ./handle-message.sh
For Codex, Aerial builds a prompt from the envelope, recent history, and workspace path:
aerial agent codex researcher --cd .
The supervisor sets AERIAL_AGENT, AERIAL_MESSAGE_ID,
AERIAL_MESSAGE_BODY, AERIAL_SOCKET, and AERIAL_ENVELOPE_JSON for worker
commands. Use --once for deterministic smoke tests or demos:
aerial agent exec researcher --once -- ./handle-message.sh
Run the package-style e2e against aerial on PATH:
scripts/installed-e2e.sh
Run the lower-level two-agent exchange against aerial on PATH:
scripts/two-agent-smoke.sh
The script starts a temporary daemon, registers engineer and researcher,
sends one message, acks it, prints compact history, and removes the temporary
data directory.
With Homebrew:
brew tap dcdeniz/aerial brew trust dcdeniz/aerial brew install dcdeniz/aerial/aerial-local
See docs/INSTALL.md for packaging details.