mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-07 22:09:57 +00:00
Matrix: replace legacy plugin with new implementation
This commit is contained in:
@@ -1,391 +0,0 @@
|
||||
---
|
||||
summary: "Matrix-js support status, setup, and configuration examples"
|
||||
read_when:
|
||||
- Setting up Matrix-js in OpenClaw
|
||||
- Configuring Matrix E2EE and verification
|
||||
title: "Matrix-js"
|
||||
---
|
||||
|
||||
# Matrix-js (plugin)
|
||||
|
||||
Matrix-js is the current Matrix channel plugin for OpenClaw.
|
||||
It uses the official `matrix-js-sdk` and supports DMs, rooms, threads, media, reactions, polls, location, and E2EE.
|
||||
|
||||
For new setups, use Matrix-js.
|
||||
If you need legacy compatibility with `@vector-im/matrix-bot-sdk`, use [Matrix (legacy)](/channels/matrix).
|
||||
|
||||
## Plugin required
|
||||
|
||||
Matrix-js is a plugin and is not bundled with core OpenClaw.
|
||||
|
||||
Install from npm:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/matrix-js
|
||||
```
|
||||
|
||||
Install from a local checkout:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/matrix-js
|
||||
```
|
||||
|
||||
See [Plugins](/tools/plugin) for plugin behavior and install rules.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install the plugin.
|
||||
2. Create a Matrix account on your homeserver.
|
||||
3. Configure `channels["matrix-js"]` with either:
|
||||
- `homeserver` + `accessToken`, or
|
||||
- `homeserver` + `userId` + `password`.
|
||||
4. Restart the gateway.
|
||||
5. Start a DM with the bot or invite it to a room.
|
||||
|
||||
Minimal token-based setup:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"matrix-js": {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
dm: { policy: "pairing" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Password-based setup (token is cached after login):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"matrix-js": {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
password: "replace-me",
|
||||
deviceName: "OpenClaw Gateway",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Matrix-js stores cached credentials in `~/.openclaw/credentials/matrix/`.
|
||||
The default account uses `credentials.json`; named accounts use `credentials-<account>.json`.
|
||||
|
||||
Environment variable equivalents (used when the config key is not set):
|
||||
|
||||
- `MATRIX_HOMESERVER`
|
||||
- `MATRIX_ACCESS_TOKEN`
|
||||
- `MATRIX_USER_ID`
|
||||
- `MATRIX_PASSWORD`
|
||||
- `MATRIX_DEVICE_ID`
|
||||
- `MATRIX_DEVICE_NAME`
|
||||
|
||||
For non-default accounts, use account-scoped env vars:
|
||||
|
||||
- `MATRIX_<ACCOUNT_ID>_HOMESERVER`
|
||||
- `MATRIX_<ACCOUNT_ID>_ACCESS_TOKEN`
|
||||
- `MATRIX_<ACCOUNT_ID>_USER_ID`
|
||||
- `MATRIX_<ACCOUNT_ID>_PASSWORD`
|
||||
- `MATRIX_<ACCOUNT_ID>_DEVICE_ID`
|
||||
- `MATRIX_<ACCOUNT_ID>_DEVICE_NAME`
|
||||
|
||||
Example for account `ops`:
|
||||
|
||||
- `MATRIX_OPS_HOMESERVER`
|
||||
- `MATRIX_OPS_ACCESS_TOKEN`
|
||||
|
||||
## Configuration example
|
||||
|
||||
This is a practical baseline config with DM pairing, room allowlist, and E2EE enabled:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"matrix-js": {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
encryption: true,
|
||||
|
||||
dm: {
|
||||
policy: "pairing",
|
||||
},
|
||||
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@admin:example.org"],
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
|
||||
autoJoin: "allowlist",
|
||||
autoJoinAllowlist: ["!roomid:example.org"],
|
||||
threadReplies: "inbound",
|
||||
replyToMode: "off",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## E2EE setup
|
||||
|
||||
Enable encryption:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"matrix-js": {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
encryption: true,
|
||||
dm: { policy: "pairing" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Check verification status:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify status
|
||||
```
|
||||
|
||||
Verbose status (full diagnostics):
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify status --verbose
|
||||
```
|
||||
|
||||
Bootstrap cross-signing and verification state:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify bootstrap
|
||||
```
|
||||
|
||||
Verbose bootstrap diagnostics:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify bootstrap --verbose
|
||||
```
|
||||
|
||||
Verify this device with a recovery key:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify device "<your-recovery-key>"
|
||||
```
|
||||
|
||||
Verbose device verification details:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify device "<your-recovery-key>" --verbose
|
||||
```
|
||||
|
||||
Check room-key backup health:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify backup status
|
||||
```
|
||||
|
||||
Verbose backup health diagnostics:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify backup status --verbose
|
||||
```
|
||||
|
||||
Restore room keys from server backup:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify backup restore
|
||||
```
|
||||
|
||||
Verbose restore diagnostics:
|
||||
|
||||
```bash
|
||||
openclaw matrix-js verify backup restore --verbose
|
||||
```
|
||||
|
||||
All `verify` commands are concise by default (including quiet internal SDK logging) and show detailed diagnostics only with `--verbose`.
|
||||
Use `--json` for full machine-readable output when scripting.
|
||||
|
||||
When `encryption: true`, Matrix-js defaults `startupVerification` to `"if-unverified"`.
|
||||
On startup, if this device is still unverified, Matrix-js will request self-verification in another Matrix client,
|
||||
skip duplicate requests while one is already pending, and apply a local cooldown before retrying after restarts.
|
||||
Failed request attempts retry sooner than successful request creation by default.
|
||||
Set `startupVerification: "off"` to disable automatic startup requests, or tune `startupVerificationCooldownHours`
|
||||
if you want a shorter or longer retry window.
|
||||
|
||||
Encrypted runtime state is stored per account and per access token in
|
||||
`~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/`.
|
||||
That directory contains the sync store (`bot-storage.json`), crypto store (`crypto/`),
|
||||
recovery key file (`recovery-key.json`), IndexedDB snapshot (`crypto-idb-snapshot.json`),
|
||||
thread bindings (`thread-bindings.json`), and startup verification state (`startup-verification.json`)
|
||||
when those features are in use.
|
||||
|
||||
## Automatic verification notices
|
||||
|
||||
Matrix-js now posts verification lifecycle notices directly into the Matrix room as `m.notice` messages.
|
||||
That includes:
|
||||
|
||||
- verification request notices
|
||||
- verification ready notices (with explicit "Verify by emoji" guidance)
|
||||
- verification start and completion notices
|
||||
- SAS details (emoji and decimal) when available
|
||||
|
||||
Inbound SAS requests are auto-confirmed by the bot device, so once the user confirms "They match"
|
||||
in their Matrix client, verification completes without requiring a manual OpenClaw tool step.
|
||||
Verification protocol/system notices are not forwarded to the agent chat pipeline, so they do not produce `NO_REPLY`.
|
||||
|
||||
## Threads
|
||||
|
||||
Matrix-js supports native Matrix threads for both automatic replies and message-tool sends.
|
||||
|
||||
- `threadReplies: "off"` keeps replies top-level.
|
||||
- `threadReplies: "inbound"` replies inside a thread only when the inbound message was already in that thread.
|
||||
- `threadReplies: "always"` keeps room replies in a thread rooted at the triggering message.
|
||||
- Inbound threaded messages include the thread root message as extra agent context.
|
||||
- Message-tool sends now auto-inherit the current Matrix thread when the target is the same room, or the same DM user target, unless an explicit `threadId` is provided.
|
||||
- Runtime thread bindings are supported for Matrix-js. `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, and thread-bound `/acp spawn` now work in Matrix rooms and DMs.
|
||||
- Top-level Matrix room/DM `/focus` creates a new Matrix thread and binds it to the target session when `threadBindings.spawnSubagentSessions=true`.
|
||||
- Running `/focus` or `/acp spawn --thread here` inside an existing Matrix thread binds that current thread instead.
|
||||
|
||||
### Thread Binding Config
|
||||
|
||||
Matrix-js inherits global defaults from `session.threadBindings`, and also supports per-channel overrides:
|
||||
|
||||
- `threadBindings.enabled`
|
||||
- `threadBindings.idleHours`
|
||||
- `threadBindings.maxAgeHours`
|
||||
- `threadBindings.spawnSubagentSessions`
|
||||
- `threadBindings.spawnAcpSessions`
|
||||
|
||||
Matrix-js thread-bound spawn flags are opt-in:
|
||||
|
||||
- Set `threadBindings.spawnSubagentSessions: true` to allow top-level `/focus` to create and bind new Matrix threads.
|
||||
- Set `threadBindings.spawnAcpSessions: true` to allow `/acp spawn --thread auto|here` to bind ACP sessions to Matrix threads.
|
||||
|
||||
## Reactions
|
||||
|
||||
Matrix-js supports outbound reaction actions, inbound reaction notifications, and inbound ack reactions.
|
||||
|
||||
- Outbound reaction tooling is gated by `channels["matrix-js"].actions.reactions`.
|
||||
- `react` adds a reaction to a specific Matrix event.
|
||||
- `reactions` lists the current reaction summary for a specific Matrix event.
|
||||
- `emoji=""` removes the bot account's own reactions on that event.
|
||||
- `remove: true` removes only the specified emoji reaction from the bot account.
|
||||
|
||||
Ack reactions use the standard OpenClaw resolution order:
|
||||
|
||||
- `channels["matrix-js"].accounts.<accountId>.ackReaction`
|
||||
- `channels["matrix-js"].ackReaction`
|
||||
- `messages.ackReaction`
|
||||
- agent identity emoji fallback
|
||||
|
||||
Ack reaction scope resolves in this order:
|
||||
|
||||
- `channels["matrix-js"].accounts.<accountId>.ackReactionScope`
|
||||
- `channels["matrix-js"].ackReactionScope`
|
||||
- `messages.ackReactionScope`
|
||||
|
||||
Reaction notification mode resolves in this order:
|
||||
|
||||
- `channels["matrix-js"].accounts.<accountId>.reactionNotifications`
|
||||
- `channels["matrix-js"].reactionNotifications`
|
||||
- default: `own`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- `reactionNotifications: "own"` forwards added `m.reaction` events when they target bot-authored Matrix messages.
|
||||
- `reactionNotifications: "off"` disables reaction system events.
|
||||
- Reaction removals are still not synthesized into system events because Matrix surfaces those as redactions, not as standalone `m.reaction` removals.
|
||||
|
||||
## DM and room policy example
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"matrix-js": {
|
||||
dm: {
|
||||
policy: "allowlist",
|
||||
allowFrom: ["@admin:example.org"],
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@admin:example.org"],
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
See [Groups](/channels/groups) for mention-gating and allowlist behavior.
|
||||
|
||||
## Multi-account example
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"matrix-js": {
|
||||
enabled: true,
|
||||
dm: { policy: "pairing" },
|
||||
accounts: {
|
||||
assistant: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_assistant_xxx",
|
||||
encryption: true,
|
||||
},
|
||||
alerts: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_alerts_xxx",
|
||||
dm: {
|
||||
policy: "allowlist",
|
||||
allowFrom: ["@ops:example.org"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration reference
|
||||
|
||||
- `enabled`: enable or disable the channel.
|
||||
- `homeserver`: homeserver URL, for example `https://matrix.example.org`.
|
||||
- `userId`: full Matrix user ID, for example `@bot:example.org`.
|
||||
- `accessToken`: access token for token-based auth.
|
||||
- `password`: password for password-based login.
|
||||
- `deviceId`: explicit Matrix device ID.
|
||||
- `deviceName`: device display name for password login.
|
||||
- `initialSyncLimit`: startup sync event limit.
|
||||
- `encryption`: enable E2EE.
|
||||
- `allowlistOnly`: force allowlist-only behavior for DMs and rooms.
|
||||
- `groupPolicy`: `open`, `allowlist`, or `disabled`.
|
||||
- `groupAllowFrom`: allowlist of user IDs for room traffic.
|
||||
- `replyToMode`: `off`, `first`, or `all`.
|
||||
- `threadReplies`: `off`, `inbound`, or `always`.
|
||||
- `threadBindings`: per-channel overrides for thread-bound session routing and lifecycle.
|
||||
- `startupVerification`: automatic self-verification request mode on startup (`if-unverified`, `off`).
|
||||
- `startupVerificationCooldownHours`: cooldown before retrying automatic startup verification requests.
|
||||
- `textChunkLimit`: outbound message chunk size.
|
||||
- `chunkMode`: `length` or `newline`.
|
||||
- `responsePrefix`: optional message prefix for outbound replies.
|
||||
- `ackReaction`: optional ack reaction override for this channel/account.
|
||||
- `ackReactionScope`: optional ack reaction scope override (`group-mentions`, `group-all`, `direct`, `all`, `none`, `off`).
|
||||
- `reactionNotifications`: inbound reaction notification mode (`own`, `off`).
|
||||
- `mediaMaxMb`: outbound media size cap in MB.
|
||||
- `autoJoin`: invite auto-join policy (`always`, `allowlist`, `off`).
|
||||
- `autoJoinAllowlist`: rooms/aliases allowed when `autoJoin` is `allowlist`.
|
||||
- `dm`: DM policy block (`enabled`, `policy`, `allowFrom`).
|
||||
- `groups`: per-room policy map.
|
||||
- `rooms`: legacy alias for `groups`.
|
||||
- `actions`: per-action tool gating (`messages`, `reactions`, `pins`, `memberInfo`, `channelInfo`, `verification`).
|
||||
@@ -1,83 +1,45 @@
|
||||
---
|
||||
summary: "Matrix support status, capabilities, and configuration"
|
||||
summary: "Matrix support status, setup, and configuration examples"
|
||||
read_when:
|
||||
- Working on Matrix channel features
|
||||
- Setting up Matrix in OpenClaw
|
||||
- Configuring Matrix E2EE and verification
|
||||
title: "Matrix"
|
||||
---
|
||||
|
||||
# Matrix (plugin)
|
||||
|
||||
Matrix is an open, decentralized messaging protocol. OpenClaw connects as a Matrix **user**
|
||||
on any homeserver, so you need a Matrix account for the bot. Once it is logged in, you can DM
|
||||
the bot directly or invite it to rooms (Matrix "groups"). Beeper is a valid client option too,
|
||||
but it requires E2EE to be enabled.
|
||||
|
||||
Status: supported via plugin (@vector-im/matrix-bot-sdk). Direct messages, rooms, threads, media, reactions,
|
||||
polls (send + poll-start as text), location, and E2EE (with crypto support).
|
||||
Matrix is the Matrix channel plugin for OpenClaw.
|
||||
It uses the official `matrix-js-sdk` and supports DMs, rooms, threads, media, reactions, polls, location, and E2EE.
|
||||
|
||||
## Plugin required
|
||||
|
||||
Matrix ships as a plugin and is not bundled with the core install.
|
||||
Matrix is a plugin and is not bundled with core OpenClaw.
|
||||
|
||||
Install via CLI (npm registry):
|
||||
Install from npm:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/matrix
|
||||
```
|
||||
|
||||
Local checkout (when running from a git repo):
|
||||
Install from a local checkout:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/matrix
|
||||
```
|
||||
|
||||
If you choose Matrix during configure/onboarding and a git checkout is detected,
|
||||
OpenClaw will offer the local install path automatically.
|
||||
|
||||
Details: [Plugins](/tools/plugin)
|
||||
See [Plugins](/tools/plugin) for plugin behavior and install rules.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install the Matrix plugin:
|
||||
- From npm: `openclaw plugins install @openclaw/matrix`
|
||||
- From a local checkout: `openclaw plugins install ./extensions/matrix`
|
||||
2. Create a Matrix account on a homeserver:
|
||||
- Browse hosting options at [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/)
|
||||
- Or host it yourself.
|
||||
3. Get an access token for the bot account:
|
||||
- Use the Matrix login API with `curl` at your home server:
|
||||
1. Install the plugin.
|
||||
2. Create a Matrix account on your homeserver.
|
||||
3. Configure `channels.matrix` with either:
|
||||
- `homeserver` + `accessToken`, or
|
||||
- `homeserver` + `userId` + `password`.
|
||||
4. Restart the gateway.
|
||||
5. Start a DM with the bot or invite it to a room.
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url https://matrix.example.org/_matrix/client/v3/login \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"type": "m.login.password",
|
||||
"identifier": {
|
||||
"type": "m.id.user",
|
||||
"user": "your-user-name"
|
||||
},
|
||||
"password": "your-password"
|
||||
}'
|
||||
```
|
||||
|
||||
- Replace `matrix.example.org` with your homeserver URL.
|
||||
- Or set `channels.matrix.userId` + `channels.matrix.password`: OpenClaw calls the same
|
||||
login endpoint, stores the access token in `~/.openclaw/credentials/matrix/credentials.json`,
|
||||
and reuses it on next start.
|
||||
|
||||
4. Configure credentials:
|
||||
- Env: `MATRIX_HOMESERVER`, `MATRIX_ACCESS_TOKEN` (or `MATRIX_USER_ID` + `MATRIX_PASSWORD`)
|
||||
- Or config: `channels.matrix.*`
|
||||
- If both are set, config takes precedence.
|
||||
- With access token: user ID is fetched automatically via `/whoami`.
|
||||
- When set, `channels.matrix.userId` should be the full Matrix ID (example: `@bot:example.org`).
|
||||
5. Restart the gateway (or finish onboarding).
|
||||
6. Start a DM with the bot or invite it to a room from any Matrix client
|
||||
(Element, Beeper, etc.; see [https://matrix.org/ecosystem/clients/](https://matrix.org/ecosystem/clients/)). Beeper requires E2EE,
|
||||
so set `channels.matrix.encryption: true` and verify the device.
|
||||
|
||||
Minimal config (access token, user ID auto-fetched):
|
||||
Minimal token-based setup:
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -85,14 +47,14 @@ Minimal config (access token, user ID auto-fetched):
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_***",
|
||||
accessToken: "syt_xxx",
|
||||
dm: { policy: "pairing" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
E2EE config (end to end encryption enabled):
|
||||
Password-based setup (token is cached after login):
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -100,7 +62,85 @@ E2EE config (end to end encryption enabled):
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_***",
|
||||
userId: "@bot:example.org",
|
||||
password: "replace-me",
|
||||
deviceName: "OpenClaw Gateway",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Matrix stores cached credentials in `~/.openclaw/credentials/matrix/`.
|
||||
The default account uses `credentials.json`; named accounts use `credentials-<account>.json`.
|
||||
|
||||
Environment variable equivalents (used when the config key is not set):
|
||||
|
||||
- `MATRIX_HOMESERVER`
|
||||
- `MATRIX_ACCESS_TOKEN`
|
||||
- `MATRIX_USER_ID`
|
||||
- `MATRIX_PASSWORD`
|
||||
- `MATRIX_DEVICE_ID`
|
||||
- `MATRIX_DEVICE_NAME`
|
||||
|
||||
For non-default accounts, use account-scoped env vars:
|
||||
|
||||
- `MATRIX_<ACCOUNT_ID>_HOMESERVER`
|
||||
- `MATRIX_<ACCOUNT_ID>_ACCESS_TOKEN`
|
||||
- `MATRIX_<ACCOUNT_ID>_USER_ID`
|
||||
- `MATRIX_<ACCOUNT_ID>_PASSWORD`
|
||||
- `MATRIX_<ACCOUNT_ID>_DEVICE_ID`
|
||||
- `MATRIX_<ACCOUNT_ID>_DEVICE_NAME`
|
||||
|
||||
Example for account `ops`:
|
||||
|
||||
- `MATRIX_OPS_HOMESERVER`
|
||||
- `MATRIX_OPS_ACCESS_TOKEN`
|
||||
|
||||
## Configuration example
|
||||
|
||||
This is a practical baseline config with DM pairing, room allowlist, and E2EE enabled:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
encryption: true,
|
||||
|
||||
dm: {
|
||||
policy: "pairing",
|
||||
},
|
||||
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@admin:example.org"],
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
|
||||
autoJoin: "allowlist",
|
||||
autoJoinAllowlist: ["!roomid:example.org"],
|
||||
threadReplies: "inbound",
|
||||
replyToMode: "off",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## E2EE setup
|
||||
|
||||
Enable encryption:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
encryption: true,
|
||||
dm: { policy: "pairing" },
|
||||
},
|
||||
@@ -108,41 +148,193 @@ E2EE config (end to end encryption enabled):
|
||||
}
|
||||
```
|
||||
|
||||
## Encryption (E2EE)
|
||||
Check verification status:
|
||||
|
||||
End-to-end encryption is **supported** via the Rust crypto SDK.
|
||||
```bash
|
||||
openclaw matrix verify status
|
||||
```
|
||||
|
||||
Enable with `channels.matrix.encryption: true`:
|
||||
Verbose status (full diagnostics):
|
||||
|
||||
- If the crypto module loads, encrypted rooms are decrypted automatically.
|
||||
- Outbound media is encrypted when sending to encrypted rooms.
|
||||
- On first connection, OpenClaw requests device verification from your other sessions.
|
||||
- Verify the device in another Matrix client (Element, etc.) to enable key sharing.
|
||||
- If the crypto module cannot be loaded, E2EE is disabled and encrypted rooms will not decrypt;
|
||||
OpenClaw logs a warning.
|
||||
- If you see missing crypto module errors (for example, `@matrix-org/matrix-sdk-crypto-nodejs-*`),
|
||||
allow build scripts for `@matrix-org/matrix-sdk-crypto-nodejs` and run
|
||||
`pnpm rebuild @matrix-org/matrix-sdk-crypto-nodejs` or fetch the binary with
|
||||
`node node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js`.
|
||||
```bash
|
||||
openclaw matrix verify status --verbose
|
||||
```
|
||||
|
||||
Crypto state is stored per account + access token in
|
||||
`~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/crypto/`
|
||||
(SQLite database). Sync state lives alongside it in `bot-storage.json`.
|
||||
If the access token (device) changes, a new store is created and the bot must be
|
||||
re-verified for encrypted rooms.
|
||||
Bootstrap cross-signing and verification state:
|
||||
|
||||
**Device verification:**
|
||||
When E2EE is enabled, the bot will request verification from your other sessions on startup.
|
||||
Open Element (or another client) and approve the verification request to establish trust.
|
||||
Once verified, the bot can decrypt messages in encrypted rooms.
|
||||
```bash
|
||||
openclaw matrix verify bootstrap
|
||||
```
|
||||
|
||||
## Multi-account
|
||||
Verbose bootstrap diagnostics:
|
||||
|
||||
Multi-account support: use `channels.matrix.accounts` with per-account credentials and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern.
|
||||
```bash
|
||||
openclaw matrix verify bootstrap --verbose
|
||||
```
|
||||
|
||||
Each account runs as a separate Matrix user on any homeserver. Per-account config
|
||||
inherits from the top-level `channels.matrix` settings and can override any option
|
||||
(DM policy, groups, encryption, etc.).
|
||||
Verify this device with a recovery key:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify device "<your-recovery-key>"
|
||||
```
|
||||
|
||||
Verbose device verification details:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify device "<your-recovery-key>" --verbose
|
||||
```
|
||||
|
||||
Check room-key backup health:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup status
|
||||
```
|
||||
|
||||
Verbose backup health diagnostics:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup status --verbose
|
||||
```
|
||||
|
||||
Restore room keys from server backup:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup restore
|
||||
```
|
||||
|
||||
Verbose restore diagnostics:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup restore --verbose
|
||||
```
|
||||
|
||||
All `verify` commands are concise by default (including quiet internal SDK logging) and show detailed diagnostics only with `--verbose`.
|
||||
Use `--json` for full machine-readable output when scripting.
|
||||
|
||||
When `encryption: true`, Matrix defaults `startupVerification` to `"if-unverified"`.
|
||||
On startup, if this device is still unverified, Matrix will request self-verification in another Matrix client,
|
||||
skip duplicate requests while one is already pending, and apply a local cooldown before retrying after restarts.
|
||||
Failed request attempts retry sooner than successful request creation by default.
|
||||
Set `startupVerification: "off"` to disable automatic startup requests, or tune `startupVerificationCooldownHours`
|
||||
if you want a shorter or longer retry window.
|
||||
|
||||
Upgrading from the previous public Matrix plugin:
|
||||
|
||||
- OpenClaw automatically reuses the same Matrix account, access token, and device identity when possible.
|
||||
- If the previous plugin stored a Matrix room-key backup decryption key locally, startup or `openclaw doctor --fix` will import it into the new recovery-key flow automatically.
|
||||
- On the next gateway start, backed-up room keys are restored automatically into the new crypto store.
|
||||
- If the old plugin had local-only room keys that were never backed up, OpenClaw will warn clearly. Those keys cannot be exported automatically from the previous rust crypto store, so some old encrypted history may remain unavailable until recovered manually.
|
||||
- See [Matrix migration](/install/migrating-matrix) for the full upgrade flow, limits, recovery commands, and common migration messages.
|
||||
|
||||
Encrypted runtime state is stored per account and per access token in
|
||||
`~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/`.
|
||||
That directory contains the sync store (`bot-storage.json`), crypto store (`crypto/`),
|
||||
recovery key file (`recovery-key.json`), IndexedDB snapshot (`crypto-idb-snapshot.json`),
|
||||
thread bindings (`thread-bindings.json`), and startup verification state (`startup-verification.json`)
|
||||
when those features are in use.
|
||||
|
||||
## Automatic verification notices
|
||||
|
||||
Matrix now posts verification lifecycle notices directly into the Matrix room as `m.notice` messages.
|
||||
That includes:
|
||||
|
||||
- verification request notices
|
||||
- verification ready notices (with explicit "Verify by emoji" guidance)
|
||||
- verification start and completion notices
|
||||
- SAS details (emoji and decimal) when available
|
||||
|
||||
Inbound SAS requests are auto-confirmed by the bot device, so once the user confirms "They match"
|
||||
in their Matrix client, verification completes without requiring a manual OpenClaw tool step.
|
||||
Verification protocol/system notices are not forwarded to the agent chat pipeline, so they do not produce `NO_REPLY`.
|
||||
|
||||
## Threads
|
||||
|
||||
Matrix supports native Matrix threads for both automatic replies and message-tool sends.
|
||||
|
||||
- `threadReplies: "off"` keeps replies top-level.
|
||||
- `threadReplies: "inbound"` replies inside a thread only when the inbound message was already in that thread.
|
||||
- `threadReplies: "always"` keeps room replies in a thread rooted at the triggering message.
|
||||
- Inbound threaded messages include the thread root message as extra agent context.
|
||||
- Message-tool sends now auto-inherit the current Matrix thread when the target is the same room, or the same DM user target, unless an explicit `threadId` is provided.
|
||||
- Runtime thread bindings are supported for Matrix. `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, and thread-bound `/acp spawn` now work in Matrix rooms and DMs.
|
||||
- Top-level Matrix room/DM `/focus` creates a new Matrix thread and binds it to the target session when `threadBindings.spawnSubagentSessions=true`.
|
||||
- Running `/focus` or `/acp spawn --thread here` inside an existing Matrix thread binds that current thread instead.
|
||||
|
||||
### Thread Binding Config
|
||||
|
||||
Matrix inherits global defaults from `session.threadBindings`, and also supports per-channel overrides:
|
||||
|
||||
- `threadBindings.enabled`
|
||||
- `threadBindings.idleHours`
|
||||
- `threadBindings.maxAgeHours`
|
||||
- `threadBindings.spawnSubagentSessions`
|
||||
- `threadBindings.spawnAcpSessions`
|
||||
|
||||
Matrix thread-bound spawn flags are opt-in:
|
||||
|
||||
- Set `threadBindings.spawnSubagentSessions: true` to allow top-level `/focus` to create and bind new Matrix threads.
|
||||
- Set `threadBindings.spawnAcpSessions: true` to allow `/acp spawn --thread auto|here` to bind ACP sessions to Matrix threads.
|
||||
|
||||
## Reactions
|
||||
|
||||
Matrix supports outbound reaction actions, inbound reaction notifications, and inbound ack reactions.
|
||||
|
||||
- Outbound reaction tooling is gated by `channels["matrix"].actions.reactions`.
|
||||
- `react` adds a reaction to a specific Matrix event.
|
||||
- `reactions` lists the current reaction summary for a specific Matrix event.
|
||||
- `emoji=""` removes the bot account's own reactions on that event.
|
||||
- `remove: true` removes only the specified emoji reaction from the bot account.
|
||||
|
||||
Ack reactions use the standard OpenClaw resolution order:
|
||||
|
||||
- `channels["matrix"].accounts.<accountId>.ackReaction`
|
||||
- `channels["matrix"].ackReaction`
|
||||
- `messages.ackReaction`
|
||||
- agent identity emoji fallback
|
||||
|
||||
Ack reaction scope resolves in this order:
|
||||
|
||||
- `channels["matrix"].accounts.<accountId>.ackReactionScope`
|
||||
- `channels["matrix"].ackReactionScope`
|
||||
- `messages.ackReactionScope`
|
||||
|
||||
Reaction notification mode resolves in this order:
|
||||
|
||||
- `channels["matrix"].accounts.<accountId>.reactionNotifications`
|
||||
- `channels["matrix"].reactionNotifications`
|
||||
- default: `own`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- `reactionNotifications: "own"` forwards added `m.reaction` events when they target bot-authored Matrix messages.
|
||||
- `reactionNotifications: "off"` disables reaction system events.
|
||||
- Reaction removals are still not synthesized into system events because Matrix surfaces those as redactions, not as standalone `m.reaction` removals.
|
||||
|
||||
## DM and room policy example
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: {
|
||||
policy: "allowlist",
|
||||
allowFrom: ["@admin:example.org"],
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@admin:example.org"],
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
See [Groups](/channels/groups) for mention-gating and allowlist behavior.
|
||||
|
||||
## Multi-account example
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -152,16 +344,17 @@ inherits from the top-level `channels.matrix` settings and can override any opti
|
||||
dm: { policy: "pairing" },
|
||||
accounts: {
|
||||
assistant: {
|
||||
name: "Main assistant",
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_assistant_***",
|
||||
accessToken: "syt_assistant_xxx",
|
||||
encryption: true,
|
||||
},
|
||||
alerts: {
|
||||
name: "Alerts bot",
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_alerts_***",
|
||||
dm: { policy: "allowlist", allowFrom: ["@admin:example.org"] },
|
||||
accessToken: "syt_alerts_xxx",
|
||||
dm: {
|
||||
policy: "allowlist",
|
||||
allowFrom: ["@ops:example.org"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -169,135 +362,35 @@ inherits from the top-level `channels.matrix` settings and can override any opti
|
||||
}
|
||||
```
|
||||
|
||||
Notes:
|
||||
## Configuration reference
|
||||
|
||||
- Account startup is serialized to avoid race conditions with concurrent module imports.
|
||||
- Env variables (`MATRIX_HOMESERVER`, `MATRIX_ACCESS_TOKEN`, etc.) only apply to the **default** account.
|
||||
- Base channel settings (DM policy, group policy, mention gating, etc.) apply to all accounts unless overridden per account.
|
||||
- Use `bindings[].match.accountId` to route each account to a different agent.
|
||||
- Crypto state is stored per account + access token (separate key stores per account).
|
||||
|
||||
## Routing model
|
||||
|
||||
- Replies always go back to Matrix.
|
||||
- DMs share the agent's main session; rooms map to group sessions.
|
||||
|
||||
## Access control (DMs)
|
||||
|
||||
- Default: `channels.matrix.dm.policy = "pairing"`. Unknown senders get a pairing code.
|
||||
- Approve via:
|
||||
- `openclaw pairing list matrix`
|
||||
- `openclaw pairing approve matrix <CODE>`
|
||||
- Public DMs: `channels.matrix.dm.policy="open"` plus `channels.matrix.dm.allowFrom=["*"]`.
|
||||
- `channels.matrix.dm.allowFrom` accepts full Matrix user IDs (example: `@user:server`). The wizard resolves display names to user IDs when directory search finds a single exact match.
|
||||
- Do not use display names or bare localparts (example: `"Alice"` or `"alice"`). They are ambiguous and are ignored for allowlist matching. Use full `@user:server` IDs.
|
||||
|
||||
## Rooms (groups)
|
||||
|
||||
- Default: `channels.matrix.groupPolicy = "allowlist"` (mention-gated). Use `channels.defaults.groupPolicy` to override the default when unset.
|
||||
- Runtime note: if `channels.matrix` is completely missing, runtime falls back to `groupPolicy="allowlist"` for room checks (even if `channels.defaults.groupPolicy` is set).
|
||||
- Allowlist rooms with `channels.matrix.groups` (room IDs or aliases; names are resolved to IDs when directory search finds a single exact match):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"!roomId:example.org": { allow: true },
|
||||
"#alias:example.org": { allow: true },
|
||||
},
|
||||
groupAllowFrom: ["@owner:example.org"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- `requireMention: false` enables auto-reply in that room.
|
||||
- `groups."*"` can set defaults for mention gating across rooms.
|
||||
- `groupAllowFrom` restricts which senders can trigger the bot in rooms (full Matrix user IDs).
|
||||
- Per-room `users` allowlists can further restrict senders inside a specific room (use full Matrix user IDs).
|
||||
- The configure wizard prompts for room allowlists (room IDs, aliases, or names) and resolves names only on an exact, unique match.
|
||||
- On startup, OpenClaw resolves room/user names in allowlists to IDs and logs the mapping; unresolved entries are ignored for allowlist matching.
|
||||
- Invites are auto-joined by default; control with `channels.matrix.autoJoin` and `channels.matrix.autoJoinAllowlist`.
|
||||
- To allow **no rooms**, set `channels.matrix.groupPolicy: "disabled"` (or keep an empty allowlist).
|
||||
- Legacy key: `channels.matrix.rooms` (same shape as `groups`).
|
||||
|
||||
## Threads
|
||||
|
||||
- Reply threading is supported.
|
||||
- `channels.matrix.threadReplies` controls whether replies stay in threads:
|
||||
- `off`, `inbound` (default), `always`
|
||||
- `channels.matrix.replyToMode` controls reply-to metadata when not replying in a thread:
|
||||
- `off` (default), `first`, `all`
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Feature | Status |
|
||||
| --------------- | ------------------------------------------------------------------------------------- |
|
||||
| Direct messages | ✅ Supported |
|
||||
| Rooms | ✅ Supported |
|
||||
| Threads | ✅ Supported |
|
||||
| Media | ✅ Supported |
|
||||
| E2EE | ✅ Supported (crypto module required) |
|
||||
| Reactions | ✅ Supported (send/read via tools) |
|
||||
| Polls | ✅ Send supported; inbound poll starts are converted to text (responses/ends ignored) |
|
||||
| Location | ✅ Supported (geo URI; altitude ignored) |
|
||||
| Native commands | ✅ Supported |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Run this ladder first:
|
||||
|
||||
```bash
|
||||
openclaw status
|
||||
openclaw gateway status
|
||||
openclaw logs --follow
|
||||
openclaw doctor
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
Then confirm DM pairing state if needed:
|
||||
|
||||
```bash
|
||||
openclaw pairing list matrix
|
||||
```
|
||||
|
||||
Common failures:
|
||||
|
||||
- Logged in but room messages ignored: room blocked by `groupPolicy` or room allowlist.
|
||||
- DMs ignored: sender pending approval when `channels.matrix.dm.policy="pairing"`.
|
||||
- Encrypted rooms fail: crypto support or encryption settings mismatch.
|
||||
|
||||
For triage flow: [/channels/troubleshooting](/channels/troubleshooting).
|
||||
|
||||
## Configuration reference (Matrix)
|
||||
|
||||
Full configuration: [Configuration](/gateway/configuration)
|
||||
|
||||
Provider options:
|
||||
|
||||
- `channels.matrix.enabled`: enable/disable channel startup.
|
||||
- `channels.matrix.homeserver`: homeserver URL.
|
||||
- `channels.matrix.userId`: Matrix user ID (optional with access token).
|
||||
- `channels.matrix.accessToken`: access token.
|
||||
- `channels.matrix.password`: password for login (token stored).
|
||||
- `channels.matrix.deviceName`: device display name.
|
||||
- `channels.matrix.encryption`: enable E2EE (default: false).
|
||||
- `channels.matrix.initialSyncLimit`: initial sync limit.
|
||||
- `channels.matrix.threadReplies`: `off | inbound | always` (default: inbound).
|
||||
- `channels.matrix.textChunkLimit`: outbound text chunk size (chars).
|
||||
- `channels.matrix.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking.
|
||||
- `channels.matrix.dm.policy`: `pairing | allowlist | open | disabled` (default: pairing).
|
||||
- `channels.matrix.dm.allowFrom`: DM allowlist (full Matrix user IDs). `open` requires `"*"`. The wizard resolves names to IDs when possible.
|
||||
- `channels.matrix.groupPolicy`: `allowlist | open | disabled` (default: allowlist).
|
||||
- `channels.matrix.groupAllowFrom`: allowlisted senders for group messages (full Matrix user IDs).
|
||||
- `channels.matrix.allowlistOnly`: force allowlist rules for DMs + rooms.
|
||||
- `channels.matrix.groups`: group allowlist + per-room settings map.
|
||||
- `channels.matrix.rooms`: legacy group allowlist/config.
|
||||
- `channels.matrix.replyToMode`: reply-to mode for threads/tags.
|
||||
- `channels.matrix.mediaMaxMb`: inbound/outbound media cap (MB).
|
||||
- `channels.matrix.autoJoin`: invite handling (`always | allowlist | off`, default: always).
|
||||
- `channels.matrix.autoJoinAllowlist`: allowed room IDs/aliases for auto-join.
|
||||
- `channels.matrix.accounts`: multi-account configuration keyed by account ID (each account inherits top-level settings).
|
||||
- `channels.matrix.actions`: per-action tool gating (reactions/messages/pins/memberInfo/channelInfo).
|
||||
- `enabled`: enable or disable the channel.
|
||||
- `homeserver`: homeserver URL, for example `https://matrix.example.org`.
|
||||
- `userId`: full Matrix user ID, for example `@bot:example.org`.
|
||||
- `accessToken`: access token for token-based auth.
|
||||
- `password`: password for password-based login.
|
||||
- `deviceId`: explicit Matrix device ID.
|
||||
- `deviceName`: device display name for password login.
|
||||
- `initialSyncLimit`: startup sync event limit.
|
||||
- `encryption`: enable E2EE.
|
||||
- `allowlistOnly`: force allowlist-only behavior for DMs and rooms.
|
||||
- `groupPolicy`: `open`, `allowlist`, or `disabled`.
|
||||
- `groupAllowFrom`: allowlist of user IDs for room traffic.
|
||||
- `replyToMode`: `off`, `first`, or `all`.
|
||||
- `threadReplies`: `off`, `inbound`, or `always`.
|
||||
- `threadBindings`: per-channel overrides for thread-bound session routing and lifecycle.
|
||||
- `startupVerification`: automatic self-verification request mode on startup (`if-unverified`, `off`).
|
||||
- `startupVerificationCooldownHours`: cooldown before retrying automatic startup verification requests.
|
||||
- `textChunkLimit`: outbound message chunk size.
|
||||
- `chunkMode`: `length` or `newline`.
|
||||
- `responsePrefix`: optional message prefix for outbound replies.
|
||||
- `ackReaction`: optional ack reaction override for this channel/account.
|
||||
- `ackReactionScope`: optional ack reaction scope override (`group-mentions`, `group-all`, `direct`, `all`, `none`, `off`).
|
||||
- `reactionNotifications`: inbound reaction notification mode (`own`, `off`).
|
||||
- `mediaMaxMb`: outbound media size cap in MB.
|
||||
- `autoJoin`: invite auto-join policy (`always`, `allowlist`, `off`).
|
||||
- `autoJoinAllowlist`: rooms/aliases allowed when `autoJoin` is `allowlist`.
|
||||
- `dm`: DM policy block (`enabled`, `policy`, `allowFrom`).
|
||||
- `groups`: per-room policy map.
|
||||
- `rooms`: legacy alias for `groups`.
|
||||
- `actions`: per-action tool gating (`messages`, `reactions`, `pins`, `memberInfo`, `channelInfo`, `verification`).
|
||||
|
||||
@@ -870,7 +870,12 @@
|
||||
},
|
||||
{
|
||||
"group": "Maintenance",
|
||||
"pages": ["install/updating", "install/migrating", "install/uninstall"]
|
||||
"pages": [
|
||||
"install/updating",
|
||||
"install/migrating",
|
||||
"install/migrating-matrix",
|
||||
"install/uninstall"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Hosting and deployment",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
summary: "Replace the legacy Matrix plugin with the new Matrix implementation while preserving the public matrix surface and providing automatic migration for current users."
|
||||
owner: "gumadeiras"
|
||||
status: "in progress"
|
||||
status: "implemented"
|
||||
last_updated: "2026-03-08"
|
||||
title: "Matrix Supersession Migration"
|
||||
---
|
||||
@@ -28,17 +28,19 @@ This plan is also the working implementation tracker. Update the checklist statu
|
||||
### Current status
|
||||
|
||||
- [x] Migration plan written and tracked in repo
|
||||
- [ ] Replace `extensions/matrix` with the new implementation
|
||||
- [ ] Remove shipped `matrix-js` public/runtime/package surfaces
|
||||
- [ ] Preserve legacy `matrix` config compatibility
|
||||
- [ ] Preserve legacy `matrix` state compatibility
|
||||
- [ ] Add startup and doctor migration/repair UX
|
||||
- [ ] Rewrite docs/help/tests to use `matrix` only
|
||||
- [ ] Verify update flow end to end
|
||||
- [x] Replace `extensions/matrix` with the new implementation
|
||||
- [x] Remove shipped `matrix-js` public/runtime/package surfaces
|
||||
- [x] Preserve legacy `matrix` config compatibility
|
||||
- [x] Preserve legacy `matrix` state compatibility
|
||||
- [x] Add startup and doctor migration/repair UX
|
||||
- [x] Rewrite docs/help/tests to use `matrix` only
|
||||
- [x] Verify update flow end to end
|
||||
|
||||
### Change log
|
||||
|
||||
- 2026-03-08: Initial supersession plan written and added to docs as a live checklist.
|
||||
- 2026-03-08: Replaced `extensions/matrix` with the new Matrix implementation, removed shipped `matrix-js` surfaces, added startup/doctor Matrix migration UX, and deleted `extensions/matrix-js`.
|
||||
- 2026-03-08: Added encrypted-state migration prep for legacy Matrix rust crypto stores, automatic backup-key extraction, startup room-key restore, and explicit warnings for local-only keys that cannot be exported automatically.
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -50,153 +52,156 @@ This plan is also the working implementation tracker. Update the checklist statu
|
||||
|
||||
## Public surface after cutover
|
||||
|
||||
- [ ] Canonical package/install surface stays `@openclaw/matrix` and `openclaw plugins install @openclaw/matrix`.
|
||||
- [ ] Canonical channel/plugin/binding id is `matrix`.
|
||||
- [ ] Canonical config namespace is `channels.matrix`.
|
||||
- [ ] Canonical CLI surface is `openclaw matrix ...`, including the verification/account commands currently only exposed under Matrix-js.
|
||||
- [ ] Canonical gateway methods become `matrix.verify.status`, `matrix.verify.bootstrap`, and `matrix.verify.recoveryKey`.
|
||||
- [ ] Canonical ACP/subagent binding channel is `matrix`.
|
||||
- [ ] Canonical plugin SDK subpath is `openclaw/plugin-sdk/matrix`.
|
||||
- [ ] Remove all shipped/public `matrix-js` references from docs, config help, tests, install catalog metadata, and package exports.
|
||||
- [x] Canonical package/install surface stays `@openclaw/matrix` and `openclaw plugins install @openclaw/matrix`.
|
||||
- [x] Canonical channel/plugin/binding id is `matrix`.
|
||||
- [x] Canonical config namespace is `channels.matrix`.
|
||||
- [x] Canonical CLI surface is `openclaw matrix ...`, including the verification/account commands currently only exposed under Matrix-js.
|
||||
- [x] Canonical gateway methods become `matrix.verify.status`, `matrix.verify.bootstrap`, and `matrix.verify.recoveryKey`.
|
||||
- [x] Canonical ACP/subagent binding channel is `matrix`.
|
||||
- [x] Canonical plugin SDK subpath is `openclaw/plugin-sdk/matrix`.
|
||||
- [x] Remove all shipped/public `matrix-js` references from docs, config help, tests, install catalog metadata, and package exports.
|
||||
|
||||
## Migration flow and UX
|
||||
|
||||
### Standard npm users
|
||||
|
||||
- [ ] No config key change required.
|
||||
- [ ] No plugin install record rewrite required because the package remains `@openclaw/matrix`.
|
||||
- [ ] Updating OpenClaw or running `openclaw plugins update` replaces the plugin in place.
|
||||
- [ ] Startup and doctor automatically repair any legacy Matrix config/state that the new implementation cannot consume directly.
|
||||
- [x] No config key change required.
|
||||
- [x] No plugin install record rewrite required because the package remains `@openclaw/matrix`.
|
||||
- [x] Updating OpenClaw or running `openclaw plugins update` replaces the plugin in place.
|
||||
- [x] Startup and doctor automatically repair any legacy Matrix config/state that the new implementation cannot consume directly.
|
||||
|
||||
### Startup behavior
|
||||
|
||||
- [ ] Keep the existing startup auto-migration model.
|
||||
- [ ] On first startup after upgrade, detect legacy Matrix config/state mismatches and repair them automatically when the repair is deterministic and local.
|
||||
- [ ] Log a concise one-time summary of what was migrated and only show next steps when user action is still required.
|
||||
- [x] Keep the existing startup auto-migration model.
|
||||
- [x] On first startup after upgrade, detect legacy Matrix config/state mismatches and repair them automatically when the repair is deterministic and local.
|
||||
- [x] Log a concise one-time summary of what was migrated and only show next steps when user action is still required.
|
||||
|
||||
### Doctor and update behavior
|
||||
|
||||
- [ ] `openclaw doctor --fix` and update-triggered doctor run the same Matrix migration logic, but with richer user-facing output.
|
||||
- [ ] Doctor shows exactly which Matrix paths/keys were changed and why.
|
||||
- [ ] Doctor validates the installed Matrix plugin source and surfaces manual repair steps for custom path installs.
|
||||
- [x] `openclaw doctor --fix` and update-triggered doctor run the same Matrix migration logic, but with richer user-facing output.
|
||||
- [x] Doctor shows exactly which Matrix paths/keys were changed and why.
|
||||
- [x] Doctor validates the installed Matrix plugin source and surfaces manual repair steps for custom path installs.
|
||||
|
||||
### Custom or local-path installs
|
||||
|
||||
- [ ] Do not auto-rewrite arbitrary custom plugin paths.
|
||||
- [ ] If the legacy Matrix plugin was installed from a custom path and that path is now stale or missing, warn clearly and print the exact replacement command or path to use.
|
||||
- [ ] If the custom path is valid and already points at the replacement plugin, leave it alone.
|
||||
- [x] Do not auto-rewrite arbitrary custom plugin paths.
|
||||
- [x] If the legacy Matrix plugin was installed from a custom path and that path is now stale or missing, warn clearly and print the exact replacement command or path to use.
|
||||
- [x] If the custom path is valid and already points at the replacement plugin, leave it alone.
|
||||
|
||||
### Unsupported scope
|
||||
|
||||
- [ ] No backward compatibility for internal `matrix-js` adopters.
|
||||
- [ ] Do not auto-migrate `channels.matrix-js`, `@openclaw/matrix-js`, `openclaw matrix-js`, or `plugins.entries["matrix-js"]`.
|
||||
- [x] No backward compatibility for internal `matrix-js` adopters.
|
||||
- [x] Do not auto-migrate `channels.matrix-js`, `@openclaw/matrix-js`, `openclaw matrix-js`, or `plugins.entries["matrix-js"]`.
|
||||
|
||||
## Implementation changes
|
||||
|
||||
### 1. Replace identity at the package and plugin layer
|
||||
|
||||
- [ ] Overwrite `extensions/matrix` with the Matrix-js implementation instead of renaming user-facing config.
|
||||
- [ ] Delete `extensions/matrix-js` after the port is complete.
|
||||
- [ ] Update `extensions/matrix/package.json`, `extensions/matrix/openclaw.plugin.json`, and `extensions/matrix/index.ts` so the package remains `@openclaw/matrix` but exposes the new feature set.
|
||||
- [ ] Port the Matrix-js CLI and gateway-method registration into `extensions/matrix/index.ts` and register it under `matrix`, not `matrix-js`.
|
||||
- [ ] Replace all internal `openclaw/plugin-sdk/matrix-js` imports with `openclaw/plugin-sdk/matrix`.
|
||||
- [ ] Replace the plugin SDK implementation behind `src/plugin-sdk/matrix.ts` with the Matrix-js helper surface superset, then remove the `matrix-js` plugin-sdk export from `package.json`, `scripts/check-plugin-sdk-exports.mjs`, `scripts/write-plugin-sdk-entry-dts.ts`, and related release/build checks.
|
||||
- [x] Overwrite `extensions/matrix` with the Matrix-js implementation instead of renaming user-facing config.
|
||||
- [x] Delete `extensions/matrix-js` after the port is complete.
|
||||
- [x] Update `extensions/matrix/package.json`, `extensions/matrix/openclaw.plugin.json`, and `extensions/matrix/index.ts` so the package remains `@openclaw/matrix` but exposes the new feature set.
|
||||
- [x] Port the Matrix-js CLI and gateway-method registration into `extensions/matrix/index.ts` and register it under `matrix`, not `matrix-js`.
|
||||
- [x] Replace all internal `openclaw/plugin-sdk/matrix-js` imports with `openclaw/plugin-sdk/matrix`.
|
||||
- [x] Replace the plugin SDK implementation behind `src/plugin-sdk/matrix.ts` with the Matrix-js helper surface superset, then remove the `matrix-js` plugin-sdk export from `package.json`, `scripts/check-plugin-sdk-exports.mjs`, `scripts/write-plugin-sdk-entry-dts.ts`, and related release/build checks.
|
||||
|
||||
### 2. Preserve legacy `matrix` config compatibility
|
||||
|
||||
- [ ] Make the new `matrix` plugin accept the current public legacy `channels.matrix` schema as-is.
|
||||
- [ ] Keep support for top-level single-account `channels.matrix.*`.
|
||||
- [ ] Keep support for `channels.matrix.accounts.*`.
|
||||
- [ ] Keep support for `channels.matrix.defaultAccount`.
|
||||
- [ ] Keep support for the legacy `rooms` alias.
|
||||
- [ ] Keep support for existing DM and group policy keys.
|
||||
- [ ] Keep support for existing bindings that use `match.channel: "matrix"`.
|
||||
- [ ] Preserve SecretRef password inputs used by the legacy plugin.
|
||||
- [ ] Do not require rewriting normal single-account configs into `accounts.default`.
|
||||
- [ ] Add or keep doctor and startup migrations only for keys that are genuinely obsolete or ignored by the new implementation.
|
||||
- [ ] Ensure config help, schema labels, and reference docs all describe `channels.matrix`, never `channels.matrix-js`.
|
||||
- [x] Make the new `matrix` plugin accept the current public legacy `channels.matrix` schema as-is.
|
||||
- [x] Keep support for top-level single-account `channels.matrix.*`.
|
||||
- [x] Keep support for `channels.matrix.accounts.*`.
|
||||
- [x] Keep support for `channels.matrix.defaultAccount`.
|
||||
- [x] Keep support for the legacy `rooms` alias.
|
||||
- [x] Keep support for existing DM and group policy keys.
|
||||
- [x] Keep support for existing bindings that use `match.channel: "matrix"`.
|
||||
- [x] Preserve SecretRef password inputs used by the legacy plugin.
|
||||
- [x] Do not require rewriting normal single-account configs into `accounts.default`.
|
||||
- [x] Add or keep doctor and startup migrations only for keys that are genuinely obsolete or ignored by the new implementation.
|
||||
- [x] Ensure config help, schema labels, and reference docs all describe `channels.matrix`, never `channels.matrix-js`.
|
||||
|
||||
### 3. Preserve legacy `matrix` state and runtime behavior
|
||||
|
||||
- [ ] Keep `credentials/matrix/credentials*.json` as the credential root.
|
||||
- [ ] Keep `matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/...` as the canonical runtime and crypto root.
|
||||
- [ ] Add explicit migration support in the new plugin for direct upgrades from the oldest legacy flat store:
|
||||
- [ ] `~/.openclaw/matrix/bot-storage.json`
|
||||
- [ ] `~/.openclaw/matrix/crypto/`
|
||||
- [ ] Do not retain `matrix-js`-path migration logic in the shipped plugin.
|
||||
- [ ] Preserve multi-account isolation and default-account behavior exactly on the `matrix` channel.
|
||||
- [ ] Preserve legacy secrets integration by continuing to use the existing `channels.matrix.*` secret collectors and credential surface definitions.
|
||||
- [ ] Keep route/session binding, ACP binding, thread binding, and outbound message routing keyed to `matrix`, with the current new Matrix functionality carried over.
|
||||
- [x] Keep `credentials/matrix/credentials*.json` as the credential root.
|
||||
- [x] Keep `matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/...` as the canonical runtime and crypto root.
|
||||
- [x] Add explicit migration support in the new plugin for direct upgrades from the oldest legacy flat store:
|
||||
- [x] `~/.openclaw/matrix/bot-storage.json`
|
||||
- [x] `~/.openclaw/matrix/crypto/`
|
||||
- [x] Do not retain `matrix-js`-path migration logic in the shipped plugin.
|
||||
- [x] Preserve multi-account isolation and default-account behavior exactly on the `matrix` channel.
|
||||
- [x] Preserve legacy secrets integration by continuing to use the existing `channels.matrix.*` secret collectors and credential surface definitions.
|
||||
- [x] Keep route/session binding, ACP binding, thread binding, and outbound message routing keyed to `matrix`, with the current new Matrix functionality carried over.
|
||||
|
||||
### 4. Migrate internal Matrix-js-only surfaces to `matrix`
|
||||
|
||||
- [ ] Replace every internal channel string and binding string `matrix-js` with `matrix` across ACP binding schemas and runtime.
|
||||
- [ ] Replace every internal channel string and binding string `matrix-js` with `matrix` across thread binding policy and commands.
|
||||
- [ ] Replace every internal channel string and binding string `matrix-js` with `matrix` across auto-reply and session context surfaces.
|
||||
- [ ] Replace every internal channel string and binding string `matrix-js` with `matrix` across agent binding commands and tests.
|
||||
- [ ] Replace all CLI help, onboarding text, runtime warnings, and verification prompts from `matrix-js` to `matrix`.
|
||||
- [ ] Rewrite `docs/channels/matrix.md` to describe the new implementation and new verification, ACP, and thread features.
|
||||
- [ ] Remove `docs/channels/matrix-js.md`.
|
||||
- [ ] Update shared docs that still reference Matrix-js, including `docs/tools/acp-agents.md`, `docs/tools/subagents.md`, `docs/tools/plugin.md`, and `docs/gateway/configuration-reference.md`.
|
||||
- [ ] Leave `docs/zh-CN/**` untouched in this pass.
|
||||
- [x] Replace every internal channel string and binding string `matrix-js` with `matrix` across ACP binding schemas and runtime.
|
||||
- [x] Replace every internal channel string and binding string `matrix-js` with `matrix` across thread binding policy and commands.
|
||||
- [x] Replace every internal channel string and binding string `matrix-js` with `matrix` across auto-reply and session context surfaces.
|
||||
- [x] Replace every internal channel string and binding string `matrix-js` with `matrix` across agent binding commands and tests.
|
||||
- [x] Replace all CLI help, onboarding text, runtime warnings, and verification prompts from `matrix-js` to `matrix`.
|
||||
- [x] Rewrite `docs/channels/matrix.md` to describe the new implementation and new verification, ACP, and thread features.
|
||||
- [x] Remove `docs/channels/matrix-js.md`.
|
||||
- [x] Update shared docs that still reference Matrix-js, including `docs/tools/acp-agents.md`, `docs/tools/subagents.md`, `docs/tools/plugin.md`, and `docs/gateway/configuration-reference.md`.
|
||||
- [x] Leave `docs/zh-CN/**` untouched in this pass.
|
||||
|
||||
### 5. Automatic messaging and failure handling
|
||||
|
||||
- [ ] When startup or doctor rewrites Matrix config, emit a short summary such as:
|
||||
- [ ] Matrix plugin upgraded in place
|
||||
- [ ] migrated deprecated Matrix config keys
|
||||
- [ ] migrated legacy Matrix crypto store
|
||||
- [ ] no user action required
|
||||
- [ ] When automatic repair is not safe, emit exact commands, not generic warnings.
|
||||
- [ ] For custom or stale local plugin paths, point users to the concrete replacement command or path.
|
||||
- [ ] Never log secrets or token values in migration output.
|
||||
- [ ] If a legacy state migration fails, continue with clear non-fatal messaging and tell the user what functionality may be degraded until they re-verify.
|
||||
- [x] When startup or doctor rewrites Matrix config, emit a short summary such as:
|
||||
- [x] Matrix plugin upgraded in place
|
||||
- [x] migrated deprecated Matrix config keys
|
||||
- [x] migrated legacy Matrix crypto store
|
||||
- [x] no user action required
|
||||
- [x] When automatic repair is not safe, emit exact commands, not generic warnings.
|
||||
- [x] For custom or stale local plugin paths, point users to the concrete replacement command or path.
|
||||
- [x] Never log secrets or token values in migration output.
|
||||
- [x] If a legacy state migration fails, continue with clear non-fatal messaging and tell the user what functionality may be degraded until they re-verify.
|
||||
|
||||
## Test plan and acceptance criteria
|
||||
|
||||
### Config compatibility
|
||||
|
||||
- [ ] Existing `channels.matrix` single-account config loads unchanged.
|
||||
- [ ] Existing `channels.matrix.accounts.*` config loads unchanged.
|
||||
- [ ] Existing `channels.matrix.defaultAccount` behavior is preserved.
|
||||
- [ ] Existing SecretRef password config continues to validate and resolve.
|
||||
- [ ] Deprecated Matrix-only keys are auto-repaired by startup and doctor with clear change reporting.
|
||||
- [x] Existing `channels.matrix` single-account config loads unchanged.
|
||||
- [x] Existing `channels.matrix.accounts.*` config loads unchanged.
|
||||
- [x] Existing `channels.matrix.defaultAccount` behavior is preserved.
|
||||
- [x] Existing SecretRef password config continues to validate and resolve.
|
||||
- [x] Deprecated Matrix-only keys are auto-repaired by startup and doctor with clear change reporting.
|
||||
|
||||
### State compatibility
|
||||
|
||||
- [ ] Current canonical `credentials/matrix/*` credentials are reused with no prompt.
|
||||
- [ ] Current canonical `matrix/accounts/*` runtime state is reused with no prompt.
|
||||
- [ ] Oldest flat legacy Matrix crypto and sync store is migrated automatically to account-scoped storage.
|
||||
- [ ] Multi-account state remains isolated after migration.
|
||||
- [x] Current canonical `credentials/matrix/*` credentials are reused with no prompt.
|
||||
- [x] Current canonical `matrix/accounts/*` runtime state is reused with no prompt.
|
||||
- [x] Oldest flat legacy Matrix crypto and sync store is migrated automatically to account-scoped storage.
|
||||
- [x] Legacy Matrix encrypted backup material is imported automatically when it can be resolved safely.
|
||||
- [x] Backed-up Matrix room keys are restored automatically on startup after encrypted-state prep.
|
||||
- [x] Multi-account state remains isolated after migration.
|
||||
|
||||
### Plugin and install compatibility
|
||||
|
||||
- [ ] Existing npm-installed `@openclaw/matrix` updates in place and remains enabled.
|
||||
- [ ] `plugins.installs.matrix` continues to update correctly after the cutover.
|
||||
- [ ] Stale custom path installs are detected and produce exact repair messaging.
|
||||
- [x] Existing npm-installed `@openclaw/matrix` updates in place and remains enabled.
|
||||
- [x] `plugins.installs.matrix` continues to update correctly after the cutover.
|
||||
- [x] Stale custom path installs are detected and produce exact repair messaging.
|
||||
|
||||
### Public surface
|
||||
|
||||
- [ ] `openclaw matrix ...` exposes the verification and account commands that the new Matrix implementation owns.
|
||||
- [ ] `matrix.verify.*` gateway methods work.
|
||||
- [ ] All bindings, ACP, thread, and session flows use `matrix`, not `matrix-js`.
|
||||
- [ ] No shipped docs, help, schema output, or package exports reference `matrix-js`.
|
||||
- [x] `openclaw matrix ...` exposes the verification and account commands that the new Matrix implementation owns.
|
||||
- [x] `matrix.verify.*` gateway methods work.
|
||||
- [x] All bindings, ACP, thread, and session flows use `matrix`, not `matrix-js`.
|
||||
- [x] No shipped docs, help, schema output, or package exports reference `matrix-js`.
|
||||
|
||||
### Regression coverage
|
||||
|
||||
- [ ] Startup auto-migration path.
|
||||
- [ ] Doctor `--fix` Matrix migration path.
|
||||
- [ ] Update-triggered doctor path.
|
||||
- [ ] Route bindings and ACP bindings with `match.channel: "matrix"`.
|
||||
- [ ] Thread binding spawn gating and routing on `matrix`.
|
||||
- [ ] Plugin install and update records for `matrix`.
|
||||
- [x] Startup auto-migration path.
|
||||
- [x] Doctor `--fix` Matrix migration path.
|
||||
- [x] Legacy encrypted-state prep and startup restore path.
|
||||
- [x] Update-triggered doctor path.
|
||||
- [x] Route bindings and ACP bindings with `match.channel: "matrix"`.
|
||||
- [x] Thread binding spawn gating and routing on `matrix`.
|
||||
- [x] Plugin install and update records for `matrix`.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- [ ] A current public Matrix user can update and keep using `channels.matrix` without editing config.
|
||||
- [ ] Automatic migration covers every deterministic case.
|
||||
- [ ] Every non-deterministic case produces explicit next steps.
|
||||
- [ ] No public `matrix-js` surface remains in the shipped product.
|
||||
- [x] A current public Matrix user can update and keep using `channels.matrix` without editing config.
|
||||
- [x] Automatic migration covers every deterministic case.
|
||||
- [x] Every non-deterministic case produces explicit next steps.
|
||||
- [x] No public `matrix-js` surface remains in the shipped product.
|
||||
|
||||
## Assumptions and defaults
|
||||
|
||||
|
||||
@@ -651,7 +651,7 @@ Run multiple accounts per channel (each with its own `accountId`):
|
||||
### Other extension channels
|
||||
|
||||
Many extension channels are configured as `channels.<id>` and documented in their dedicated channel pages (for example Feishu, Matrix, LINE, Nostr, Zalo, Nextcloud Talk, Synology Chat, and Twitch).
|
||||
Matrix-js also supports top-level `bindings[]` entries with `type: "acp"` for persistent ACP bindings. Use the Matrix room id or Matrix thread root event id in `match.peer.id`.
|
||||
Matrix also supports top-level `bindings[]` entries with `type: "acp"` for persistent ACP bindings. Use the Matrix room id or Matrix thread root event id in `match.peer.id`.
|
||||
See the full channel index: [Channels](/channels).
|
||||
|
||||
### Group chat mention gating
|
||||
|
||||
243
docs/install/migrating-matrix.md
Normal file
243
docs/install/migrating-matrix.md
Normal file
@@ -0,0 +1,243 @@
|
||||
---
|
||||
summary: "How OpenClaw upgrades the previous Matrix plugin in place, including encrypted-state recovery limits and manual recovery steps."
|
||||
read_when:
|
||||
- Upgrading an existing Matrix installation
|
||||
- Migrating encrypted Matrix history and device state
|
||||
title: "Matrix migration"
|
||||
---
|
||||
|
||||
# Matrix migration
|
||||
|
||||
This page covers upgrades from the previous public `matrix` plugin to the current implementation.
|
||||
|
||||
For most users, the upgrade is in place:
|
||||
|
||||
- the plugin stays `@openclaw/matrix`
|
||||
- the channel stays `matrix`
|
||||
- your config stays under `channels.matrix`
|
||||
- cached credentials stay under `~/.openclaw/credentials/matrix/`
|
||||
- runtime state stays under `~/.openclaw/matrix/`
|
||||
|
||||
You do not need to rename config keys or reinstall the plugin under a new name.
|
||||
|
||||
## What the migration does automatically
|
||||
|
||||
When the gateway starts, and when you run [`openclaw doctor --fix`](/gateway/doctor), OpenClaw tries to repair old Matrix state automatically.
|
||||
|
||||
Automatic migration covers:
|
||||
|
||||
- reusing your cached Matrix credentials
|
||||
- keeping the same account selection and `channels.matrix` config
|
||||
- moving the oldest flat Matrix sync store into the current account-scoped location
|
||||
- moving the oldest flat Matrix crypto store into the current account-scoped location when the target account can be resolved safely
|
||||
- extracting a previously saved Matrix room-key backup decryption key from the old rust crypto store, when that key exists locally
|
||||
- restoring backed-up room keys into the new crypto store on the next Matrix startup
|
||||
|
||||
## What the migration cannot do automatically
|
||||
|
||||
The previous public Matrix plugin did **not** automatically create Matrix room-key backups. It persisted local crypto state and requested device verification, but it did not guarantee that your room keys were backed up to the homeserver.
|
||||
|
||||
That means some encrypted installs can only be migrated partially.
|
||||
|
||||
OpenClaw cannot automatically recover:
|
||||
|
||||
- local-only room keys that were never backed up
|
||||
- encrypted state when the target Matrix account cannot be resolved yet because `homeserver`, `userId`, or `accessToken` are still unavailable
|
||||
- custom plugin path installs that now point at a missing directory
|
||||
- a missing recovery key when the old store had backed-up keys but did not keep the decryption key locally
|
||||
|
||||
If your old installation had local-only encrypted history that was never backed up, some older encrypted messages may remain unreadable after the upgrade.
|
||||
|
||||
## Recommended upgrade flow
|
||||
|
||||
1. Update OpenClaw and the Matrix plugin normally.
|
||||
2. Run:
|
||||
|
||||
```bash
|
||||
openclaw doctor --fix
|
||||
```
|
||||
|
||||
3. Start or restart the gateway.
|
||||
4. Check current verification and backup state:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify status
|
||||
openclaw matrix verify backup status
|
||||
```
|
||||
|
||||
5. If OpenClaw tells you a recovery key is needed, run:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"
|
||||
```
|
||||
|
||||
6. If this device is still unverified, run:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify device "<your-recovery-key>"
|
||||
```
|
||||
|
||||
7. If no server-side key backup exists yet, create one for future recoveries:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify bootstrap
|
||||
```
|
||||
|
||||
## How encrypted migration works
|
||||
|
||||
Encrypted migration is a two-stage process:
|
||||
|
||||
1. Startup or `openclaw doctor --fix` inspects the old Matrix crypto store.
|
||||
2. If a backup decryption key is found, OpenClaw writes it into the new recovery-key flow and marks room-key restore as pending.
|
||||
3. On the next Matrix startup, OpenClaw restores backed-up room keys into the new crypto store automatically.
|
||||
|
||||
If the old store reports room keys that were never backed up, OpenClaw warns instead of pretending recovery succeeded.
|
||||
|
||||
## Common messages and what they mean
|
||||
|
||||
### Upgrade and detection messages
|
||||
|
||||
`Matrix plugin upgraded in place.`
|
||||
|
||||
- Meaning: the old on-disk Matrix state was detected and migrated into the current layout.
|
||||
- What to do: nothing unless the same output also includes warnings.
|
||||
|
||||
`Legacy Matrix state detected at ... but channels.matrix is not configured yet.`
|
||||
|
||||
- Meaning: old Matrix state exists, but OpenClaw cannot map it to a current Matrix account because Matrix is not configured.
|
||||
- What to do: configure `channels.matrix`, then rerun `openclaw doctor --fix` or restart the gateway.
|
||||
|
||||
`Legacy Matrix state detected at ... but the new account-scoped target could not be resolved yet (need homeserver, userId, and access token for channels.matrix...).`
|
||||
|
||||
- Meaning: OpenClaw found old state, but it still cannot determine the exact current account/device root.
|
||||
- What to do: start the gateway once with a working Matrix login, or rerun `openclaw doctor --fix` after cached credentials exist.
|
||||
|
||||
`Matrix legacy sync store not migrated because the target already exists (...)`
|
||||
|
||||
- Meaning: the new account-scoped location already has a sync or crypto store, so OpenClaw did not overwrite it automatically.
|
||||
- What to do: verify that the current account is the correct one before manually removing or moving the conflicting target.
|
||||
|
||||
`Failed migrating Matrix legacy sync store (...)` or `Failed migrating Matrix legacy crypto store (...)`
|
||||
|
||||
- Meaning: OpenClaw tried to move old Matrix state but the filesystem operation failed.
|
||||
- What to do: inspect filesystem permissions and disk state, then rerun `openclaw doctor --fix`.
|
||||
|
||||
`Legacy Matrix encrypted state detected at ... but channels.matrix is not configured yet.`
|
||||
|
||||
- Meaning: OpenClaw found an old encrypted Matrix store, but there is no current Matrix config to attach it to.
|
||||
- What to do: configure `channels.matrix`, then rerun `openclaw doctor --fix` or restart the gateway.
|
||||
|
||||
`Legacy Matrix encrypted state detected at ... but the account-scoped target could not be resolved yet (need homeserver, userId, and access token for channels.matrix...).`
|
||||
|
||||
- Meaning: the encrypted store exists, but OpenClaw cannot safely decide which current account/device it belongs to.
|
||||
- What to do: start the gateway once with a working Matrix login, or rerun `openclaw doctor --fix` after cached credentials are available.
|
||||
|
||||
### Encrypted-state recovery messages
|
||||
|
||||
`matrix: restored X/Y room key(s) from legacy encrypted-state backup`
|
||||
|
||||
- Meaning: backed-up room keys were restored successfully into the new crypto store.
|
||||
- What to do: usually nothing.
|
||||
|
||||
`matrix: N legacy local-only room key(s) were never backed up and could not be restored automatically`
|
||||
|
||||
- Meaning: some old room keys existed only in the old local store and had never been uploaded to Matrix backup.
|
||||
- What to do: expect some old encrypted history to remain unavailable unless you can recover those keys manually from another verified client.
|
||||
|
||||
`Legacy Matrix encrypted state for account "..." has backed-up room keys, but no local backup decryption key was found. Ask the operator to run "openclaw matrix verify backup restore --recovery-key <key>" after upgrade if they have the recovery key.`
|
||||
|
||||
- Meaning: backup exists, but OpenClaw could not recover the recovery key automatically.
|
||||
- What to do: run `openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"`.
|
||||
|
||||
`Failed inspecting legacy Matrix encrypted state for account "...": ...`
|
||||
|
||||
- Meaning: OpenClaw found the old encrypted store, but it could not inspect it safely enough to prepare recovery.
|
||||
- What to do: rerun `openclaw doctor --fix`. If it repeats, keep the old state directory intact and recover using another verified Matrix client plus `openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"`.
|
||||
|
||||
`Legacy Matrix backup key was found for account "...", but .../recovery-key.json already contains a different recovery key. Leaving the existing file unchanged.`
|
||||
|
||||
- Meaning: OpenClaw detected a backup key conflict and refused to overwrite the current recovery-key file automatically.
|
||||
- What to do: verify which recovery key is correct before retrying any restore command.
|
||||
|
||||
`Legacy Matrix encrypted state for account "..." cannot be fully converted automatically because the old rust crypto store does not expose all local room keys for export.`
|
||||
|
||||
- Meaning: this is the hard limit of the old storage format.
|
||||
- What to do: backed-up keys can still be restored, but local-only encrypted history may remain unavailable.
|
||||
|
||||
`matrix: failed restoring room keys from legacy encrypted-state backup: ...`
|
||||
|
||||
- Meaning: the new plugin attempted restore but Matrix returned an error.
|
||||
- What to do: run `openclaw matrix verify backup status`, then retry with `openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"` if needed.
|
||||
|
||||
### Manual recovery messages
|
||||
|
||||
`Backup key is not loaded on this device. Run 'openclaw matrix verify backup restore' to load it and restore old room keys.`
|
||||
|
||||
- Meaning: OpenClaw knows you should have a backup key, but it is not active on this device.
|
||||
- What to do: run `openclaw matrix verify backup restore`, or pass `--recovery-key` if needed.
|
||||
|
||||
`Store a recovery key with 'openclaw matrix verify device <key>', then run 'openclaw matrix verify backup restore'.`
|
||||
|
||||
- Meaning: this device does not currently have the recovery key stored.
|
||||
- What to do: verify the device with your recovery key first, then restore the backup.
|
||||
|
||||
`Backup key mismatch on this device. Re-run 'openclaw matrix verify device <key>' with the matching recovery key.`
|
||||
|
||||
- Meaning: the stored key does not match the active Matrix backup.
|
||||
- What to do: rerun `openclaw matrix verify device "<your-recovery-key>"` with the correct key.
|
||||
|
||||
`Backup trust chain is not verified on this device. Re-run 'openclaw matrix verify device <key>'.`
|
||||
|
||||
- Meaning: the backup exists, but this device does not trust the cross-signing chain strongly enough yet.
|
||||
- What to do: rerun `openclaw matrix verify device "<your-recovery-key>"`.
|
||||
|
||||
`Matrix recovery key is required`
|
||||
|
||||
- Meaning: you tried a recovery step without supplying a recovery key when one was required.
|
||||
- What to do: rerun the command with your recovery key.
|
||||
|
||||
`Invalid Matrix recovery key: ...`
|
||||
|
||||
- Meaning: the provided key could not be parsed or did not match the expected format.
|
||||
- What to do: retry with the exact recovery key from your Matrix client or recovery-key file.
|
||||
|
||||
`Matrix device is still unverified after applying recovery key. Verify your recovery key and ensure cross-signing is available.`
|
||||
|
||||
- Meaning: the key was applied, but the device still could not complete verification.
|
||||
- What to do: confirm you used the correct key and that cross-signing is available on the account, then retry.
|
||||
|
||||
`Matrix key backup is not active on this device after loading from secret storage.`
|
||||
|
||||
- Meaning: secret storage did not produce an active backup session on this device.
|
||||
- What to do: verify the device first, then recheck with `openclaw matrix verify backup status`.
|
||||
|
||||
`Matrix crypto backend cannot load backup keys from secret storage. Verify this device with 'openclaw matrix verify device <key>' first.`
|
||||
|
||||
- Meaning: this device cannot restore from secret storage until device verification is complete.
|
||||
- What to do: run `openclaw matrix verify device "<your-recovery-key>"` first.
|
||||
|
||||
### Custom plugin install messages
|
||||
|
||||
`Matrix is installed from a custom path that no longer exists: ...`
|
||||
|
||||
- Meaning: your plugin install record points at a local path that is gone.
|
||||
- What to do: reinstall with `openclaw plugins install @openclaw/matrix`, or if you are running from a repo checkout, `openclaw plugins install ./extensions/matrix`.
|
||||
|
||||
## If encrypted history still does not come back
|
||||
|
||||
Run these checks in order:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify status --verbose
|
||||
openclaw matrix verify backup status --verbose
|
||||
openclaw matrix verify backup restore --recovery-key "<your-recovery-key>" --verbose
|
||||
```
|
||||
|
||||
If the backup restores successfully but some old rooms are still missing history, those missing keys were probably never backed up by the previous plugin.
|
||||
|
||||
## Related pages
|
||||
|
||||
- [Matrix](/channels/matrix)
|
||||
- [Doctor](/gateway/doctor)
|
||||
- [Migrating](/install/migrating)
|
||||
- [Plugins](/tools/plugin)
|
||||
@@ -79,7 +79,7 @@ Required feature flags for thread-bound ACP:
|
||||
- `acp.dispatch.enabled` is on by default (set `false` to pause ACP dispatch)
|
||||
- Channel-adapter ACP thread-spawn flag enabled (adapter-specific)
|
||||
- Discord: `channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
- Matrix-js: `channels["matrix-js"].threadBindings.spawnAcpSessions=true`
|
||||
- Matrix: `channels["matrix"].threadBindings.spawnAcpSessions=true`
|
||||
- Telegram: `channels.telegram.threadBindings.spawnAcpSessions=true`
|
||||
|
||||
### Thread supporting channels
|
||||
@@ -87,7 +87,7 @@ Required feature flags for thread-bound ACP:
|
||||
- Any channel adapter that exposes session/thread binding capability.
|
||||
- Current built-in support:
|
||||
- Discord threads/channels
|
||||
- Matrix-js room threads and DMs
|
||||
- Matrix room threads and DMs
|
||||
- Telegram topics (forum topics in groups/supergroups and DM topics)
|
||||
- Plugin channels can add support through the same binding interface.
|
||||
|
||||
@@ -100,7 +100,7 @@ For non-ephemeral workflows, configure persistent ACP bindings in top-level `bin
|
||||
- `bindings[].type="acp"` marks a persistent ACP conversation binding.
|
||||
- `bindings[].match` identifies the target conversation:
|
||||
- Discord channel or thread: `match.channel="discord"` + `match.peer.id="<channelOrThreadId>"`
|
||||
- Matrix room or thread: `match.channel="matrix-js"` + `match.peer.id="<roomIdOrThreadRootEventId>"`
|
||||
- Matrix room or thread: `match.channel="matrix"` + `match.peer.id="<roomIdOrThreadRootEventId>"`
|
||||
- Telegram forum topic: `match.channel="telegram"` + `match.peer.id="<chatId>:topic:<topicId>"`
|
||||
- `bindings[].agentId` is the owning OpenClaw agent id.
|
||||
- Optional ACP overrides live under `bindings[].acp`:
|
||||
@@ -378,7 +378,7 @@ Notes:
|
||||
- On non-thread binding surfaces, default behavior is effectively `off`.
|
||||
- Thread-bound spawn requires channel policy support:
|
||||
- Discord: `channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
- Matrix-js: `channels["matrix-js"].threadBindings.spawnAcpSessions=true`
|
||||
- Matrix: `channels["matrix"].threadBindings.spawnAcpSessions=true`
|
||||
- Telegram: `channels.telegram.threadBindings.spawnAcpSessions=true`
|
||||
|
||||
## ACP controls
|
||||
@@ -481,7 +481,7 @@ Core ACP baseline:
|
||||
}
|
||||
```
|
||||
|
||||
Thread binding config is channel-adapter specific. Example for Discord and Matrix-js:
|
||||
Thread binding config is channel-adapter specific. Example for Discord and Matrix:
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -499,7 +499,7 @@ Thread binding config is channel-adapter specific. Example for Discord and Matri
|
||||
spawnAcpSessions: true,
|
||||
},
|
||||
},
|
||||
"matrix-js": {
|
||||
matrix: {
|
||||
threadBindings: {
|
||||
enabled: true,
|
||||
spawnAcpSessions: true,
|
||||
@@ -512,7 +512,7 @@ Thread binding config is channel-adapter specific. Example for Discord and Matri
|
||||
If thread-bound ACP spawn does not work, verify the adapter feature flag first:
|
||||
|
||||
- Discord: `channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
- Matrix-js: `channels["matrix-js"].threadBindings.spawnAcpSessions=true`
|
||||
- Matrix: `channels["matrix"].threadBindings.spawnAcpSessions=true`
|
||||
|
||||
See [Configuration Reference](/gateway/configuration-reference).
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ authoring plugins:
|
||||
`openclaw/plugin-sdk/google-gemini-cli-auth`, `openclaw/plugin-sdk/googlechat`,
|
||||
`openclaw/plugin-sdk/irc`, `openclaw/plugin-sdk/llm-task`,
|
||||
`openclaw/plugin-sdk/lobster`, `openclaw/plugin-sdk/matrix`,
|
||||
`openclaw/plugin-sdk/matrix-js`,
|
||||
`openclaw/plugin-sdk/matrix`,
|
||||
`openclaw/plugin-sdk/mattermost`, `openclaw/plugin-sdk/memory-core`,
|
||||
`openclaw/plugin-sdk/memory-lancedb`,
|
||||
`openclaw/plugin-sdk/minimax-portal-auth`,
|
||||
|
||||
@@ -17,7 +17,7 @@ Channel notes:
|
||||
|
||||
- **Discord/Slack**: empty `emoji` removes all of the bot's reactions on the message; `remove: true` removes just that emoji.
|
||||
- **Google Chat**: empty `emoji` removes the app's reactions on the message; `remove: true` removes just that emoji.
|
||||
- **Matrix-js**: empty `emoji` removes the bot account's own reactions on the message; `remove: true` removes just that emoji; inbound reaction notifications on bot-authored messages are controlled by `reactionNotifications`.
|
||||
- **Matrix**: empty `emoji` removes the bot account's own reactions on the message; `remove: true` removes just that emoji; inbound reaction notifications on bot-authored messages are controlled by `reactionNotifications`.
|
||||
- **Telegram**: empty `emoji` removes the bot's reactions; `remove: true` also removes reactions but still requires a non-empty `emoji` for tool validation.
|
||||
- **WhatsApp**: empty `emoji` removes the bot reaction; `remove: true` maps to empty emoji (still requires `emoji`).
|
||||
- **Zalo Personal (`zalouser`)**: requires non-empty `emoji`; `remove: true` removes that specific emoji reaction.
|
||||
|
||||
@@ -100,7 +100,7 @@ When thread bindings are enabled for a channel, a sub-agent can stay bound to a
|
||||
### Thread supporting channels
|
||||
|
||||
- `sessions_spawn` with `thread: true`: currently supported on Discord only.
|
||||
- Manual thread/conversation controls are supported on Discord, Matrix-js, and Telegram.
|
||||
- Manual thread/conversation controls are supported on Discord, Matrix, and Telegram.
|
||||
- Available controls: `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`
|
||||
|
||||
Quick flow:
|
||||
|
||||
Reference in New Issue
Block a user