#19581: feat: add XMTP channel plugin for wallet-to-agent messaging
size: XL
Cluster:
Messaging Channel Integrations
AI assisted PR; codex + openclaw. Prompts largely targeted usage of XMTP sdk (LLM friendly docs) and mirroring the existing flow of the telegram channel. Tested with my own openclaw instance and functional.
## Summary
- **Problem:** OpenClaw has no way to communicate via XMTP, an E2E-encrypted, wallet-native messaging protocol used by applications such as, Converse, World, and xmtp.chat - leaving onchain/web3 agents unreachable from these surfaces.
- **Why it matters:** XMTP is the de facto messaging layer for wallet-to-wallet agent communication. Supporting it makes OpenClaw agents discoverable and reachable from any XMTP-compatible app using just an Ethereum address.
- **What changed:** Added a new `@openclaw/xmtp` channel plugin (`extensions/xmtp/`) implementing DM support, pairing/allowlist access control, reply threading (inbound + outbound), policy-aware auto-consent, `walletKeyFile`/`dbEncryptionKeyFile` support for file-based secret loading, and comprehensive test coverage (58+ tests across 4 test files). Config schema aligns with the existing OpenClaw channel config conventions.
- **What did NOT change (scope boundary):** No group chat support (DMs only). No media/attachment support. No changes to core OpenClaw — this is a self-contained plugin using the standard `ChannelPlugin` interface. No changes to existing channels or gateway logic.
## Change Type (select all)
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
https://github.com/openclaw/openclaw/discussions/2050
## User-visible / Behavior Changes
- **New channel: `xmtp`** — agents can now receive and respond to XMTP DMs from any XMTP-compatible app (Base, Converse, World, xmtp.chat)
- **New config section: `channels.xmtp`** with the following keys:
- `walletKey` (required unless `walletKeyFile` set) — EOA private key for the agent's XMTP identity
- `walletKeyFile` — path to a file containing the wallet key (alternative to inline config)
- `dbEncryptionKey` (required unless `dbEncryptionKeyFile` set) — 64 hex char encryption key for local SQLite DB
- `dbEncryptionKeyFile` — path to a file containing the DB encryption key
- `env` — `local` | `dev` | `production` (default: `production`)
- `dbPath` — custom DB directory (default: `~/.openclaw/channels/xmtp/<env>/`)
- `dmPolicy` — `pairing` | `allowlist` | `open` | `disabled` (default: `pairing`)
- `allowFrom` — array of Ethereum addresses
- **New plugin entry: `plugins.entries.xmtp`** — standard enable/disable toggle
- **Reply threading** — inbound replies include referenced message context (`ReplyToId`, `ReplyToBody`); outbound replies are sent as threaded XMTP replies when `replyToId` is present
- **Policy-aware auto-consent** — new DM conversations are auto-consented based on `dmPolicy`: always for `open`/`pairing`, only for allowlisted senders in `allowlist` mode, never for `disabled`
- **Pairing flow** — follows the standard OpenClaw pairing pattern; users send a message, receive a pairing code, admin approves via `openclaw pairing approve --channel xmtp <CODE>`
- **Credential source tracking** — `describeAccount` reports `credentialSource` and `secretSource` (`config`, `file`, or `none`) for diagnostics
## Security Impact (required)
- New permissions/capabilities? **Yes** — new channel plugin that connects to the XMTP network
- Secrets/tokens handling changed? **Yes** — `walletKey` and `dbEncryptionKey` stored in config or loaded from file via `walletKeyFile`/`dbEncryptionKeyFile`
- New/changed network calls? **Yes** — connects to XMTP network nodes (gRPC) for message streaming
- Command/tool execution surface changed? **No**
- Data access scope changed? **No**
**Risk + mitigation:**
- `walletKey` is an EOA private key — if compromised, attacker can impersonate the agent on XMTP. Mitigation: config values are redacted in logs/status; `walletKeyFile` supported for file-based secret loading (e.g. mounted secrets, keychain export); recommend env vars or keychain for production.
- XMTP SQLite DB files contain identity + encryption keys. Mitigation: DB directory is created with `0o700` permissions; `dbEncryptionKey` encrypts the DB via SQLCipher.
- Plugin runs in-process with the Gateway (same as all OpenClaw plugins). Mitigation: standard plugin trust model; plugin uses only the official `@xmtp/agent-sdk`.
## Repro + Verification
### Environment
- OS: macOS 15.3.1 (arm64)
- Runtime/container: Node.js v25.6.0
- Model/provider: N/A (channel plugin, not model-dependent)
- Integration/channel: XMTP (production network)
- Relevant config:
```json5
{
"channels": {
"xmtp": {
"enabled": true,
"walletKey": "<REDACTED>",
"dbEncryptionKey": "<REDACTED>",
"env": "production",
"dmPolicy": "pairing",
"allowFrom": ["0x..."]
}
},
"plugins": {
"entries": {
"xmtp": { "enabled": true }
}
}
}
```
### Steps
1. Configure `channels.xmtp` with a valid wallet key and DB encryption key
2. Enable the plugin in `plugins.entries.xmtp`
3. Restart the gateway
4. From any XMTP client (xmtp.chat, Base app, Converse), send a DM to the agent's Ethereum address
5. If `dmPolicy` is `pairing`, approve the pairing request via `openclaw pairing approve --channel xmtp <CODE>`
6. Send messages — agent should respond; reply to a message to test threading
### Expected
- Agent connects to XMTP network and shows `XMTP: ON / OK / configured` in `openclaw status`
- Inbound DMs are routed to the correct agent session
- Outbound replies are delivered back via XMTP
- Reply threading preserves message context (referenced message ID and text)
- Auto-consent respects dmPolicy (e.g. `disabled` never consents, `allowlist` only consents for allowed senders)
### Actual
- Verified working on production XMTP network with real DMs from xmtp.chat
## Evidence
- [x] Failing test/log before + passing after
- 58+ tests passing across 4 test files (`vitest run extensions/xmtp/`)
- Test files: `channel.test.ts` (plugin structure, capabilities, reply support), `channel.behavior.test.ts` (inbound routing, pairing, outbound delivery, reply threading, threaded dispatcher replies), `types.test.ts` (account resolution, config parsing, credential source tracking), `xmtp-bus.test.ts` (SDK wrapper, send/receive, reply context extraction, auto-consent callback)
- [x] Trace/log snippets
- Gateway logs show: `[default] XMTP agent connected (env: production)`, `[default] XMTP provider started (address: 0x...)`
- Inbound: `xmtp inbound: sender=0x... sid=... len=... preview="..."`
- Outbound: `xmtp outbound: to=... len=... preview="..."`
## Human Verification (required)
- **Verified scenarios:** DM send/receive on production XMTP network via xmtp.chat; pairing flow (request → approve → message delivery); reply threading (inbound reply context visible to agent, outbound threaded replies); `openclaw status` shows correct channel state; `openclaw pairing list --channel xmtp` lists pending requests; auto-consent behavior across all dmPolicy modes
- **Edge cases checked:** Unauthorized senders blocked per dmPolicy; empty messages filtered; policy-aware auto-consent (`disabled` never consents, `allowlist` only for allowed senders, `open`/`pairing` always consent); hot-reload of account config on each message; allowFrom store scoped by accountId; graceful fallback if sendReply not available on conversation object; `readAllowFromStore` failures logged as warnings instead of silently swallowed
- **What was NOT verified:** Group chat (not implemented); media/attachments (not implemented); multi-account XMTP; behavior under XMTP network outages; XMTP mainnet fee model (not yet live); `walletKeyFile`/`dbEncryptionKeyFile` loading (file-based paths, not tested end-to-end)
## Compatibility / Migration
- Backward compatible? **Yes** — purely additive; no changes to existing code
- Config/env changes? **Yes** — new `channels.xmtp` config section (only needed if enabling XMTP)
- Migration needed? **No**
## Failure Recovery (if this breaks)
- **How to disable/revert:** Set `plugins.entries.xmtp.enabled: false` or remove `channels.xmtp` from config, then restart gateway
- **Files/config to restore:** Only `openclaw.json` (remove xmtp entries)
- **Known bad symptoms:** If XMTP SDK fails to connect, gateway logs will show `XMTP error (...)` but other channels are unaffected (plugin is isolated). If DB files are corrupted/lost, agent creates a new XMTP installation (max 10 per inbox — monitor with `openclaw status`)
## Risks and Mitigations
- **Risk:** XMTP SDK is an external dependency that could introduce breaking changes on update.
**Mitigation:** `@xmtp/agent-sdk` version is pinned in `package.json`; plugin is isolated in `extensions/xmtp/` and can be disabled independently.
- **Risk:** SQLite DB file loss creates new installations (hard limit of 10 per inbox, no revocation yet).
**Mitigation:** DB files stored in persistent `~/.openclaw/channels/xmtp/` directory with restricted permissions; documented in code comments and plugin README.
- **Risk:** `walletKey` in config could be accidentally exposed in logs or status output.
**Mitigation:** OpenClaw's config system redacts sensitive fields; plugin reports `credentialSource`/`secretSource` in diagnostics rather than the actual values; `walletKeyFile`/`dbEncryptionKeyFile` options allow keeping secrets out of config entirely.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Added self-contained XMTP channel plugin (`extensions/xmtp/`) that i...
Most Similar PRs
#20348: Add support for Keybase as a channel
by xgess · 2026-02-18
72.4%
#21015: # feat(xmpp): Complete XMPP Channel Implementation
by toughworm · 2026-02-19
70.8%
#22260: feat(extensions/deltachat): add Delta.Chat channel extension
by alanz · 2026-02-20
70.4%
#17157: feat(messenger): add Facebook Messenger channel integration
by gmjuhasz · 2026-02-15
69.6%
#18860: feat(agents): expose tools and their schemas via new after_tools_re...
by lan17 · 2026-02-17
68.6%
#19514: feat: add Bluesky DM channel extension
by librenews · 2026-02-17
68.5%
#23226: fix(msteams): proactive messaging, EADDRINUSE fix, tool status, ada...
by TarogStar · 2026-02-22
68.4%
#21208: feat: update tlon channel/plugin to be more fully featured
by arthyn · 2026-02-19
67.6%
#9594: feat: add SimpleX messaging channel
by dangoldbj · 2026-02-05
67.4%
#6588: feat(channels): add 'confirming' dmPolicy mode for owner-approved r...
by zote · 2026-02-01
67.0%