diff --git a/docs/channels/matrix-push-rules.md b/docs/channels/matrix-push-rules.md index f35b2125f97..34081375c87 100644 --- a/docs/channels/matrix-push-rules.md +++ b/docs/channels/matrix-push-rules.md @@ -132,6 +132,8 @@ New user-defined `override` rules are inserted ahead of default suppress rules, If you run Synapse behind a reverse proxy or workers, make sure `/_matrix/client/.../pushrules/` reaches Synapse correctly. Push delivery is handled by the main process or `synapse.app.pusher` / configured pusher workers — ensure those are healthy. + The rule uses the `event_property_is` push-rule condition (MSC3758, push rule v1.10), which was added to Synapse in 2023. Older Synapse releases accept the `PUT pushrules/...` call but silently never match the condition — upgrade Synapse if no notification arrives on a finalized preview edit. + diff --git a/docs/channels/matrix.md b/docs/channels/matrix.md index 8fc47b90383..8a2be43d130 100644 --- a/docs/channels/matrix.md +++ b/docs/channels/matrix.md @@ -11,107 +11,39 @@ It uses the official `matrix-js-sdk` and supports DMs, rooms, threads, media, re ## Bundled plugin -Matrix ships as a bundled plugin in current OpenClaw releases, so normal -packaged builds do not need a separate install. +Current packaged OpenClaw releases ship the Matrix plugin in the box. You do not need to install anything; configuring `channels.matrix.*` (see [Setup](#setup)) is what activates it. -If you are on an older build or a custom install that excludes Matrix, install -it manually: - -Install from npm: +For older builds or custom installs that exclude Matrix, install manually first: ```bash openclaw plugins install @openclaw/matrix -``` - -Install from a local checkout: - -```bash +# or, from a local checkout openclaw plugins install ./path/to/local/matrix-plugin ``` -See [Plugins](/tools/plugin) for plugin behavior and install rules. +`plugins install` registers and enables the plugin, so no separate `openclaw plugins enable matrix` step is needed. The plugin still does nothing until you configure the channel below. See [Plugins](/tools/plugin) for general plugin behavior and install rules. ## Setup -1. Ensure the Matrix plugin is available. - - Current packaged OpenClaw releases already bundle it. - - Older/custom installs can add it manually with the commands above. -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. - - Fresh Matrix invites only work when `channels.matrix.autoJoin` allows them. +1. Create a Matrix account on your homeserver. +2. Configure `channels.matrix` with either `homeserver` + `accessToken`, or `homeserver` + `userId` + `password`. +3. Restart the gateway. +4. Start a DM with the bot, or invite it to a room (see [auto-join](#auto-join) — fresh invites only land when `autoJoin` allows them). -Interactive setup paths: +### Interactive setup ```bash openclaw channels add openclaw configure --section channels ``` -The Matrix wizard asks for: +The wizard asks for: homeserver URL, auth method (access token or password), user ID (password auth only), optional device name, whether to enable E2EE, and whether to configure room access and auto-join. -- homeserver URL -- auth method: access token or password -- user ID (password auth only) -- optional device name -- whether to enable E2EE -- whether to configure room access and invite auto-join +If matching `MATRIX_*` env vars already exist and the selected account has no saved auth, the wizard offers an env-var shortcut. To resolve room names before saving an allowlist, run `openclaw channels resolve --channel matrix "Project Room"`. When E2EE is enabled, the wizard writes the config and runs the same bootstrap as [`openclaw matrix encryption setup`](#encryption-and-verification). -Key wizard behaviors: +### Minimal config -- If Matrix auth env vars already exist and that account does not already have auth saved in config, the wizard offers an env shortcut to keep auth in env vars. -- Account names are normalized to the account ID. For example, `Ops Bot` becomes `ops-bot`. -- DM allowlist entries accept `@user:server` directly; display names only work when live directory lookup finds one exact match. -- Room allowlist entries accept room IDs and aliases directly. Prefer `!room:server` or `#alias:server`; unresolved names are ignored at runtime by allowlist resolution. -- In invite auto-join allowlist mode, use only stable invite targets: `!roomId:server`, `#alias:server`, or `*`. Plain room names are rejected. -- To resolve room names before saving, use `openclaw channels resolve --channel matrix "Project Room"`. -- When setup enables E2EE, OpenClaw writes the encryption config and runs the - same verification bootstrap used by `openclaw matrix encryption setup`. - - -`channels.matrix.autoJoin` defaults to `off`. - -If you leave it unset, the bot will not join invited rooms or fresh DM-style invites, so it will not appear in new groups or invited DMs unless you join manually first. - -Set `autoJoin: "allowlist"` together with `autoJoinAllowlist` to restrict which invites it accepts, or set `autoJoin: "always"` if you want it to join every invite. - -In `allowlist` mode, `autoJoinAllowlist` only accepts `!roomId:server`, `#alias:server`, or `*`. - - -Allowlist example: - -```json5 -{ - channels: { - matrix: { - autoJoin: "allowlist", - autoJoinAllowlist: ["!ops:example.org", "#support:example.org"], - groups: { - "!ops:example.org": { - requireMention: true, - }, - }, - }, - }, -} -``` - -Join every invite: - -```json5 -{ - channels: { - matrix: { - autoJoin: "always", - }, - }, -} -``` - -Minimal token-based setup: +Token-based: ```json5 { @@ -126,7 +58,7 @@ Minimal token-based setup: } ``` -Password-based setup (token is cached after login): +Password-based (the token is cached after first login): ```json5 { @@ -142,48 +74,75 @@ Password-based setup (token is cached after login): } ``` -Matrix stores cached credentials in `~/.openclaw/credentials/matrix/`. -The default account uses `credentials.json`; named accounts use `credentials-.json`. -When cached credentials exist there, OpenClaw treats Matrix as configured for setup, doctor, and channel-status discovery even if current auth is not set directly in config. +### Auto-join -Environment variable equivalents (used when the config key is not set): +`channels.matrix.autoJoin` defaults to `off`. With the default, the bot will not appear in new rooms or DMs from fresh invites until you join manually. -- `MATRIX_HOMESERVER` -- `MATRIX_ACCESS_TOKEN` -- `MATRIX_USER_ID` -- `MATRIX_PASSWORD` -- `MATRIX_DEVICE_ID` -- `MATRIX_DEVICE_NAME` +OpenClaw cannot tell at invite time whether an invited room is a DM or a group, so all invites — including DM-style invites — go through `autoJoin` first. `dm.policy` only applies later, after the bot has joined and the room has been classified. -For non-default accounts, use account-scoped env vars: + +Set `autoJoin: "allowlist"` plus `autoJoinAllowlist` to restrict which invites the bot accepts, or `autoJoin: "always"` to accept every invite. -- `MATRIX__HOMESERVER` -- `MATRIX__ACCESS_TOKEN` -- `MATRIX__USER_ID` -- `MATRIX__PASSWORD` -- `MATRIX__DEVICE_ID` -- `MATRIX__DEVICE_NAME` +`autoJoinAllowlist` only accepts stable targets: `!roomId:server`, `#alias:server`, or `*`. Plain room names are rejected; alias entries are resolved against the homeserver, not against state claimed by the invited room. + -Example for account `ops`: +```json5 +{ + channels: { + matrix: { + autoJoin: "allowlist", + autoJoinAllowlist: ["!ops:example.org", "#support:example.org"], + groups: { + "!ops:example.org": { requireMention: true }, + }, + }, + }, +} +``` -- `MATRIX_OPS_HOMESERVER` -- `MATRIX_OPS_ACCESS_TOKEN` +To accept every invite, use `autoJoin: "always"`. -For normalized account ID `ops-bot`, use: +### Allowlist target formats -- `MATRIX_OPS_X2D_BOT_HOMESERVER` -- `MATRIX_OPS_X2D_BOT_ACCESS_TOKEN` +DM and room allowlists are best populated with stable IDs: -Matrix escapes punctuation in account IDs to keep scoped env vars collision-free. -For example, `-` becomes `_X2D_`, so `ops-prod` maps to `MATRIX_OPS_X2D_PROD_*`. +- DMs (`dm.allowFrom`, `groupAllowFrom`, `groups..users`): use `@user:server`. Display names only resolve when the homeserver directory returns exactly one match. +- Rooms (`groups`, `autoJoinAllowlist`): use `!room:server` or `#alias:server`. Names are resolved best-effort against joined rooms; unresolved entries are ignored at runtime. -The interactive wizard only offers the env-var shortcut when those auth env vars are already present and the selected account does not already have Matrix auth saved in config. +### Account ID normalization + +The wizard converts a friendly name into a normalized account ID. For example, `Ops Bot` becomes `ops-bot`. Punctuation is escaped in scoped env-var names so that two accounts cannot collide: `-` → `_X2D_`, so `ops-prod` maps to `MATRIX_OPS_X2D_PROD_*`. + +### Cached credentials + +Matrix stores cached credentials under `~/.openclaw/credentials/matrix/`: + +- default account: `credentials.json` +- named accounts: `credentials-.json` + +When cached credentials exist there, OpenClaw treats Matrix as configured even if the access token is not in the config file — that covers setup, `openclaw doctor`, and channel-status probes. + +### Environment variables + +Used when the equivalent config key is not set. The default account uses unprefixed names; named accounts use the account ID inserted before the suffix. + +| Default account | Named account (`` is the normalized account ID) | +| --------------------- | --------------------------------------------------- | +| `MATRIX_HOMESERVER` | `MATRIX__HOMESERVER` | +| `MATRIX_ACCESS_TOKEN` | `MATRIX__ACCESS_TOKEN` | +| `MATRIX_USER_ID` | `MATRIX__USER_ID` | +| `MATRIX_PASSWORD` | `MATRIX__PASSWORD` | +| `MATRIX_DEVICE_ID` | `MATRIX__DEVICE_ID` | +| `MATRIX_DEVICE_NAME` | `MATRIX__DEVICE_NAME` | +| `MATRIX_RECOVERY_KEY` | `MATRIX__RECOVERY_KEY` | + +For account `ops`, the names become `MATRIX_OPS_HOMESERVER`, `MATRIX_OPS_ACCESS_TOKEN`, and so on. The recovery-key env vars are read by recovery-aware CLI flows (`verify backup restore`, `verify device`, `verify bootstrap`) when you pipe the key in via `--recovery-key-stdin`. `MATRIX_HOMESERVER` cannot be set from a workspace `.env`; see [Workspace `.env` files](/gateway/security). ## Configuration example -This is a practical baseline config with DM pairing, room allowlist, and E2EE enabled: +A practical baseline with DM pairing, room allowlist, and E2EE: ```json5 { @@ -203,9 +162,7 @@ This is a practical baseline config with DM pairing, room allowlist, and E2EE en groupPolicy: "allowlist", groupAllowFrom: ["@admin:example.org"], groups: { - "!roomid:example.org": { - requireMention: true, - }, + "!roomid:example.org": { requireMention: true }, }, autoJoin: "allowlist", @@ -218,17 +175,9 @@ This is a practical baseline config with DM pairing, room allowlist, and E2EE en } ``` -`autoJoin` applies to all Matrix invites, including DM-style invites. OpenClaw cannot reliably -classify an invited room as a DM or group at invite time, so all invites go through `autoJoin` -first. `dm.policy` applies after the bot has joined and the room is classified as a DM. - ## Streaming previews -Matrix reply streaming is opt-in. - -Set `channels.matrix.streaming` to `"partial"` when you want OpenClaw to send a single live preview -reply, edit that preview in place while the model is generating text, and then finalize it when the -reply is done: +Matrix reply streaming is opt-in. `streaming` controls how OpenClaw delivers the in-flight assistant reply; `blockStreaming` controls whether each completed block is preserved as its own Matrix message. ```json5 { @@ -240,26 +189,28 @@ reply is done: } ``` -- `streaming: "off"` is the default. OpenClaw waits for the final reply and sends it once. -- `streaming: "partial"` creates one editable preview message for the current assistant block using normal Matrix text messages. This preserves Matrix's legacy preview-first notification behavior, so stock clients may notify on the first streamed preview text instead of the finished block. -- `streaming: "quiet"` creates one editable quiet preview notice for the current assistant block. Use this only when you also configure recipient push rules for finalized preview edits. -- `blockStreaming: true` enables separate Matrix progress messages. With preview streaming enabled, Matrix keeps the live draft for the current block and preserves completed blocks as separate messages. -- When preview streaming is on and `blockStreaming` is off, Matrix edits the live draft in place and finalizes that same event when the block or turn finishes. -- If the preview no longer fits in one Matrix event, OpenClaw stops preview streaming and falls back to normal final delivery. -- Media replies still send attachments normally. If a stale preview can no longer be reused safely, OpenClaw redacts it before sending the final media reply. -- Preview edits cost extra Matrix API calls. Leave streaming off if you want the most conservative rate-limit behavior. +| `streaming` | Behavior | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `"off"` (default) | Wait for the full reply, send once. `true` ↔ `"partial"`, `false` ↔ `"off"`. | +| `"partial"` | Edit one normal text message in place as the model writes the current block. Stock Matrix clients may notify on the first preview, not the final edit. | +| `"quiet"` | Same as `"partial"` but the message is a non-notifying notice. Recipients only get a notification once a per-user push rule matches the finalized edit (see below). | -`blockStreaming` does not enable draft previews by itself. -Use `streaming: "partial"` or `streaming: "quiet"` for preview edits; then add `blockStreaming: true` only if you also want completed assistant blocks to remain visible as separate progress messages. +`blockStreaming` is independent of `streaming`: -If you need stock Matrix notifications without custom push rules, use `streaming: "partial"` for preview-first behavior or leave `streaming` off for final-only delivery. With `streaming: "off"`: +| `streaming` | `blockStreaming: true` | `blockStreaming: false` (default) | +| ----------------------- | ------------------------------------------------------------------- | ---------------------------------------------------- | +| `"partial"` / `"quiet"` | Live draft for the current block, completed blocks kept as messages | Live draft for the current block, finalized in place | +| `"off"` | One notifying Matrix message per finished block | One notifying Matrix message for the full reply | -- `blockStreaming: true` sends each finished block as a normal notifying Matrix message. -- `blockStreaming: false` sends only the final completed reply as a normal notifying Matrix message. +Notes: + +- If a preview grows past Matrix's per-event size limit, OpenClaw stops preview streaming and falls back to final-only delivery. +- Media replies always send attachments normally. If a stale preview can no longer be reused safely, OpenClaw redacts it before sending the final media reply. +- Preview edits cost extra Matrix API calls. Leave `streaming: "off"` if you want the most conservative rate-limit profile. ### Self-hosted push rules for quiet finalized previews -Quiet streaming (`streaming: "quiet"`) only notifies recipients once a block or turn is finalized — a per-user push rule has to match the finalized preview marker. See [Matrix push rules for quiet previews](/channels/matrix-push-rules) for the full setup (recipient token, pusher check, rule install, per-homeserver notes). +`streaming: "quiet"` only notifies recipients once a block or turn is finalized — a per-user push rule has to match the finalized preview marker. See [Matrix push rules for quiet previews](/channels/matrix-push-rules) for the full recipe (recipient token, pusher check, rule install, per-homeserver notes). ## Bot-to-bot rooms @@ -294,17 +245,20 @@ Use strict room allowlists and mention requirements when enabling bot-to-bot tra In encrypted (E2EE) rooms, outbound image events use `thumbnail_file` so image previews are encrypted alongside the full attachment. Unencrypted rooms still use plain `thumbnail_url`. No configuration is needed — the plugin detects E2EE state automatically. -Recommended setup flow: +All `openclaw matrix` commands accept `--verbose` (full diagnostics), `--json` (machine-readable output), and `--account ` (multi-account setups). Output is concise by default with quiet internal SDK logging. The examples below show the canonical form; add the flags as needed. + +### Enable encryption ```bash openclaw matrix encryption setup ``` -This enables `channels.matrix.encryption`, bootstraps Matrix secret storage and -cross-signing, creates room-key backup state when needed, then prints the -current verification and backup status with next steps. +Bootstraps secret storage and cross-signing, creates a room-key backup if needed, then prints status and next steps. Useful flags: -For a new account, enable E2EE during account creation: +- `--recovery-key ` apply a recovery key before bootstrapping (prefer the stdin form documented below) +- `--force-reset-cross-signing` discard the current cross-signing identity and create a new one (use only intentionally) + +For a new account, enable E2EE at creation time: ```bash openclaw matrix account add \ @@ -313,11 +267,7 @@ openclaw matrix account add \ --enable-e2ee ``` -Multi-account setups can target a specific account: - -```bash -openclaw matrix encryption setup --account assistant -``` +`--encryption` is an alias for `--enable-e2ee`. Manual config equivalent: @@ -335,191 +285,119 @@ Manual config equivalent: } ``` -Verification commands (all take `--verbose` for diagnostics and `--json` for machine-readable output): +### Status and trust signals ```bash openclaw matrix verify status -``` - -Verbose status (full diagnostics): - -```bash -openclaw matrix verify status --verbose -``` - -Include the stored recovery key in machine-readable output: - -```bash openclaw matrix verify status --include-recovery-key --json ``` -Bootstrap cross-signing and verification state: +`verify status` reports three independent trust signals (`--verbose` shows all of them): + +- `Locally trusted`: trusted by this client only +- `Cross-signing verified`: the SDK reports verification via cross-signing +- `Signed by owner`: signed by your own self-signing key (diagnostic only) + +`Verified by owner` becomes `yes` only when `Cross-signing verified` is `yes`. Local trust or an owner signature alone is not enough. + +`--allow-degraded-local-state` returns best-effort diagnostics without preparing the Matrix account first; useful for offline or partially-configured probes. + +### Verify this device with a recovery key + +The recovery key is sensitive — pipe it via stdin instead of passing it on the command line. Set `MATRIX_RECOVERY_KEY` (or `MATRIX__RECOVERY_KEY` for a named account): + +```bash +printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin +``` + +The command reports three states: + +- `Recovery key accepted`: Matrix accepted the key for secret storage or device trust. +- `Backup usable`: room-key backup can be loaded with the trusted recovery material. +- `Device verified by owner`: this device has full Matrix cross-signing identity trust. + +It exits non-zero when full identity trust is incomplete, even if the recovery key unlocked backup material. In that case, finish self-verification from another Matrix client: + +```bash +openclaw matrix verify self +``` + +`verify self` waits for `Cross-signing verified: yes` before it exits successfully. Use `--timeout-ms ` to tune the wait. + +The literal-key form `openclaw matrix verify device ""` is also accepted, but the key ends up in your shell history. + +### Bootstrap or repair cross-signing ```bash openclaw matrix verify bootstrap ``` -Verbose bootstrap diagnostics: +`verify bootstrap` is the repair and setup command for encrypted accounts. In order, it: -```bash -openclaw matrix verify bootstrap --verbose -``` +- bootstraps secret storage, reusing an existing recovery key when possible +- bootstraps cross-signing and uploads missing public keys +- marks and cross-signs the current device +- creates a server-side room-key backup if one does not already exist -Force a fresh cross-signing identity reset before bootstrapping: +If the homeserver requires UIA to upload cross-signing keys, OpenClaw tries no-auth first, then `m.login.dummy`, then `m.login.password` (requires `channels.matrix.password`). -```bash -openclaw matrix verify bootstrap --force-reset-cross-signing -``` +Useful flags: -Verify this device with a recovery key: +- `--recovery-key-stdin` (pair with `printf '%s\n' "$MATRIX_RECOVERY_KEY" | …`) or `--recovery-key ` +- `--force-reset-cross-signing` to discard the current cross-signing identity (intentional only) -```bash -openclaw matrix verify device "" -``` - -This command reports three separate states: - -- `Recovery key accepted`: Matrix accepted the recovery key for secret storage or device trust. -- `Backup usable`: room-key backup can be loaded with trusted recovery material. -- `Device verified by owner`: the current OpenClaw device has full Matrix cross-signing identity trust. - -`Signed by owner` in verbose or JSON output is diagnostic only. OpenClaw does not -treat that as sufficient unless `Cross-signing verified` is also `yes`. - -The command still exits non-zero when full Matrix identity trust is incomplete, -even if the recovery key can unlock backup material. In that case, complete -self-verification from another Matrix client: - -```bash -openclaw matrix verify self -``` - -Accept the request in another Matrix client, compare the SAS emoji or decimals, -and type `yes` only when they match. The command waits for Matrix to report -`Cross-signing verified: yes` before it exits successfully. - -Use `verify bootstrap --force-reset-cross-signing` only when you intentionally -want to replace the current cross-signing identity. - -Verbose device verification details: - -```bash -openclaw matrix verify device "" --verbose -``` - -Check room-key backup health: +### Room-key backup ```bash openclaw matrix verify backup status +printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin ``` -Verbose backup health diagnostics: +`backup status` shows whether a server-side backup exists and whether this device can decrypt it. `backup restore` imports backed-up room keys into the local crypto store; if the recovery key is already on disk you can omit `--recovery-key-stdin`. -```bash -openclaw matrix verify backup status --verbose -``` - -Restore room keys from server backup: - -```bash -openclaw matrix verify backup restore -``` - -If the backup key is not already loaded on disk, pass the Matrix recovery key: - -```bash -openclaw matrix verify backup restore --recovery-key "" -``` - -Interactive self-verification flow: - -```bash -openclaw matrix verify self -``` - -For lower-level or inbound verification requests, use: - -```bash -openclaw matrix verify accept -openclaw matrix verify start -openclaw matrix verify sas -openclaw matrix verify confirm-sas -``` - -Use `openclaw matrix verify cancel ` to cancel a request. - -Verbose restore diagnostics: - -```bash -openclaw matrix verify backup restore --verbose -``` - -Delete the current server backup and create a fresh backup baseline. If the stored -backup key cannot be loaded cleanly, this reset can also recreate secret storage so -future cold starts can load the new backup key: +To replace a broken backup with a fresh baseline (accepts losing unrecoverable old history; can also recreate secret storage if the current backup secret is unloadable): ```bash openclaw matrix verify backup reset --yes ``` -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. +Add `--rotate-recovery-key` only when you intentionally want the previous recovery key to stop unlocking the fresh backup baseline. -In multi-account setups, Matrix CLI commands use the implicit Matrix default account unless you pass `--account `. -If you configure multiple named accounts, set `channels.matrix.defaultAccount` first or those implicit CLI operations will stop and ask you to choose an account explicitly. -Use `--account` whenever you want verification or device operations to target a named account explicitly: +### Listing, requesting, and responding to verifications ```bash -openclaw matrix verify status --account assistant -openclaw matrix verify backup restore --account assistant -openclaw matrix devices list --account assistant +openclaw matrix verify list ``` -When encryption is disabled or unavailable for a named account, Matrix warnings and verification errors point at that account's config key, for example `channels.matrix.accounts.assistant.encryption`. +Lists pending verification requests for the selected account. + +```bash +openclaw matrix verify request --own-user +openclaw matrix verify request --user-id @ops:example.org --device-id ABCDEF +``` + +Sends a verification request from this OpenClaw account. `--own-user` requests self-verification (you accept the prompt in another Matrix client of the same user); `--user-id`/`--device-id`/`--room-id` target someone else. `--own-user` cannot be combined with the other targeting flags. + +For lower-level lifecycle handling — typically while shadowing inbound requests from another client — these commands act on a specific request `` (printed by `verify list` and `verify request`): + +| Command | Purpose | +| ------------------------------------------ | ------------------------------------------------------------------- | +| `openclaw matrix verify accept ` | Accept an inbound request | +| `openclaw matrix verify start ` | Start the SAS flow | +| `openclaw matrix verify sas ` | Print the SAS emoji or decimals | +| `openclaw matrix verify confirm-sas ` | Confirm that the SAS matches what the other client shows | +| `openclaw matrix verify mismatch-sas ` | Reject the SAS when the emoji or decimals do not match | +| `openclaw matrix verify cancel ` | Cancel; takes optional `--reason ` and `--code ` | + +`accept`, `start`, `sas`, `confirm-sas`, `mismatch-sas`, and `cancel` all accept `--user-id` and `--room-id` as DM follow-up hints when the verification is anchored to a specific direct-message room. + +### Multi-account notes + +Without `--account `, Matrix CLI commands use the implicit default account. If you have multiple named accounts and have not set `channels.matrix.defaultAccount`, they will refuse to guess and ask you to choose. When E2EE is disabled or unavailable for a named account, errors point at that account's config key, for example `channels.matrix.accounts.assistant.encryption`. - - OpenClaw treats a device as verified only when your own cross-signing identity signs it. `verify status --verbose` exposes three trust signals: - - - `Locally trusted`: trusted by this client only - - `Cross-signing verified`: the SDK reports verification via cross-signing - - `Signed by owner`: signed by your own self-signing key - - `Verified by owner` becomes `yes` only when cross-signing verification is present. - Local trust or an owner signature by itself is not enough for OpenClaw to treat - the device as fully verified. - - - - - `verify bootstrap` is the repair and setup command for encrypted accounts. In order, it: - - - bootstraps secret storage, reusing an existing recovery key when possible - - bootstraps cross-signing and uploads missing public cross-signing keys - - marks and cross-signs the current device - - creates a server-side room-key backup if one does not already exist - - If the homeserver requires UIA to upload cross-signing keys, OpenClaw tries no-auth first, then `m.login.dummy`, then `m.login.password` (requires `channels.matrix.password`). Use `--force-reset-cross-signing` only when intentionally discarding the current identity. - - - - - If you want to keep future encrypted messages working and accept losing unrecoverable old history: - -```bash -openclaw matrix verify backup reset --yes -openclaw matrix verify backup status --verbose -openclaw matrix verify status -``` - - Add `--account ` to target a named account. This can also recreate secret storage if the current backup secret cannot be loaded safely. - Add `--rotate-recovery-key` only when you intentionally want the old recovery - key to stop unlocking the fresh backup baseline. - - - - With `encryption: true`, `startupVerification` defaults to `"if-unverified"`. On startup an unverified device requests self-verification in another Matrix client, skipping duplicates and applying a cooldown. Tune with `startupVerificationCooldownHours` or disable with `startupVerification: "off"`. + With `encryption: true`, `startupVerification` defaults to `"if-unverified"`. On startup an unverified device requests self-verification in another Matrix client, skipping duplicates and applying a cooldown (24 hours by default). Tune with `startupVerificationCooldownHours` or disable with `startupVerification: "off"`. Startup also runs a conservative crypto bootstrap pass that reuses the current secret storage and cross-signing identity. If bootstrap state is broken, OpenClaw attempts a guarded repair even without `channels.matrix.password`; if the homeserver requires password UIA, startup logs a warning and stays non-fatal. Already-owner-signed devices are preserved. @@ -537,8 +415,7 @@ openclaw matrix verify status - If `verify status` says the current device is no longer listed on the - homeserver, create a new OpenClaw Matrix device. For password login: + If `verify status` says the current device is no longer listed on the homeserver, create a new OpenClaw Matrix device. For password login: ```bash openclaw matrix account add \ @@ -549,8 +426,7 @@ openclaw matrix account add \ --device-name OpenClaw-Gateway ``` - For token auth, create a fresh access token in your Matrix client or admin UI, - then update OpenClaw: + For token auth, create a fresh access token in your Matrix client or admin UI, then update OpenClaw: ```bash openclaw matrix account add \ @@ -559,8 +435,7 @@ openclaw matrix account add \ --access-token '' ``` - Replace `assistant` with the account ID from the failed command, or omit - `--account` for the default account. + Replace `assistant` with the account ID from the failed command, or omit `--account` for the default account. @@ -584,35 +459,48 @@ openclaw matrix devices prune-stale ## Profile management -Update the Matrix self-profile for the selected account with: +Update the Matrix self-profile for the selected account: ```bash openclaw matrix profile set --name "OpenClaw Assistant" openclaw matrix profile set --avatar-url https://cdn.example.org/avatar.png ``` -Add `--account ` when you want to target a named Matrix account explicitly. - -Matrix accepts `mxc://` avatar URLs directly. When you pass an `http://` or `https://` avatar URL, OpenClaw uploads it to Matrix first and stores the resolved `mxc://` URL back into `channels.matrix.avatarUrl` (or the selected account override). +You can pass both options in one call. Matrix accepts `mxc://` avatar URLs directly; when you pass `http://` or `https://`, OpenClaw uploads the file first and stores the resolved `mxc://` URL into `channels.matrix.avatarUrl` (or the per-account override). ## Threads -Matrix supports native Matrix threads for both automatic replies and message-tool sends. +Matrix supports native Matrix threads for both automatic replies and message-tool sends. Two independent knobs control behavior: + +### Session routing (`sessionScope`) + +`dm.sessionScope` decides how Matrix DM rooms map to OpenClaw sessions: + +- `"per-user"` (default): all DM rooms with the same routed peer share one session. +- `"per-room"`: each Matrix DM room gets its own session key, even when the peer is the same. + +Explicit conversation bindings always win over `sessionScope`, so bound rooms and threads keep their chosen target session. + +### Reply threading (`threadReplies`) + +`threadReplies` decides where the bot posts its reply: + +- `"off"`: replies are top-level. Inbound threaded messages stay on the parent session. +- `"inbound"`: reply inside a thread only when the inbound message was already in that thread. +- `"always"`: reply inside a thread rooted at the triggering message; that conversation is routed through a matching thread-scoped session from the first trigger onward. + +`dm.threadReplies` overrides this for DMs only — for example, keep room threads isolated while keeping DMs flat. + +### Thread inheritance and slash commands -- `dm.sessionScope: "per-user"` (default) keeps Matrix DM routing sender-scoped, so multiple DM rooms can share one session when they resolve to the same peer. -- `dm.sessionScope: "per-room"` isolates each Matrix DM room into its own session key while still using normal DM auth and allowlist checks. -- Explicit Matrix conversation bindings still win over `dm.sessionScope`, so bound rooms and threads keep their chosen target session. -- `threadReplies: "off"` keeps replies top-level and keeps inbound threaded messages on the parent session. -- `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 and routes that conversation through the matching thread-scoped session from the first triggering message. -- `dm.threadReplies` overrides the top-level setting for DMs only. For example, you can keep room threads isolated while keeping DMs flat. - Inbound threaded messages include the thread root message as extra agent context. -- Message-tool sends 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. -- Same-session DM user-target reuse only kicks in when the current session metadata proves the same DM peer on the same Matrix account; otherwise OpenClaw falls back to normal user-scoped routing. -- When OpenClaw sees a Matrix DM room collide with another DM room on the same shared Matrix DM session, it posts a one-time `m.notice` in that room with the `/focus` escape hatch when thread bindings are enabled and the `dm.sessionScope` hint. -- Runtime thread bindings are supported for Matrix. `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, and thread-bound `/acp spawn` 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. +- Message-tool sends auto-inherit the current Matrix thread when targeting the same room (or the same DM user target), unless an explicit `threadId` is provided. +- DM user-target reuse only kicks in when the current session metadata proves the same DM peer on the same Matrix account; otherwise OpenClaw falls back to normal user-scoped routing. +- `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, and thread-bound `/acp spawn` all work in Matrix rooms and DMs. +- Top-level `/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 thread in place. + +When OpenClaw detects a Matrix DM room colliding with another DM room on the same shared session, it posts a one-time `m.notice` in that room pointing to the `/focus` escape hatch and suggesting a `dm.sessionScope` change. The notice only appears when thread bindings are enabled. ## ACP conversation bindings @@ -648,38 +536,24 @@ Matrix thread-bound spawn flags are opt-in: ## Reactions -Matrix supports outbound reaction actions, inbound reaction notifications, and inbound ack reactions. +Matrix supports outbound reactions, inbound reaction notifications, and 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. +Outbound reaction tooling is gated by `channels.matrix.actions.reactions`: -Ack reactions use the standard OpenClaw resolution order: +- `react` adds a reaction to a Matrix event. +- `reactions` lists the current reaction summary for a Matrix event. +- `emoji=""` removes the bot's own reactions on that event. +- `remove: true` removes only the specified emoji reaction from the bot. -- `channels["matrix"].accounts..ackReaction` -- `channels["matrix"].ackReaction` -- `messages.ackReaction` -- agent identity emoji fallback +**Resolution order** (first defined value wins): -Ack reaction scope resolves in this order: +| Setting | Order | +| ----------------------- | -------------------------------------------------------------------------------- | +| `ackReaction` | per-account → channel → `messages.ackReaction` → agent identity emoji fallback | +| `ackReactionScope` | per-account → channel → `messages.ackReactionScope` → default `"group-mentions"` | +| `reactionNotifications` | per-account → channel → default `"own"` | -- `channels["matrix"].accounts..ackReactionScope` -- `channels["matrix"].ackReactionScope` -- `messages.ackReactionScope` - -Reaction notification mode resolves in this order: - -- `channels["matrix"].accounts..reactionNotifications` -- `channels["matrix"].reactionNotifications` -- default: `own` - -Behavior: - -- `reactionNotifications: "own"` forwards added `m.reaction` events when they target bot-authored Matrix messages. -- `reactionNotifications: "off"` disables reaction system events. -- Reaction removals are not synthesized into system events because Matrix surfaces those as redactions, not as standalone `m.reaction` removals. +`reactionNotifications: "own"` forwards added `m.reaction` events when they target bot-authored Matrix messages; `"off"` disables reaction system events. Reaction removals are not synthesized into system events because Matrix surfaces those as redactions, not as standalone `m.reaction` removals. ## History context @@ -714,15 +588,27 @@ Trigger authorization still comes from `groupPolicy`, `groups`, `groupAllowFrom` groupPolicy: "allowlist", groupAllowFrom: ["@admin:example.org"], groups: { - "!roomid:example.org": { - requireMention: true, - }, + "!roomid:example.org": { requireMention: true }, }, }, }, } ``` +To silence DMs entirely while keeping rooms working, set `dm.enabled: false`: + +```json5 +{ + channels: { + matrix: { + dm: { enabled: false }, + groupPolicy: "allowlist", + groupAllowFrom: ["@admin:example.org"], + }, + }, +} +``` + See [Groups](/channels/groups) for mention-gating and allowlist behavior. Pairing example for Matrix DMs: @@ -732,79 +618,63 @@ openclaw pairing list matrix openclaw pairing approve matrix ``` -If an unapproved Matrix user keeps messaging you before approval, OpenClaw reuses the same pending pairing code and may send a reminder reply again after a short cooldown instead of minting a new code. +If an unapproved Matrix user keeps messaging you before approval, OpenClaw reuses the same pending pairing code and may send a reminder reply after a short cooldown instead of minting a new code. See [Pairing](/channels/pairing) for the shared DM pairing flow and storage layout. ## Direct room repair -If direct-message state gets out of sync, OpenClaw can end up with stale `m.direct` mappings that point at old solo rooms instead of the live DM. Inspect the current mapping for a peer with: +If direct-message state drifts out of sync, OpenClaw can end up with stale `m.direct` mappings that point at old solo rooms instead of the live DM. Inspect the current mapping for a peer: ```bash openclaw matrix direct inspect --user-id @alice:example.org ``` -Repair it with: +Repair it: ```bash openclaw matrix direct repair --user-id @alice:example.org ``` -The repair flow: +Both commands accept `--account ` for multi-account setups. The repair flow: - prefers a strict 1:1 DM that is already mapped in `m.direct` - falls back to any currently joined strict 1:1 DM with that user - creates a fresh direct room and rewrites `m.direct` if no healthy DM exists -The repair flow does not delete old rooms automatically. It only picks the healthy DM and updates the mapping so new Matrix sends, verification notices, and other direct-message flows target the right room again. +It does not delete old rooms automatically. It picks the healthy DM and updates the mapping so future Matrix sends, verification notices, and other direct-message flows target the right room. ## Exec approvals -Matrix can act as a native approval client for a Matrix account. The native -DM/channel routing knobs still live under exec approval config: +Matrix can act as a native approval client. Configure under `channels.matrix.execApprovals` (or `channels.matrix.accounts..execApprovals` for a per-account override): -- `channels.matrix.execApprovals.enabled` -- `channels.matrix.execApprovals.approvers` (optional; falls back to `channels.matrix.dm.allowFrom`) -- `channels.matrix.execApprovals.target` (`dm` | `channel` | `both`, default: `dm`) -- `channels.matrix.execApprovals.agentFilter` -- `channels.matrix.execApprovals.sessionFilter` +- `enabled`: deliver approvals through Matrix-native prompts. When unset or `"auto"`, Matrix auto-enables once at least one approver can be resolved. Set `false` to disable explicitly. +- `approvers`: Matrix user IDs (`@owner:example.org`) allowed to approve exec requests. Optional — falls back to `channels.matrix.dm.allowFrom`. +- `target`: where prompts go. `"dm"` (default) sends to approver DMs; `"channel"` sends to the originating Matrix room or DM; `"both"` sends to both. +- `agentFilter` / `sessionFilter`: optional allowlists for which agents/sessions trigger Matrix delivery. -Approvers must be Matrix user IDs such as `@owner:example.org`. Matrix auto-enables native approvals when `enabled` is unset or `"auto"` and at least one approver can be resolved. Exec approvals use `execApprovals.approvers` first and can fall back to `channels.matrix.dm.allowFrom`. Plugin approvals authorize through `channels.matrix.dm.allowFrom`. Set `enabled: false` to disable Matrix as a native approval client explicitly. Approval requests otherwise fall back to other configured approval routes or the approval fallback policy. +Authorization differs slightly between approval kinds: -Matrix native routing supports both approval kinds: +- **Exec approvals** use `execApprovals.approvers`, falling back to `dm.allowFrom`. +- **Plugin approvals** authorize through `dm.allowFrom` only. -- `channels.matrix.execApprovals.*` controls the native DM/channel fanout mode for Matrix approval prompts. -- Exec approvals use the exec approver set from `execApprovals.approvers` or `channels.matrix.dm.allowFrom`. -- Plugin approvals use the Matrix DM allowlist from `channels.matrix.dm.allowFrom`. -- Matrix reaction shortcuts and message updates apply to both exec and plugin approvals. +Both kinds share Matrix reaction shortcuts and message updates. Approvers see reaction shortcuts on the primary approval message: -Delivery rules: +- `✅` allow once +- `❌` deny +- `♾️` allow always (when the effective exec policy allows it) -- `target: "dm"` sends approval prompts to approver DMs -- `target: "channel"` sends the prompt back to the originating Matrix room or DM -- `target: "both"` sends to approver DMs and the originating Matrix room or DM +Fallback slash commands: `/approve allow-once`, `/approve allow-always`, `/approve deny`. -Matrix approval prompts seed reaction shortcuts on the primary approval message: +Only resolved approvers can approve or deny. Channel delivery for exec approvals includes the command text — only enable `channel` or `both` in trusted rooms. -- `✅` = allow once -- `❌` = deny -- `♾️` = allow always when that decision is allowed by the effective exec policy - -Approvers can react on that message or use the fallback slash commands: `/approve allow-once`, `/approve allow-always`, or `/approve deny`. - -Only resolved approvers can approve or deny. For exec approvals, channel delivery includes the command text, so only enable `channel` or `both` in trusted rooms. - -Per-account override: - -- `channels.matrix.accounts..execApprovals` - -Related docs: [Exec approvals](/tools/exec-approvals) +Related: [Exec approvals](/tools/exec-approvals). ## Slash commands -Matrix slash commands (for example `/new`, `/reset`, `/model`) work directly in DMs. In rooms, OpenClaw also recognizes slash commands that are prefixed with the bot's own Matrix mention, so `@bot:server /new` triggers the command path without needing a custom mention regex. This keeps the bot responsive to room-style `@mention /command` posts that Element and similar clients emit when a user tab-completes the bot before typing the command. +Slash commands (`/new`, `/reset`, `/model`, `/focus`, `/unfocus`, `/agents`, `/session`, `/acp`, `/approve`, etc.) work directly in DMs. In rooms, OpenClaw also recognizes commands that are prefixed with the bot's own Matrix mention, so `@bot:server /new` triggers the command path without a custom mention regex. This keeps the bot responsive to the room-style `@mention /command` posts that Element and similar clients emit when a user tab-completes the bot before typing the command. -Authorization rules still apply: command senders must satisfy DM or room allowlist/owner policies just like plain messages. +Authorization rules still apply: command senders must satisfy the same DM or room allowlist/owner policies as plain messages. ## Multi-account @@ -836,15 +706,21 @@ Authorization rules still apply: command senders must satisfy DM or room allowli } ``` -Top-level `channels.matrix` values act as defaults for named accounts unless an account overrides them. -You can scope inherited room entries to one Matrix account with `groups..account`. -Entries without `account` stay shared across all Matrix accounts, and entries with `account: "default"` still work when the default account is configured directly on top-level `channels.matrix.*`. -Partial shared auth defaults do not create a separate implicit default account by themselves. OpenClaw only synthesizes the top-level `default` account when that default has fresh auth (`homeserver` plus `accessToken`, or `homeserver` plus `userId` and `password`); named accounts can still stay discoverable from `homeserver` plus `userId` when cached credentials satisfy auth later. -If Matrix already has exactly one named account, or `defaultAccount` points at an existing named account key, single-account-to-multi-account repair/setup promotion preserves that account instead of creating a fresh `accounts.default` entry. Only Matrix auth/bootstrap keys move into that promoted account; shared delivery-policy keys stay at the top level. -Set `defaultAccount` when you want OpenClaw to prefer one named Matrix account for implicit routing, probing, and CLI operations. -If multiple Matrix accounts are configured and one account id is `default`, OpenClaw uses that account implicitly even when `defaultAccount` is unset. -If you configure multiple named accounts, set `defaultAccount` or pass `--account ` for CLI commands that rely on implicit account selection. -Pass `--account ` to `openclaw matrix verify ...` and `openclaw matrix devices ...` when you want to override that implicit selection for one command. +**Inheritance:** + +- Top-level `channels.matrix` values act as defaults for named accounts unless an account overrides them. +- Scope an inherited room entry to a specific account with `groups..account`. Entries without `account` are shared across accounts; `account: "default"` still works when the default account is configured at the top level. + +**Default account selection:** + +- Set `defaultAccount` to pick the named account that implicit routing, probing, and CLI commands prefer. +- If you have multiple accounts and one is literally named `default`, OpenClaw uses it implicitly even when `defaultAccount` is unset. +- If you have multiple named accounts and no default is selected, CLI commands refuse to guess — set `defaultAccount` or pass `--account `. +- The top-level `channels.matrix.*` block is only treated as the implicit `default` account when its auth is complete (`homeserver` + `accessToken`, or `homeserver` + `userId` + `password`). Named accounts remain discoverable from `homeserver` + `userId` once cached credentials cover auth. + +**Promotion:** + +- When OpenClaw promotes a single-account config to multi-account during repair or setup, it preserves the existing named account if one exists or `defaultAccount` already points at one. Only Matrix auth/bootstrap keys move into the promoted account; shared delivery-policy keys stay at the top level. See [Configuration reference](/gateway/config-channels#multi-account-all-channels) for the shared multi-account pattern. @@ -923,62 +799,84 @@ Live directory lookup uses the logged-in Matrix account: ## Configuration reference +Allowlist-style fields (`groupAllowFrom`, `dm.allowFrom`, `groups..users`) accept full Matrix user IDs (safest). Exact directory matches are resolved at startup and whenever the allowlist changes while the monitor is running; entries that cannot be resolved are ignored at runtime. Room allowlists prefer room IDs or aliases for the same reason. + +### Account and connection + - `enabled`: enable or disable the channel. -- `name`: optional label for the account. +- `name`: optional display label for the account. - `defaultAccount`: preferred account ID when multiple Matrix accounts are configured. +- `accounts`: named per-account overrides. Top-level `channels.matrix` values are inherited as defaults. - `homeserver`: homeserver URL, for example `https://matrix.example.org`. -- `network.dangerouslyAllowPrivateNetwork`: allow this Matrix account to connect to private/internal homeservers. Enable this when the homeserver resolves to `localhost`, a LAN/Tailscale IP, or an internal host such as `matrix-synapse`. -- `proxy`: optional HTTP(S) proxy URL for Matrix traffic. Named accounts can override the top-level default with their own `proxy`. -- `userId`: full Matrix user ID, for example `@bot:example.org`. -- `accessToken`: access token for token-based auth. Plaintext values and SecretRef values are supported for `channels.matrix.accessToken` and `channels.matrix.accounts..accessToken` across env/file/exec providers. See [Secrets Management](/gateway/secrets). -- `password`: password for password-based login. Plaintext values and SecretRef values are supported. +- `network.dangerouslyAllowPrivateNetwork`: allow this account to connect to `localhost`, LAN/Tailscale IPs, or internal hostnames. +- `proxy`: optional HTTP(S) proxy URL for Matrix traffic. Per-account override supported. +- `userId`: full Matrix user ID (`@bot:example.org`). +- `accessToken`: access token for token-based auth. Plaintext and SecretRef values supported across env/file/exec providers ([Secrets Management](/gateway/secrets)). +- `password`: password for password-based login. Plaintext and SecretRef values supported. - `deviceId`: explicit Matrix device ID. -- `deviceName`: device display name for password login. +- `deviceName`: device display name used at password-login time. - `avatarUrl`: stored self-avatar URL for profile sync and `profile set` updates. - `initialSyncLimit`: maximum number of events fetched during startup sync. -- `encryption`: enable E2EE. -- `allowlistOnly`: when `true`, upgrades `open` room policy to `allowlist`, and forces all active DM policies except `disabled` (including `pairing` and `open`) to `allowlist`. Does not affect `disabled` policies. -- `allowBots`: allow messages from other configured OpenClaw Matrix accounts (`true` or `"mentions"`). -- `groupPolicy`: `open`, `allowlist`, or `disabled`. -- `contextVisibility`: supplemental room-context visibility mode (`all`, `allowlist`, `allowlist_quote`). -- `groupAllowFrom`: allowlist of user IDs for room traffic. Full Matrix user IDs are safest; exact directory matches are resolved at startup and when the allowlist changes while the monitor is running. Unresolved names are ignored. -- `historyLimit`: max room messages to include as group history context. Falls back to `messages.groupChat.historyLimit`; if both are unset, the effective default is `0`. Set `0` to disable. -- `replyToMode`: `off`, `first`, `all`, or `batched`. -- `markdown`: optional Markdown rendering configuration for outbound Matrix text. -- `streaming`: `off` (default), `"partial"`, `"quiet"`, `true`, or `false`. `"partial"` and `true` enable preview-first draft updates with normal Matrix text messages. `"quiet"` uses non-notifying preview notices for self-hosted push-rule setups. `false` is equivalent to `"off"`. -- `blockStreaming`: `true` enables separate progress messages for completed assistant blocks while draft preview streaming is active. -- `threadReplies`: `off`, `inbound`, or `always`. + +### Encryption + +- `encryption`: enable E2EE. Default: `false`. +- `startupVerification`: `"if-unverified"` (default when E2EE is on) or `"off"`. Auto-requests self-verification on startup when this device is unverified. +- `startupVerificationCooldownHours`: cooldown before the next automatic startup request. Default: `24`. + +### Access and policy + +- `groupPolicy`: `"open"`, `"allowlist"`, or `"disabled"`. Default: `"allowlist"`. +- `groupAllowFrom`: allowlist of user IDs for room traffic. +- `dm.enabled`: when `false`, ignore all DMs. Default: `true`. +- `dm.policy`: `"pairing"` (default), `"allowlist"`, `"open"`, or `"disabled"`. Applies after the bot has joined and classified the room as a DM; it does not affect invite handling. +- `dm.allowFrom`: allowlist of user IDs for DM traffic. +- `dm.sessionScope`: `"per-user"` (default) or `"per-room"`. +- `dm.threadReplies`: DM-only override for reply threading (`"off"`, `"inbound"`, `"always"`). +- `allowBots`: accept messages from other configured Matrix bot accounts (`true` or `"mentions"`). +- `allowlistOnly`: when `true`, forces all active DM policies (except `"disabled"`) and `"open"` group policies to `"allowlist"`. Does not change `"disabled"` policies. +- `autoJoin`: `"always"`, `"allowlist"`, or `"off"`. Default: `"off"`. Applies to every Matrix invite, including DM-style invites. +- `autoJoinAllowlist`: rooms/aliases allowed when `autoJoin` is `"allowlist"`. Alias entries are resolved against the homeserver, not against state claimed by the invited room. +- `contextVisibility`: supplemental context visibility (`"all"` default, `"allowlist"`, `"allowlist_quote"`). + +### Reply behavior + +- `replyToMode`: `"off"`, `"first"`, `"all"`, or `"batched"`. +- `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 in characters (applies when `chunkMode` is `length`). -- `chunkMode`: `length` splits messages by character count; `newline` splits at line boundaries. -- `responsePrefix`: optional string prepended to all outbound replies for this channel. -- `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`: media size cap in MB for outbound sends and inbound media processing. -- `autoJoin`: invite auto-join policy (`always`, `allowlist`, `off`). Default: `off`. Applies to all Matrix invites, including DM-style invites. -- `autoJoinAllowlist`: rooms/aliases allowed when `autoJoin` is `allowlist`. Alias entries are resolved to room IDs during invite handling; OpenClaw does not trust alias state claimed by the invited room. -- `dm`: DM policy block (`enabled`, `policy`, `allowFrom`, `sessionScope`, `threadReplies`). -- `dm.policy`: controls DM access after OpenClaw has joined the room and classified it as a DM. It does not change whether an invite is auto-joined. -- `dm.allowFrom`: allowlist of user IDs for DM traffic. Full Matrix user IDs are safest; exact directory matches are resolved at startup and when the allowlist changes while the monitor is running. Unresolved names are ignored. -- `dm.sessionScope`: `per-user` (default) or `per-room`. Use `per-room` when you want each Matrix DM room to keep separate context even if the peer is the same. -- `dm.threadReplies`: DM-only thread policy override (`off`, `inbound`, `always`). It overrides the top-level `threadReplies` setting for both reply placement and session isolation in DMs. -- `execApprovals`: Matrix-native exec approval delivery (`enabled`, `approvers`, `target`, `agentFilter`, `sessionFilter`). -- `execApprovals.approvers`: Matrix user IDs allowed to approve exec requests. Optional when `dm.allowFrom` already identifies the approvers. -- `execApprovals.target`: `dm | channel | both` (default: `dm`). -- `accounts`: named per-account overrides. Top-level `channels.matrix` values act as defaults for these entries. -- `groups`: per-room policy map. Prefer room IDs or aliases; unresolved room names are ignored at runtime. Session/group identity uses the stable room ID after resolution. -- `groups..account`: restrict one inherited room entry to a specific Matrix account in multi-account setups. -- `groups..allowBots`: room-level override for configured-bot senders (`true` or `"mentions"`). -- `groups..users`: per-room sender allowlist. -- `groups..tools`: per-room tool allow/deny overrides. -- `groups..autoReply`: room-level mention-gating override. `true` disables mention requirements for that room; `false` forces them back on. -- `groups..skills`: optional room-level skill filter. -- `groups..systemPrompt`: optional room-level system prompt snippet. -- `rooms`: legacy alias for `groups`. +- `streaming`: `"off"` (default), `"partial"`, `"quiet"`. `true` ↔ `"partial"`, `false` ↔ `"off"`. +- `blockStreaming`: when `true`, completed assistant blocks are kept as separate progress messages. +- `markdown`: optional Markdown rendering config for outbound text. +- `responsePrefix`: optional string prepended to outbound replies. +- `textChunkLimit`: outbound chunk size in characters when `chunkMode: "length"`. Default: `4000`. +- `chunkMode`: `"length"` (default, splits by character count) or `"newline"` (splits at line boundaries). +- `historyLimit`: number of recent room messages included as `InboundHistory` when a room message triggers the agent. Falls back to `messages.groupChat.historyLimit`; effective default `0` (disabled). +- `mediaMaxMb`: media size cap in MB for outbound sends and inbound processing. + +### Reactions + +- `ackReaction`: ack reaction override for this channel/account. +- `ackReactionScope`: scope override (`"group-mentions"` default, `"group-all"`, `"direct"`, `"all"`, `"none"`, `"off"`). +- `reactionNotifications`: inbound reaction notification mode (`"own"` default, `"off"`). + +### Tooling and per-room overrides + - `actions`: per-action tool gating (`messages`, `reactions`, `pins`, `profile`, `memberInfo`, `channelInfo`, `verification`). +- `groups`: per-room policy map. Session identity uses the stable room ID after resolution. (`rooms` is a legacy alias.) + - `groups..account`: restrict one inherited room entry to a specific account. + - `groups..allowBots`: per-room override of the channel-level setting (`true` or `"mentions"`). + - `groups..users`: per-room sender allowlist. + - `groups..tools`: per-room tool allow/deny overrides. + - `groups..autoReply`: per-room mention-gating override. `true` disables mention requirements for that room; `false` forces them back on. + - `groups..skills`: per-room skill filter. + - `groups..systemPrompt`: per-room system prompt snippet. + +### Exec approvals + +- `execApprovals.enabled`: deliver exec approvals through Matrix-native prompts. +- `execApprovals.approvers`: Matrix user IDs allowed to approve. Falls back to `dm.allowFrom`. +- `execApprovals.target`: `"dm"` (default), `"channel"`, or `"both"`. +- `execApprovals.agentFilter` / `execApprovals.sessionFilter`: optional agent/session allowlists for delivery. ## Related