diff --git a/gateway/config.py b/gateway/config.py index 47b779eb8..a50c9331c 100644 --- a/gateway/config.py +++ b/gateway/config.py @@ -553,6 +553,8 @@ def load_gateway_config() -> GatewayConfig: if isinstance(slack_cfg, dict): if "require_mention" in slack_cfg and not os.getenv("SLACK_REQUIRE_MENTION"): os.environ["SLACK_REQUIRE_MENTION"] = str(slack_cfg["require_mention"]).lower() + if "allow_bots" in slack_cfg and not os.getenv("SLACK_ALLOW_BOTS"): + os.environ["SLACK_ALLOW_BOTS"] = str(slack_cfg["allow_bots"]).lower() frc = slack_cfg.get("free_response_channels") if frc is not None and not os.getenv("SLACK_FREE_RESPONSE_CHANNELS"): if isinstance(frc, list): diff --git a/gateway/platforms/slack.py b/gateway/platforms/slack.py index d2f509072..825cc2511 100644 --- a/gateway/platforms/slack.py +++ b/gateway/platforms/slack.py @@ -941,9 +941,26 @@ class SlackAdapter(BasePlatformAdapter): if v > cutoff } - # Ignore bot messages (including our own) + # Bot message filtering (SLACK_ALLOW_BOTS / config allow_bots): + # "none" — ignore all bot messages (default, backward-compatible) + # "mentions" — accept bot messages only when they @mention us + # "all" — accept all bot messages (except our own) if event.get("bot_id") or event.get("subtype") == "bot_message": - return + allow_bots = self.config.extra.get("allow_bots", "") + if not allow_bots: + allow_bots = os.getenv("SLACK_ALLOW_BOTS", "none") + allow_bots = str(allow_bots).lower().strip() + if allow_bots == "none": + return + elif allow_bots == "mentions": + text_check = event.get("text", "") + if self._bot_user_id and f"<@{self._bot_user_id}>" not in text_check: + return + # "all" falls through to process the message + # Always ignore our own messages to prevent echo loops + msg_user = event.get("user", "") + if msg_user and self._bot_user_id and msg_user == self._bot_user_id: + return # Ignore message edits and deletions subtype = event.get("subtype")