Skip to main content

A SQLite mailbox for local LLM agents — a CLI primitive plus a hostable MCP server so AI coding agents can message and notify each other. No external services.

Project description

agent-mail

A local SQLite-backed mailbox for local LLM agents. AI coding agents (Claude, Codex, Gemini, …) running on the same machine or LAN get a simple, standard way to message each other — a small CLI plus a hostable MCP server over the same verbs — instead of a human hand-relaying prompts between them. Storage is a single local SQLite file: no external services, no message broker.

CI Python License


Why

Agents on one box usually coordinate by dropping files in a shared git repo — durable and auditable, but poll-only: one agent can't get another's attention. agent-mail gives each agent a real, durable inbox backed by a single local SQLite file — no server to stand up, nothing to keep running.

Honest limitation. A running LLM turn can't be interrupted or poll on a timer, and SQLite can't push a cross-process wake. So "check periodically" means check every turn — at natural decision points. You get a durable inbox to read; there is no mid-turn preemption. (notify still exists but is a best-effort no-op — see below.)

How it works

  • Every message lives in one local SQLite file. Each agent's inbox is just the rows addressed to it, and messages persist until that agent reads (acks) them.
  • Automatic expiry: when a mailbox opens, messages older than ttl_days (default 14) are purged, so history never grows without bound — one simple knob, no compaction to manage.
  • notify is a best-effort no-op: SQLite can't wake another process, so the verb still exists (and validates the address) but doesn't push anything. The model is "check your inbox every turn."
  • The CLI and the MCP server share one core (agent_mail.mailbox.Mailbox) — no logic duplication.

Requirements

  • Python 3.12+
  • Nothing else. Storage is a single local SQLite file (AGENT_MAIL_DB, default ~/.local/share/agent-mail/agent-mail.db); there is no broker or other service to run.

Install

The PyPI package is agent-inbox; it installs the agent-mail command.

uv tool install agent-inbox     # recommended (isolated CLI)
pipx install agent-inbox        # or
pip install agent-inbox         # into the current environment

Or run the MCP server as a container — see Hosting:

docker run -p 8080:8080 -v agent-mail-data:/data \
  salimfadhley/agent-inbox:latest

Quickstart (CLI)

Zero infrastructure: install the package, set your two-part identity — project + agent (--project / AGENT_MAIL_PROJECT and --from / AGENT_ID) — and run. The SQLite file is created on first use.

export AGENT_MAIL_PROJECT=agent-mail
export AGENT_ID=claude-opus

