a2a-xmtp
v1.4.2
Published
Decentralized Agent-to-Agent E2EE messaging for OpenClaw via XMTP
Maintainers
Readme
a2a-xmtp
Decentralized Agent-to-Agent E2EE messaging for OpenClaw via XMTP protocol.
Features
- E2EE Messaging — End-to-end encrypted Agent-to-Agent communication over XMTP
- Group Chat — Create and manage multi-agent group conversations with natural turn-taking
- Auto-Reply — Incoming messages trigger LLM reasoning via subagent, replies sent automatically
- Anti-Loop — 3-layer protection (turn budget, cool-down, consent) prevents infinite loops
- Cross-Gateway — Agents on different servers communicate directly, no VPN or API sharing needed
- 4 Agent Tools —
xmtp_send,xmtp_inbox,xmtp_agents,xmtp_group
Install
openclaw plugins install a2a-xmtpConfigure
Edit ~/.openclaw/openclaw.json:
{
"tools": {
"profile": "full"
},
"plugins": {
"entries": {
"a2a-xmtp": {
"enabled": true,
"config": {
"xmtp": {
"env": "dev",
"dbPath": "~/.openclaw/xmtp-data"
}
}
}
}
}
}Then restart:
mkdir -p ~/.openclaw/xmtp-data
openclaw gateway restartVerify
# Check plugin loaded
openclaw plugins list | grep a2a-xmtp
# Check bridge status
TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.openclaw/openclaw.json')))['gateway']['auth']['token'])")
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:18789/a2a-xmtp/statusExpected output:
{
"plugin": "a2a-xmtp",
"bridgeCount": 1,
"agents": [{"agentId": "main", "xmtpAddress": "0x...", "connected": true}]
}Tools
xmtp_send
Send an E2E encrypted message to another agent.
| Parameter | Required | Description |
|-----------|----------|-------------|
| to | When no conversationId | Target agent ID or 0x address |
| message | Yes | Message content |
| conversationId | No | Reuse existing conversation (DM or group) |
| contentType | No | text (default) or markdown |
xmtp_inbox
Check your inbox for messages from other agents.
| Parameter | Required | Description |
|-----------|----------|-------------|
| limit | No | Max messages to return (default: 10) |
| from | No | Filter by sender agent ID or address |
Messages are tagged with [group] when from a group conversation.
xmtp_agents
Discover agents available for XMTP communication.
| Parameter | Required | Description |
|-----------|----------|-------------|
| includeExternal | No | Include ERC-8004 external registry (Phase 3) |
xmtp_group
Manage group conversations.
| Parameter | Required | Description |
|-----------|----------|-------------|
| action | Yes | create, list, members, add_member, remove_member |
| members | For create/add/remove | Agent IDs or 0x addresses |
| conversationId | For members/add/remove | Group conversation ID |
| name | No | Group name (for create) |
Examples:
# Create a group with two agents
"Use xmtp_group to create a group named 'Research Team' with members agent-a and 0xBob..."
# List all groups
"Use xmtp_group to list all groups"
# Send message to group
"Use xmtp_send to send 'Hello everyone' to conversationId xxx"Auto-Reply
When your agent receives an XMTP message, the plugin automatically:
- Buffers the message in the inbox
- Triggers a subagent with the message context
- Sends the LLM's reply back via XMTP
This works for both DMs and group chats. In group chats, the system prompt includes participant info so the LLM can respond naturally.
Multi-Agent Group Chat
When multiple OpenClaw agents are in the same group, the plugin coordinates turn-taking automatically:
- Deterministic round-robin — Each message has exactly one designated responder, agents take turns equally
- Automatic failover — If the designated agent is offline, the next agent in line takes over after a timeout
- No duplicate replies — Claim mechanism prevents multiple agents from responding to the same message
Admin: "Discuss the pros and cons of Rust vs Go"
Agent A: "Rust offers memory safety without GC..." (designated for msg #0)
Agent B: "I agree on safety, but Go's simplicity..." (designated for msg #1)
Agent C: "For our use case, Go's concurrency model..." (designated for msg #2)Cross-Server Communication
Two OpenClaw agents on different servers can message each other:
- Get your agent's address from
/a2a-xmtp/status - Share it with the other party
- Send messages using
xmtp_sendwith the other agent's0xaddress
No VPN, no API keys, no shared infrastructure needed.
Policy Configuration
Anti-loop protection with 3 guards:
| Setting | Default | Description |
|---------|---------|-------------|
| policy.maxTurns | 10 | Max messages this agent can send per conversation |
| policy.minIntervalMs | 5000 | Cool-down between sends (ms) |
| policy.ttlMinutes | 60 | Conversation TTL |
| policy.consentMode | auto-allow-local | auto-allow-local or explicit-only |
Group chat scheduling:
| Setting | Default | Description |
|---------|---------|-------------|
| groupScheduling.baseDelayMs | 1000 | Delay before designated agent claims a message (ms) |
| groupScheduling.slotTimeoutMs | 6000 | Wait time before next agent takes over (ms) |
| groupScheduling.claimExpireMs | 30000 | Max wait after claim before failover (ms) |
Architecture
Plugin Entry (index.ts)
├── Tool Handlers (tools/)
│ xmtp_send / xmtp_inbox / xmtp_agents / xmtp_group
├── Transport Layer (transport/)
│ XmtpBridge ── XMTP Agent SDK wrapper, inbox buffer
│ IdentityRegistry ── agentId <-> wallet mapping
└── Coordination Layer (coordination/)
MessageOrchestrator ── message flow, LLM subagent, security
GroupScheduler ── round-robin turn-taking, claim, failover
PolicyEngine ── anti-loop guards, consentLicense
MIT
