NousResearch/hermes-agent

Telegram ignored threads config feature request

Cluster 9208. Data as of

Nothing open on GitHub. Fix merged in #9530 on 14 Apr 2026. Check it covers your case.

The short answer

0open issues
0open PRs
3items grouped
Known?
Yes. 3 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #9530. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #9530. That is separate from the fix event.
Still open
Nothing open on GitHub.

These items all concern adding an ignored_threads configuration option to the Telegram gateway for filtering specific topics or threads. The group includes a feature request and related implementation pull requests.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #9530 feat(gateway): add ignored_threads config for Telegram

    merged to main

    files: gateway/config.py, gateway/platforms/telegram.py, tests/gateway/test_telegram_group_gating.py

    Show the diff
    • gateway/config.py
      @@ -625,6 +625,11 @@ def load_gateway_config() -> GatewayConfig:
                           if isinstance(frc, list):
                               frc = ",".join(str(v) for v in frc)
                           os.environ["TELEGRAM_FREE_RESPONSE_CHATS"] = str(frc)
      +                ignored_threads = telegram_cfg.get("ignored_threads")
      +                if ignored_threads is not None and not os.getenv("TELEGRAM_IGNORED_THREADS"):
      +                    if isinstance(ignored_threads, list):
      +                        ignored_threads = ",".join(str(v) for v in ignored_threads)
      +                    os.environ["TELEGRAM_IGNORED_THREADS"] = str(ignored_threads)
                       if "reactions" in telegram_cfg and not os.getenv("TELEGRAM_REACTIONS"):
                           os.environ["TELEGRAM_REACTIONS"] = str(telegram_cfg["reactions"]).lower()
       
    • gateway/platforms/telegram.py
      @@ -1991,6 +1991,27 @@ def _telegram_free_response_chats(self) -> set[str]:
                   return {str(part).strip() for part in raw if str(part).strip()}
               return {part.strip() for part in str(raw).split(",") if part.strip()}
       
      +    def _telegram_ignored_threads(self) -> set[int]:
      +        raw = self.config.extra.get("ignored_threads")
      +        if raw is None:
      +            raw = os.getenv("TELEGRAM_IGNORED_THREADS", "")
      +
      +        if isinstance(raw, list):
      +            values = raw
      +        else:
      +            values = str(raw).split(",")
      +
      +        ignored: set[int] = set()
      +        for value in values:
      +            text = str(value).strip()
      +            if not text:
      +                continue
      +            try:
      +                ignored.add(int(text))
      +            except (TypeError, ValueError):
      +                logger.warning("[%s] Ignoring invalid Telegram thread id: %r", self.name, value)
      +        return ignored
      +
           def _compile_mention_patterns(self) -> List[re.Pattern]:
               """Compile optional regex wake-word patterns for group triggers."""
               patterns = self.config.extra.get("mention_patterns")
      @@ -2102,6 +2123,13 @@ def _should_process_message(self, message: Message, *, is_command: bool = False)
               """
               if not self._is_group_chat(message):
                   return True
      +        thread_id = getattr(message, "message_thread_id", None)
      +        if thread_id is not None:
      +            try:
      +                if int(thread_id) in self._telegram_ignored_threads():
      +                    return False
      +            except (TypeError, ValueError):
      +                logger.warning("[%s] Ignoring non-numeric Telegram message_thread_id: %r", self.name, thread_id)
               if str(getattr(getattr(message, "chat", None), "id", "")) in self._telegram_free_response_chats():
                   return True
               if not self._telegram_require_mention():
    • tests/gateway/test_telegram_group_gating.py
      @@ -5,7 +5,7 @@
       from gateway.config import Platform, PlatformConfig, load_gateway_config
       
       
      -def _make_adapter(require_mention=None, free_response_chats=None, mention_patterns=None):
      +def _make_adapter(require_mention=None, free_response_chats=None, mention_patterns=None, ignored_threads=None):
           from gateway.platforms.telegram import TelegramAdapter
       
           extra = {}
      @@ -15,6 +15,8 @@ def _make_adapter(require_mention=None, free_response_chats=None, mention_patter
               extra["free_response_chats"] = free_response_chats
           if mention_patterns is not None:
               extra["mention_patterns"] = mention_patterns
      +    if ignored_threads is not None:
      +        extra["ignored_threads"] = ignored_threads
       
           adapter = object.__new__(TelegramAdapter)
           adapter.platform = Platform.TELEGRAM
      @@ -28,7 +30,16 @@ def _make_adapter(require_mention=None, free_response_chats=None, mention_patter
           return adapter
       
       
      -def _group_message(text="hello", *, chat_id=-100, reply_to_bot=False, entities=None, caption=None, caption_entities=None):
      +def _group_message(
      +    text="hello",
      +    *,
      +    chat_id=-100,
      +    thread_id=None,
      +    reply_to_bot=False,
      +    entities=None,
      +    caption=None,
      +    caption_entities=None,
      +):
           reply_to_message = None
           if reply_to_bot:
               reply_to_message = SimpleNamespace(from_user=SimpleNamespace(id=999))
      @@ -37,6 +48,7 @@ def _group_message(text="hello", *, chat_id=-100, reply_to_bot=False, entities=N
               caption=caption,
               entities=entities or [],
               caption_entities=caption_entities or [],
      +        message_thread_id=thread_id,
               chat=SimpleNamespace(id=chat_id, type="group"),
               reply_to_message=reply_to_message,
           )
      @@ -69,6 +81,14 @@ def test_free_response_chats_bypass_mention_requirement():
           assert adapter._should_process_message(_group_message("hello everyone", chat_id=-201)) is False
       
       
      +def test_ignored_threads_drop_group_messages_before_other_gates():
      +    adapter = _make_adapter(require_mention=False, free_response_chats=["-200"], ignored_threads=[31, "42"])
      +
      +    assert adapter._should_process_message(_group_message("hello everyone", chat_id=-200, thread_id=31)) is False
      +    assert adapter._should_process_message(_group_message("hello everyone", chat_id=-200, thread_id=42)) is False
      +    assert adapter._should_process_message(_group_message("hello everyone", chat_id=-200, thread_id=99)) is True
      +
      +
       def test_regex_mention_patterns_allow_custom_wake_words():
           adapter = _make_adapter(require_mention=True, mention_patterns=[r"^\s*chompy\b"])
       
      @@ -108,3 +128,23 @@ def test_config_bridges_telegram_group_settings(monkeypatch, tmp_path):
           assert __import__("os").environ["TELEGRAM_REQUIRE_MENTION"] == "true"
           assert json.loads(__import__("os").environ["TELEGRAM_MENTION_PATTERNS"]) == [r"^\s*chompy\b"]
           assert __import__("os").environ["TELEGRAM_FREE_RESPONSE_CHATS"] == "-123"
      +
      +
      +def test_config_bridges_telegram_ignored_threads(monkeypatch, tmp_path):
      +    hermes_home = tmp_path / ".hermes"
      +    hermes_home.mkdir()
      +    (hermes_home / "config.yaml").write_text(
      +        "telegram:\n"
      +        "  ignored_threads:\n"
      +        "    - 31\n"
      +        "    - \"42\"\n",
      +        encoding="utf-8",
      +    )
      +
      +    monkeypatch.setenv("HERMES_HOME", str(hermes_home))
      +    monkeypatch.delenv("TELEGRAM_IGNORED_THREADS", raising=False)
      +
      +    config = load_gateway_config()
      +
      +    assert config is not None
      +    assert __import__("os").environ["TELEGRAM_IGNORED_THREADS"] == "31,42"

1 PR closed without merging

From the close comments: merged via another change 1

  • #9348 feat(gateway): add ignored_threads config for Telegram · merged via another change → #9530
Closed issues · 1
  • Closed#9208[Feature]: ignored_threads config for Telegram topic filtering
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Merged PRs
#9530
Closed issues
1
Attempts
1 PR closed without merging
Fix link checked
14 Apr 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.

For your agent

The same facts, typed.