openclaw - ✅(Solved) Fix Slack mention gating can ignore bot-participated threads for some visible threaded replies [1 pull requests, 3 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#77648Fetched 2026-05-06 06:23:26
View on GitHub
Comments
3
Participants
3
Timeline
12
Reactions
2
Author
Assignees
Timeline (top)
commented ×3mentioned ×2subscribed ×2assigned ×1

Slack docs say channel messages are mention-gated by default, but untagged replies inside a bot-participated Slack thread should bypass requireMention unless channels.slack.thread.requireExplicitMention is true. The inbound gating code supports that behavior via implicit mention kinds, but not every visible threaded Slack send records bot participation.

This can make an already-active Slack thread look visibly bot-participated while later untagged user replies are still dropped as no-mention.

Error Message

  • In a Slack channel thread, the bot had been explicitly mentioned and visibly replied multiple times.
  • requireMention: true was configured globally and for the channel.
  • Explicit @bot mentions triggered the bot.
  • Untagged replies in the already-active thread did not trigger the bot.
  • Visible bot replies were often delivered through Slack outbound/message-tool-style paths rather than only the ordinary final reply pipeline.

Root Cause

Slack docs say channel messages are mention-gated by default, but untagged replies inside a bot-participated Slack thread should bypass requireMention unless channels.slack.thread.requireExplicitMention is true. The inbound gating code supports that behavior via implicit mention kinds, but not every visible threaded Slack send records bot participation.

This can make an already-active Slack thread look visibly bot-participated while later untagged user replies are still dropped as no-mention.

Fix Action

Fix / Workaround

Some outbound paths record participation:

  • Normal inbound assistant reply dispatch records after successful visible delivery.
  • Slack action runtime records for sendMessage and uploadFile, so generic Slack message(action="send") is likely covered when it goes through that action runtime.

PR fix notes

PR #77660: fix: slack mention-gating thread participation

Description (problem / solution / changelog)

Summary

  • Record Slack thread participation after successful visible threaded sends in the shared Slack send path.
  • Remove narrower duplicate recording from the Slack action runtime so message-tool, outbound, and media delivery paths share the same behavior.
  • Add focused coverage for threaded text sends, media uploads, and outbound replyToId-to-threadTs routing.

Root Cause

Slack inbound mention gating already supports implicit thread mentions through the bot thread participation cache, but not every visible outbound Slack path seeded that cache. In particular, sends routed through the shared message/outbound delivery path could visibly reply in a thread without recording participation, so later unmentioned thread replies could be dropped as no-mention despite documented bot participation behavior.

Fixes #77648.

Validation

  • pnpm exec vitest run extensions/slack/src/send.blocks.test.ts extensions/slack/src/send.upload.test.ts extensions/slack/src/action-runtime.test.ts extensions/slack/src/outbound-delivery.test.ts extensions/slack/src/monitor/message-handler/prepare.test.ts --testTimeout=120000
  • pnpm check:test-types
  • pnpm build
  • codex review --base origin/main

AI-assisted: yes.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/slack/src/action-runtime.test.ts (modified, +0/-2)
  • extensions/slack/src/action-runtime.ts (modified, +0/-18)
  • extensions/slack/src/outbound-delivery.test.ts (modified, +19/-0)
  • extensions/slack/src/send.blocks.test.ts (modified, +47/-0)
  • extensions/slack/src/send.ts (modified, +8/-1)
  • extensions/slack/src/send.upload.test.ts (modified, +6/-0)

Code Example

const threadTs = normalizeSlackThreadTsCandidate(opts.threadTs);
if (threadTs && result.channelId && account.accountId) {
  recordSlackThreadParticipation(account.accountId, result.channelId, threadTs);
}
RAW_BUFFERClick to expand / collapse

Summary

Slack docs say channel messages are mention-gated by default, but untagged replies inside a bot-participated Slack thread should bypass requireMention unless channels.slack.thread.requireExplicitMention is true. The inbound gating code supports that behavior via implicit mention kinds, but not every visible threaded Slack send records bot participation.

This can make an already-active Slack thread look visibly bot-participated while later untagged user replies are still dropped as no-mention.

Observed behavior

  • In a Slack channel thread, the bot had been explicitly mentioned and visibly replied multiple times.
  • requireMention: true was configured globally and for the channel.
  • Explicit @bot mentions triggered the bot.
  • Untagged replies in the already-active thread did not trigger the bot.
  • Visible bot replies were often delivered through Slack outbound/message-tool-style paths rather than only the ordinary final reply pipeline.

Expected behavior

When channels.slack.thread.requireExplicitMention is unset or false, a user reply in a thread where the bot has visibly participated should count as an implicit mention and bypass requireMention.

Source investigation

Inbound mention gating appears correct:

  • extensions/slack/src/monitor/message-handler/prepare.ts computes implicit mention kinds from:
    • parent_user_id === botUserId
    • hasSlackThreadParticipationWithPersistence(accountId, channelId, threadTs)
  • thread.requireExplicitMention disables implicit thread mentions by passing an empty allowed implicit-kind list.
  • Otherwise, the mention decision accepts bot-thread participation as an implicit mention.

Participation state exists and persists:

  • extensions/slack/src/sent-thread-cache.ts records accountId:channelId:threadTs in memory and persistent keyed state with TTL.

Some outbound paths record participation:

  • Normal inbound assistant reply dispatch records after successful visible delivery.
  • Slack action runtime records for sendMessage and uploadFile, so generic Slack message(action="send") is likely covered when it goes through that action runtime.

But the shared Slack send primitive does not record participation:

  • extensions/slack/src/send.ts sendMessageSlack(...) can successfully post into a thread and return { messageId, channelId }, but does not call recordSlackThreadParticipation(...).

That leaves visible threaded sends through lower-level/direct paths uncovered, including Slack outbound adapter/Block Kit/presentation delivery, attached-result delivery, approval-card/direct Slack sends, and other direct sendMessageSlack(...) callers.

Minimal reproduction shape

  1. Configure Slack with requireMention: true and leave channels.slack.thread.requireExplicitMention unset/false.
  2. Send a visible bot message into Slack channel thread T through a path that calls sendMessageSlack(..., { threadTs: T }) directly rather than action-runtime recording.
  3. Send an untagged user reply in thread T, with parent_user_id not equal to the bot user id.
  4. Expected: inbound prepare treats the thread as bot-participated and handles the message.
  5. Current risk: participation cache is missing, so prepare drops it as no-mention.

Proposed fix

Record Slack thread participation centrally in sendMessageSlack(...) after successful threaded sends, using the resolved result.channelId and normalized opts.threadTs:

const threadTs = normalizeSlackThreadTsCandidate(opts.threadTs);
if (threadTs && result.channelId && account.accountId) {
  recordSlackThreadParticipation(account.accountId, result.channelId, threadTs);
}

This should make all successful visible threaded Slack sends consistently seed implicit mention state. Existing action-runtime recording may be left in place as harmless duplicate/idempotent recording, or removed once central coverage is tested.

Tests to add

  • sendMessageSlack records thread participation after a successful threaded send.
  • sendMessageSlack does not record participation when no threadTs is present.
  • Slack outbound adapter / deliverOutboundPayloads into a thread records participation.
  • Inbound prepare accepts an untagged thread reply after central/outbound participation is recorded when requireMention: true and thread.requireExplicitMention: false.
  • Existing tests continue to show thread.requireExplicitMention: true requires an explicit mention.

References

Docs claim:

  • docs/channels/slack.md mention sources include implicit reply-to-bot thread behavior.
  • channels.slack.thread.requireExplicitMention default is false; bot-participated thread replies bypass requireMention unless it is true.

extent analysis

TL;DR

Record Slack thread participation centrally in sendMessageSlack(...) to ensure consistent implicit mention state for bot-participated threads.

Guidance

  • Verify that channels.slack.thread.requireExplicitMention is unset or false to ensure implicit mentions are allowed in bot-participated threads.
  • Update sendMessageSlack(...) to record thread participation after successful threaded sends using the proposed fix code snippet.
  • Test the updated sendMessageSlack function to ensure it records thread participation correctly, including cases with and without threadTs.
  • Review existing tests to ensure they cover the updated behavior and add new tests as proposed to verify the fix.

Example

The proposed fix code snippet can be used as an example:

const threadTs = normalizeSlackThreadTsCandidate(opts.threadTs);
if (threadTs && result.channelId && account.accountId) {
  recordSlackThreadParticipation(account.accountId, result.channelId, threadTs);
}

This code records thread participation centrally in sendMessageSlack(...) after successful threaded sends.

Notes

The fix assumes that the recordSlackThreadParticipation function is correctly implemented and that the normalizeSlackThreadTsCandidate function returns the correct threadTs value.

Recommendation

Apply the proposed workaround by updating sendMessageSlack(...) to record thread participation centrally, as this should fix the issue and ensure consistent implicit mention state for bot-participated threads.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

When channels.slack.thread.requireExplicitMention is unset or false, a user reply in a thread where the bot has visibly participated should count as an implicit mention and bypass requireMention.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Slack mention gating can ignore bot-participated threads for some visible threaded replies [1 pull requests, 3 comments, 3 participants]