# direct: a specific agent on a project
agent-mail send --to agent-mail/codex --subject "corpus stale?" --body "reindex?"
# any one agent on a project (a shared work queue)
agent-mail send --to agent-mail --subject "task" --body "who can take this?"
# broadcast: every agent on a project
agent-mail send --to agent-mail/* --subject "heads up" --body "deploying in 5"

# read your own inbox (as agent-mail/codex)
AGENT_ID=codex agent-mail inbox
AGENT_ID=codex agent-mail read <id>
AGENT_ID=codex agent-mail reply <id> --body "on it"   # replies directly to the sender

Add --json to any command for machine-readable output.

Addressing: project/agent (direct) · project (any one agent) · project/* (broadcast).

Verb What it does
send --to <target> --subject --body [--thread] [--intent] Send to project/agent, project (any), or project/* (all)
inbox List my unread messages (peek — does not ack)
read <id> Show a message and ack it (consume)
reply <id> --body Reply directly to the sender and ack the original
notify --to <target> [--thread] Validate the address (best-effort; a no-op — SQLite can't wake a process)
ping Round-trip a message to yourself to check the system is operational
doctor Validate config + storage; print the db path, storage: ✅ ready, and the effective (redacted) config
hub-info Show this hub's public self-description (name, connect URL, admin/feedback)
mcp-serve Run the MCP server (see below)
# verify agent-mail is working end-to-end (send + inbox + read to yourself)
AGENT_MAIL_PROJECT=agent-mail AGENT_ID=claude-opus agent-mail ping

MCP server

The same verbs are exposed as MCP tools (send_message, check_inbox, read_message, reply_message, notify_agent, and ping — a self round-trip a client can call on sign-on to confirm everything works). Two ways to run it:

Local, per-agent (stdio). The client spawns it; identity is AGENT_MAIL_PROJECT + AGENT_ID.

AGENT_MAIL_PROJECT=agent-mail AGENT_ID=claude-opus agent-mail mcp-serve

Hosted, multi-agent (http). One server serves everyone. Each agent connects on its own address — the URL is its identity, /<project>/<agent>/mcp:

http://mail-host:8080/agent-mail/claude-opus/mcp   → agent-mail / claude-opus
http://mail-host:8080/goldberg/casework/mcp        → goldberg / casework
agent-mail mcp-serve --transport http --host 0.0.0.0

That personalized URL is an agent's entire configuration — no env, no headers. (?project=&agent= and X-Agent-Project + X-Agent-Id headers also work for programmatic clients.) See docs/mcp-clients.md to wire it into Claude Code, Codex, and others, and docs/hosting.md to deploy it.

The "check your inbox" convention

An agent only benefits from mail if it looks. Paste the ready-made block from docs/inbox-check-snippet.md into your agents' CLAUDE.md / AGENTS.md, and hand a new agent docs/agent-onboarding.md to get it participating.

Configuration

Settings resolve from four layers, later winning: field defaults → the baked defaults.toml → a runtime --config file.tomlenvironment variables. Every setting has one name usable as a lowercase TOML key or its UPPERCASE env var (db == AGENT_MAIL_DB). Containers set env vars; developers point at a TOML file:

agent-mail --config ./agent-mail.toml mcp-serve   # env still overrides the file
agent-mail doctor                                 # show effective config + check storage

Common settings: AGENT_MAIL_DB (the SQLite file path), AGENT_MAIL_TTL_DAYS (auto-purge age, default 14; 0 disables), AGENT_MAIL_MAX_MESSAGE_BYTES (default 1048576 = 1 MiB), AGENT_MAIL_PROJECT, AGENT_ID, AGENT_MAIL_TRANSPORT/HOST/PORT/PATH, AGENT_MAIL_HUB, and the hub's admin/feedback fields advertised via hub_info. Full reference: docs/configuration.md.

Development

uv sync --dev
uv run pytest                       # unit tests
uv run ruff check . && uv run ruff format --check .
uv run pyright

The test suite needs no external services — it runs against SQLite in normal CI.

See CONTRIBUTING.md for the coding standards and quality gates.

License

GPL-3.0-or-later.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_inbox-0.1.0.tar.gz (56.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_inbox-0.1.0-py3-none-any.whl (37.3 kB view details)

Uploaded Python 3

File details

Details for the file agent_inbox-0.1.0.tar.gz.

File metadata

  • Download URL: agent_inbox-0.1.0.tar.gz
  • Upload date:
  • Size: 56.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for agent_inbox-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ddcdd42bf7a52d975a15aabeb29f347c4cf1b801122ffa5209292efbf09f1578
MD5 a0b38500a376df96e63fd19329ec05e1
BLAKE2b-256 4e0be3dc0978dc1cf6131b56ca4c48ff4e83d7699a8739c0772e811b5c1d7230

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_inbox-0.1.0.tar.gz:

Publisher: release.yaml on salimfadhley/agent-inbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agent_inbox-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: agent_inbox-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for agent_inbox-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 caed359bf4c227d481cd07eb6de00fd84fa8a0e3991b97f809d0d2eb81269f2a
MD5 07919c2113947adc2db6b25eedf054ae
BLAKE2b-256 8807dcbdb729087ce9a860e7f9afa61d93fd372b06cf37b62da5b416093d991d

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_inbox-0.1.0-py3-none-any.whl:

Publisher: release.yaml on salimfadhley/agent-inbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page