← Back to PRs

#18718: matrix: add pending group history context for room messages

by pharasyte open 2026-02-17 00:45 View on GitHub →
docs channel: matrix stale size: S
Pull request summary written by Claude, with relevant adjustments by me. Claude also effected the code changes, although this works out to mostly be copy/paste from the other channel extensions (MSTeams was used as a specific reference). All functions used are common helpers provided by OpenClaw. ## Summary Aims to resolve #18709 - **Problem:** Matrix rooms with mention gating silently drop non-mentioned messages, so the bot has no conversational context when it is finally mentioned. - **Why it matters:** Other channels (Slack, Telegram, MSTeams, Discord) already buffer skipped messages as pending history context. Matrix was the gap — the bot responded to mentions without knowing what the conversation was about. - **What changed:** Skipped room messages are now buffered in-memory and injected as context when the bot is next mentioned, using the same plugin-sdk history utilities as other channels. Config key `channels.matrix.historyLimit` added with fallback to `messages.groupChat.historyLimit` (default 50). Docs updated. - **What did NOT change (scope boundary):** DM handling is untouched. No new dependencies. No changes to the shared plugin-sdk history utilities. No test additions (handler tests don't exist for any channel extension; the underlying utility functions are already tested in core). ## Change Type (select all) - [x] Bug fix - [x] Feature - [ ] Refactor - [x] Docs - [ ] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [ ] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [ ] Memory / storage - [x] Integrations - [ ] API / contracts - [ ] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR - Closes # - Related # ## User-visible / Behavior Changes - New config key: `channels.matrix.historyLimit` (integer, default 50, `0` disables). Also available per-account via `channels.matrix.accounts.<id>.historyLimit`. - Falls back to `messages.groupChat.historyLimit` if the channel-level key is unset. - When mention gating is active in a room, skipped messages are buffered and prepended on the next triggering message. - History buffer is cleared after each bot reply (both `queuedFinal` and `!queuedFinal` paths). - Default behavior with no config changes: history is enabled at 50 messages, matching all other channels. ## Security Impact (required) - New permissions/capabilities? `No` - Secrets/tokens handling changed? `No` - New/changed network calls? `No` - Command/tool execution surface changed? `No` - Data access scope changed? `No` ## Repro + Verification ### Environment - OS: Linux - Runtime/container: Node 22+, pnpm - Model/provider: Anthropic Claude - Integration/channel: Matrix (via @openclaw/matrix plugin, Element client) - Relevant config: `channels.matrix.groupPolicy: "allowlist"`, room allowlisted with `requireMention: true` (default) ### Steps 1. Invite the bot to a Matrix room with mention gating active (default). 2. Send 2–3 messages in the room without mentioning the bot. 3. Mention the bot (e.g. `@bot what were we just talking about?`). ### Expected - Bot reply includes context from the skipped messages. ### Actual - Bot reply correctly references the prior conversation context from buffered messages. ## Evidence - [x] Verified via live gateway. ## Human Verification (required) - **Verified scenarios:** Live tested on a real Matrix room via Element client. Sent multiple unbotted messages, then mentioned the bot. Confirmed history context appeared in the prompt and the bot referenced prior messages in its reply. Verified buffer clears after reply. - **Edge cases checked:** `historyLimit: 0` disables buffering (no context injected). DMs are unaffected (history only applies to `isRoom`). Multi-account history isolation (each account gets its own `roomHistories` map. - **What you did not verify:** Thread interactions with history. Extremely large history buffers near the limit boundary. ## Compatibility / Migration - Backward compatible? `Yes` - Config/env changes? `Yes` — new optional key `channels.matrix.historyLimit` (no action required; defaults to 50 automatically) - Migration needed? `No` ## Failure Recovery (if this breaks) - **How to disable/revert this change quickly:** Set `channels.matrix.historyLimit: 0` in config. This disables all buffering — the bot behaves exactly as before this change. - **Files/config to restore:** Revert commit `6a11fbb233` on the matrix extension. No config migration to undo (historyLimit doesn't seem to be causing errors when it is present prior to the change). - **Known bad symptoms reviewers should watch for:** N/A ## Files Changed | File | Description | |------|-------------| | `extensions/matrix/src/types.ts` | Added `historyLimit?: number` to `MatrixConfig`; added `groupChat?: { historyLimit?: number }` to `CoreConfig.messages` for fallback resolution. | | `extensions/matrix/src/config-schema.ts` | Added `historyLimit: z.number().int().min(0).optional()` Zod validation rule. | | `extensions/matrix/src/matrix/monitor/index.ts` | Imported `DEFAULT_GROUP_HISTORY_LIMIT` and `HistoryEntry` from plugin-sdk. Resolves `historyLimit` with cascade fallback (account → channel → global → default 50). Creates per-monitor `roomHistories` map. Passes both to handler. | | `extensions/matrix/src/matrix/monitor/handler.ts` | Added `historyLimit` and `roomHistories` to params type and destructuring. Records skipped messages via `recordPendingHistoryEntryIfEnabled`. Injects buffered context via `buildPendingHistoryContextFromMap` before dispatch. Clears buffer via `clearHistoryEntriesIfEnabled` after reply (both `queuedFinal` and `!queuedFinal` paths). | | `docs/channels/matrix.md` | Added "History context" section describing the feature, fallback chain, and buffering behavior. Added `channels.matrix.historyLimit` to the configuration reference list. | ## Risks and Mitigations - **Risk:** In-memory `roomHistories` map grows with number of active rooms × `historyLimit` entries per room. - **Mitigation:** Buffer is capped per room (default 50). Entries are cleared on every bot reply. This matches the exact same pattern used by Telegram, Slack, MSTeams, and Discord without reported issues. <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds pending group history context buffering to the Matrix channel extension, closing the gap with Slack, Telegram, MSTeams, and Discord. When mention gating is active in a room, skipped (non-mentioned) messages are now buffered in-memory and injected as context when the bot is next mentioned. - Adds `channels.matrix.historyLimit` config (integer, default 50, `0` disables) with fallback to `messages.groupChat.historyLimit`, matching the resolution chain used by other channels. - Records skipped room messages via `recordPendingHistoryEntryIfEnabled` in the "no-mention" skip path. - Prepends buffered context via `buildPendingHistoryContextFromMap` before dispatch. - Clears buffer via `clearHistoryEntriesIfEnabled` after reply in both `queuedFinal` and `!queuedFinal` paths. - Adds Zod validation (`z.number().int().min(0).optional()`) in config schema. - Updates `CoreConfig` type to include `messages.groupChat.historyLimit` for fallback resolution. - Docs updated with "History context" section and config reference entry. The implementation closely mirrors the MSTeams handler pattern, using the same plugin-sdk history utilities. No new dependencies introduced. The per-monitor `roomHistories` map provides proper isolation for multi-account setups. <h3>Confidence Score: 4/5</h3> - This PR is safe to merge — it follows established patterns from other channel extensions with no new dependencies or risky changes. - Score of 4 reflects that the implementation correctly mirrors existing patterns (MSTeams, Discord, Telegram, Slack) using the same well-tested plugin-sdk utilities. The config resolution chain, history recording, context building, and buffer clearing all follow the established conventions. The only reason this isn't a 5 is the absence of handler-level tests (noted as out of scope since no channel extension has them), and the in-memory buffer growth pattern inheriting the same theoretical unbounded-rooms risk as other channels. - No files require special attention. All changes are consistent with the established patterns from other channel handlers. <sub>Last reviewed commit: 6a11fbb</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs