Skip to main content
Agent Mailbox delivers a message from one agent to another by name — the recipient reads its inbox on its own schedule or reacts the instant a message lands. Send a message to another agent by name — that’s it.

Quick Start

1

Simple send/receive

One sender, one receiver — the sender addresses a message and the receiver drains its inbox.
2

Push notifications with subscribe

Register a callback and react the instant a message arrives — no polling.
3

Correlate a request and its reply

Attach a correlation_id so the sender can match a reply to its original request.

How It Works

The sender enqueues a message in the recipient’s inbox; the recipient either receives a push callback or pulls the queue. Each recipient has its own bounded FIFO inbox. send appends a message and fires any subscriber callbacks; receive drains the oldest messages and removes them from the inbox.

Choosing your delivery pattern

Pick pull, push, or both based on how the recipient should react.

Mailbox vs. bus / kanban / handoff

Reach for a mailbox when you need named agent → named agent delivery — the one thing the other primitives don’t offer.

Configuration Options

InProcessMailbox takes a single constructor parameter.

AgentMessage

Every delivered message is an AgentMessage dataclass. Use msg.to_dict() and AgentMessage.from_dict(data) to round-trip a message through a plain dict.

AgentMailboxProtocol

Any object with these three methods satisfies the mailbox contract — implement it to back a mailbox with your own store. The default InProcessMailbox adds one method beyond the protocol:

Full dataclass fields, to_dict() / from_dict()

Protocol contract for custom implementations

Common Patterns

Fan-out to multiple recipients

Address the same payload to several named agents in one loop.

Request/response with correlation_id

Tag a request with a UUID, reply with the same UUID, and filter the sender’s inbox by it.

Overflow-safe queue for a slow worker

Bound the inbox so a slow consumer never grows unbounded — oldest messages drop silently.
Overflow drops the oldest message with no exception and no return value — design the caller for at-most-max_inbox buffering.

Best Practices

Recipient strings are opaque to the mailbox. Use the Agent(name=...) value as the recipient key so a scan of the code makes the addressing obvious and the same identifier works everywhere.
The default max_inbox=1000 silently drops the oldest message on overflow. If a receiver may be slow or offline for long stretches, either lower max_inbox and design for drop tolerance, or drain more aggressively on the receiver side.
Subscribers fire on the sender’s thread (outside the lock, but still synchronous per delivery). A slow callback slows down every future send() to that recipient. Push heavy work onto a queue or a thread. A single raising subscriber is logged and does not interrupt delivery to others.
The in-process default is fine for single-process demos and unit tests. Cross-process or cross-host fleets should use a wrapper implementation of AgentMailboxProtocol (e.g. Redis) — the interface is identical, only the constructor differs.

Handoffs

Synchronous parent → child delegation

Kanban

Shared task board agents pull work from

Multi-Agent Patterns

Orchestration patterns for agent teams

Named Agent Delegation

Delegatable named agents — the closest cousin