Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions gateway/platforms/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,13 @@ async def _handle_slack_message(self, event: dict) -> None:
if not is_dm and bot_uid:
if channel_id in self._slack_free_response_channels():
pass # Free-response channel — always process
elif self._slack_strict_mention():
# Strict mode: only an explicit @mention in *this* message triggers
# a response. Thread continuity, bot-started threads, and active
# sessions are all ignored. Use this for bots that should never
# auto-engage on follow-up messages (prevents agent-to-agent loops).
if not is_mentioned:
return
elif not self._slack_require_mention():
pass # Mention requirement disabled globally for Slack
elif not is_mentioned:
Expand All @@ -1122,8 +1129,9 @@ async def _handle_slack_message(self, event: dict) -> None:
if is_mentioned:
# Strip the bot mention from the text
text = text.replace(f"<@{bot_uid}>", "").strip()
# Register this thread so all future messages auto-trigger the bot
if event_thread_ts:
# Register this thread so all future messages auto-trigger the bot.
# Skip in strict mode — strict bots must be re-mentioned every time.
if event_thread_ts and not self._slack_strict_mention():
self._mentioned_threads.add(event_thread_ts)
if len(self._mentioned_threads) > self._MENTIONED_THREADS_MAX:
to_remove = list(self._mentioned_threads)[:self._MENTIONED_THREADS_MAX // 2]
Expand Down Expand Up @@ -1732,6 +1740,24 @@ def _slack_require_mention(self) -> bool:
return bool(configured)
return os.getenv("SLACK_REQUIRE_MENTION", "true").lower() not in ("false", "0", "no", "off")

def _slack_strict_mention(self) -> bool:
"""Return whether the bot should ONLY reply to direct @mentions.

Strict mode disables all forms of thread auto-engagement:
bot-started threads, previously-mentioned threads, and active
sessions are all ignored. The bot only responds when explicitly
@-tagged in the current message. Useful for agent-to-agent
scenarios where one agent's reply could land in a thread the
other agent was once tagged in, causing infinite acknowledgement
loops. Default: False (preserves legacy behavior).
"""
configured = self.config.extra.get("strict_mention")
if configured is not None:
if isinstance(configured, str):
return configured.lower() in ("true", "1", "yes", "on")
return bool(configured)
return os.getenv("SLACK_STRICT_MENTION", "false").lower() in ("true", "1", "yes", "on")

def _slack_free_response_channels(self) -> set:
"""Return channel IDs where no @mention is required."""
raw = self.config.extra.get("free_response_channels")
Expand Down