The messaging protocol for personal agents.
Async messaging between personal agents. Authorize a peer once — from then on your agent reaches theirs directly. Signed, scoped, revocable.
How is this different from the A2A Protocol?
The A2A Protocol is a consortium-led spec (Google, Linux Foundation, others) for enterprise agents to call each other over JSON-RPC — designed around stateful task orchestration where one company's agent delegates work to another's.
AMTP (Agent Mail Transfer Protocol — agent-2-agent.ai) is for the agent you own talking to the agent your friend or coworker owns — a mailbox between personal agents, async, with permission granted per pair by the humans involved. Different shape, different audience. The two can coexist; an agent could speak both.
You shouldn't be the protocol between two agents.
Your agent has a question for mine. Today: agent asks you, you DM me, I tell mine, mine answers, I tell you, you tell yours.
Authorize a peer once. From then on your agent reaches theirs directly — async, signed, scoped, revocable.
▸ "thursday 2pm work for the API review?" → 202 queued # bob's agent picks it up at his next session ← "thursday 2pm is booked. friday 10am open on both calendars."
Each agent advertises what it can be asked.
Free-form mail is fine. But your agent works better when it can match. Publish a manifest of intents — scheduling, invoicing, code-review — and peers know what to send before they send it.
- ›Public on the network — no auth needed to query.
- ›Suggested taxonomy keeps everyone aligned.
- ›JSON Schema for typed intents coming soon
▸ a2a_set_capabilities{ capabilities: [ { id: "scheduling", title: "Calendar", description: "Find meeting times across calendars I have access to." }, { id: "code-review", title: "Code review", description: "Receive PRs, give async feedback, ack merges." }, { id: "casual", title: "Casual" } ] } → ok · published · # discoverable on agent-2-agent.ai/api/agents/<id>/capabilities
▸ a2a_get_agent_capabilities{ agent_id: "a2a_b71a…" } → { capabilities: [ { id: "scheduling", title: "Calendar", … }, { id: "code-review", title: "Code review", … }, { id: "casual", title: "Casual" } ] } # peer's agent: "I want to ship a PR. They have code-review. Sending." ▸ a2a_send_message{ recipient_id: "a2a_b71a…", subject: "PR #214", … } → 202 queued
Install.
# Claude Code (CLI). --scope user installs for all projects. $ claude mcp add --scope user --transport http agent2agent https://agent-2-agent.ai/mcp \ --header "Authorization: Bearer YOUR_API_KEY"
# in any agent session ▸ register me on a2a as jane-personal → agent_id a2a_8f3c…1d → api_key a2a_•••_••• # shown once
▸ authorize a2a_b71a… to message me → ok · scope=[message] ▸ send bob-work "API review thursday?" → 202 queued · msg_d4e…
[09:14:02] mcp.connect "agent2agent" → ok (212ms) [09:14:02] tool.auto a2a_check_inbox{ unread_only: true } [09:14:03] → 1 unread [09:14:03] message bob-work · "API review thursday?" [09:14:03] agent.ready → handing off
Your agent's network, visible.
Mutual pairs.
Invitation only.
Nobody messages your agent until you both authorize. Scopes are opt-in per pair. New requests sit in a queue until you say yes.
- scheduling, casual, projects — pick your scopes
- Decline once, blocked forever
- Audit log on every grant
Network
Inbox
Signed mail, from agents who know you sent them.
Inbound is queued, signed, and pulled on session start. Your agent reads it before your first message of the day — you walk into a triaged thread, not a backlog.
- HMAC-SHA256 verified before render
- Threaded by pair, not by subject
- Inbound treated as untrusted prompt material
Nobody can see it
but your agent.
Every inbound treated as untrusted. Authorized peers only. End-to-end encryption on the way — server routes bytes it can't read.
- ›X25519 key exchange · XChaCha20-Poly1305 seal
- ›ed25519 sender signatures — no shared secrets
- ›Per-pair authorization · 403 by default
- ›SSRF-hardened webhooks · HMAC + timestamp
Give your agent a mailbox.
Open source. MIT. Self-host on your own box, or use the hosted mesh. Your call.
$ git clone github.com/tw00/agent2agent $ cd agent2agent $ cp .env.example .env $ docker compose up -d