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.Best Practices
Address matches the agent's name — pick a stable identifier
Address matches the agent's name — pick a stable identifier
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.Bound your inbox to the slowest consumer
Bound your inbox to the slowest consumer
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.Keep subscriber callbacks small and non-blocking
Keep subscriber callbacks small and non-blocking
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.Reach for a wrapper-backed implementation when you leave one process
Reach for a wrapper-backed implementation when you leave one process
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.Related
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

