Repository navigation
Conversation
Two related config knobs for the Matrix adapter, both defaulting to the current behavior so upgrades are no-ops: matrix.read_receipts (immediate | after_processing | disabled) Controls when an m.read receipt is sent for an inbound message. "immediate" (default) marks read on arrival; "after_processing" defers the receipt until the agent finishes the turn (skipped on cancel); "disabled" never sends one. On Beeper the receipt propagates to every bridged network, so this lets you stop bridged chats from showing messages as read the instant the gateway ingests them. matrix.reactions (bool, default true) Toggles the lifecycle reactions (eyes on start, checkmark/cross on completion). Set false to stop annotating every processed message. Both read from config.yaml and honor the legacy MATRIX_READ_RECEIPTS / MATRIX_REACTIONS env vars as a fallback (YAML wins when both are set). Mode parsing is back-compatible with the earlier boolean spelling. Adds parser helpers (_parse_read_receipts_mode, _parse_reactions_enabled) with regression tests covering YAML/env precedence, legacy spellings, whitespace/case handling, and the three receipt behaviors on arrival/completion/cancel.
ZoloZiak
force-pushed
the
pr-matrix-read-receipts
branch
from
September 24, 2026 10:15
55c0710 to
a892fd4
Compare
Author
|
Closing as superseded by #126283. That PR reimplements this exact feature — per-profile Left a note on #126283 in case the config slice is ever wanted as a smaller standalone fallback. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Matrix adapter automatically annotates every incoming message the moment the gateway processes it, in two independent ways, and neither could be configured from
config.yaml:m.readreceipt / fully-read marker is sent on arrival (_resolve_message_context).on_processing_start/on_processing_complete).This is especially disruptive on Beeper: both signals propagate through the bridge to the underlying network (Messenger / Instagram / WhatsApp / …). So every bridged conversation gets marked read and stamped with a visible checkmark the instant the bot ingests a message — regardless of whether the human operator has actually seen or replied to it. For a bot that passively watches many rooms, this silently annotates everything, everywhere.
This PR makes both behaviors configurable under the
matrixconfig namespace, per the repository policy that non-secret behavioral configuration belongs inconfig.yamlrather than an environment variable.matrix.read_receipts(three modes)immediate(default)after_processingdisabledafter_processingdefers the receipt toon_processing_complete, independent of the reaction lifecycle and skipped on cancellation. The legacyMATRIX_READ_RECEIPTSenv var is honored as a fallback; the YAML value wins when both are set. Legacy boolean spellings map truthy →immediate, falsy →disabled.matrix.reactions(boolean, defaulttrue)Promotes the previously env-only
MATRIX_REACTIONStoggle to aconfig.yamlboolean.true(default) keeps the historical eyes/checkmark lifecycle;falsedisables both the 👀 on start and the ✅/❌ on completion. The legacyMATRIX_REACTIONSenv var remains a fallback, with YAML winning.Both settings are bridged through the existing
_apply_yaml_confighook (matrix:YAML →MATRIX_*env, env taking precedence), the same mechanism already used byauto_thread,session_scope, etc.Files changed
plugins/platforms/matrix/adapter.py_parse_read_receipts_mode+_parse_reactions_enabledhelpers; gate immediate receipt; deferred receipt inon_processing_complete;matrix.read_receipts/matrix.reactions→ env bridges in_apply_yaml_confighermes_cli/config_defaults.pymatrix.read_receipts(immediate) andmatrix.reactions(true) defaultshermes_cli/config.pyMATRIX_READ_RECEIPTS/MATRIX_REACTIONSin the known-env allowlist sodoctordoesn't flag the internal bridge varstests/gateway/test_matrix.pyTests
23 new tests, all passing (
TestMatrixReadReceiptsMode×13,TestMatrixReactionsToggle×10):immediatesends on arrival,disablednever sends,after_processingdefers and sends on success but is skipped on cancellation,immediatedoes not double-send at completion.off/no/0/…), case/whitespace tolerance, env fallback, YAML-wins-over-env; behavior: eyes on start / checkmark on success only when enabled, nothing when disabled.(The Matrix backend has no
pytestin the venv here; tests were run via a standalone runner importing the classes and executing sync + async methods — 23 passed, 0 failed.)Compatibility
read_receipts: immediate,reactions: true) — no change for existing deployments.