fix(matrix): implement thread_require_mention to prevent multi-agent reply loops

In multi-agent shared Matrix rooms, multiple bots all participating in the
same thread could trigger infinite reply loops — each bot's reply re-engaged
the others because they were all in the bot-thread set. Discord has a
`thread_require_mention` opt-in for this; Matrix didn't.

Add `_parse_thread_require_mention(config)` (mirrors Discord's pattern).
In `_resolve_message_context`, when enabled and the message is in a
bot-participated thread (not a free-response room), require @mention
before processing.

Salvage of @justemu's 2-commit stack (#27996). Fixes #27995.
This commit is contained in:
justemu 2026-05-19 00:04:03 -07:00 committed by Teknium
parent e2a1a2bf13
commit 276e6cc52d

View file

@ -380,6 +380,7 @@ class MatrixAdapter(BasePlatformAdapter):
self._require_mention: bool = os.getenv(
"MATRIX_REQUIRE_MENTION", "true"
).lower() not in {"false", "0", "no"}
self._thread_require_mention: bool = self._parse_thread_require_mention(config)
free_rooms_raw = config.extra.get("free_response_rooms")
if free_rooms_raw is None:
free_rooms_raw = os.getenv("MATRIX_FREE_RESPONSE_ROOMS", "")
@ -468,6 +469,27 @@ class MatrixAdapter(BasePlatformAdapter):
self._processed_events_set.add(event_id)
return False
@staticmethod
def _parse_thread_require_mention(config) -> bool:
"""Parse thread_require_mention from config.extra or env var.
Handles both YAML booleans and string values (``\"true\"``, ``\"false\"``,
``\"yes\"``, ``\"no\"``, ``\"on\"``, ``\"off\"``, ``\"1\"``, ``\"0\"``).
Falls back to ``MATRIX_THREAD_REQUIRE_MENTION`` env var, default ``false``.
Mirrors Discord adapter's parsing pattern.
"""
configured = config.extra.get("thread_require_mention")
if configured is not None:
if isinstance(configured, bool):
return configured
if isinstance(configured, str):
return configured.lower() not in {"false", "0", "no", "off"}
# int, float, etc. — truthiness fallback
return bool(configured)
return os.getenv(
"MATRIX_THREAD_REQUIRE_MENTION", "false"
).lower() in {"true", "1", "yes", "on"}
# ------------------------------------------------------------------
# E2EE helpers
# ------------------------------------------------------------------
@ -1701,6 +1723,21 @@ class MatrixAdapter(BasePlatformAdapter):
)
return None
# Thread-level @mention gating: even in a bot-participated thread,
# require @mention when thread_require_mention is enabled.
# Prevents infinite reply loops in multi-agent shared rooms
# where multiple bots all participate in the same thread.
elif (self._thread_require_mention and in_bot_thread
and not is_free_room):
if not is_mentioned:
logger.debug(
"Matrix: ignoring message %s in thread %s"
"no @mention (thread_require_mention=true)",
event_id,
thread_id,
)
return None
# DM mention-thread.
if is_dm and not thread_id and self._dm_mention_threads and is_mentioned:
thread_id = event_id