1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
---
title: "Slack requireMention: true Is Bypassed for Thread Replies After Prior Bot Participation"
date: 2026-03-25
description: "OpenClaw replies to untagged messages in Slack threads after it has previously participated in that thread, bypassing the requireMention setting."
tags: ["bug", "bug:behavior", "slack", "mention-gating", "thread-participation"]
sources:
  - platform: "GitHub Issue"
    id: "openclaw#64277"
    url: "https://github.com/openclaw/openclaw/issues/64277"
openclaw_version: "2026.3.23-2"
---

## Symptom

When a Slack channel is configured with `requireMention: true`, OpenClaw should only reply when explicitly mentioned in a message. However, users observe that:

- OpenClaw correctly replies when the bot is explicitly mentioned in a thread
- After OpenClaw has replied once in a thread, **subsequent messages in the same thread trigger responses even without mentioning the bot**
- This behavior creates unnecessary noise in Slack threads as the bot responds to messages where it was not tagged

### Steps to Reproduce

1. Configure a Slack channel with `requireMention: true`
2. Start a thread and explicitly mention the bot in the first message
3. Wait for OpenClaw to reply
4. Send another reply in the same thread **without** mentioning the bot
5. Observe that OpenClaw still replies despite not being mentioned

## Root Cause Analysis

The issue stems from how OpenClaw determines whether it has been "implicitly mentioned" in a thread. The code in the Slack integration treats thread participation as an implicit mention, which bypasses the `requireMention` gating.

### Code Flow Analysis

**1. Implicit Mention Detection:**
```javascript
const implicitMention = Boolean(
  !isDirectMessage &&
  ctx.botUserId &&
  message.thread_ts &&
  (
    message.parent_user_id === ctx.botUserId ||
    hasSlackThreadParticipation(account.accountId, message.channel, message.thread_ts)
  )
);

2. Mention Gate Resolution:

1
2
3
4
5
6
7
8
const mentionGate = resolveMentionGatingWithBypass({
  isGroup: isRoom,
  requireMention: Boolean(shouldRequireMention),
  canDetectMention,
  wasMentioned,
  implicitMention,
  ...
});

3. Gating Logic:

1
2
3
4
5
6
7
8
9
function resolveMentionGating(params) {
  const implicit = params.implicitMention === true;
  const bypass = params.shouldBypassMention === true;
  const effectiveWasMentioned = params.wasMentioned || implicit || bypass;
  return {
    effectiveWasMentioned,
    shouldSkip: params.requireMention && params.canDetectMention && !effectiveWasMentioned
  };
}

4. Thread Participation Recording:

1
2
if (anyReplyDelivered && participationThreadTs)
  recordSlackThreadParticipation(account.accountId, message.channel, participationThreadTs);

Root Cause

The function hasSlackThreadParticipation() returns true when the bot has previously replied in the same thread. This causes implicitMention to become true, which in turn makes effectiveWasMentioned evaluate to true in resolveMentionGating(). As a result, shouldSkip becomes false and the mention gate is bypassed for all subsequent messages in that thread.

The logical flaw: Thread participation should not be treated as a mention. An implicit mention implies the message is directed at the bot (e.g., replying to the bot’s message), whereas simply having replied in a thread earlier does not indicate that new messages are directed at the bot.

Solution

Immediate Fix (Requires Code Change)

The implicitMention logic in the Slack integration should be modified to exclude hasSlackThreadParticipation() from the implicit mention determination when requireMention is enabled. The condition should only consider:

  • Direct replies to the bot’s messages (message.parent_user_id === ctx.botUserId)

A suggested patch for the implicit mention detection:

1
2
3
4
5
6
7
8
// Only consider thread participation as implicit mention when requireMention is NOT enabled
// When requireMention is true, we should NOT bypass it with prior participation
const implicitMention = Boolean(
  !isDirectMessage &&
  ctx.botUserId &&
  message.thread_ts &&
  message.parent_user_id === ctx.botUserId
);

Alternatively, pass requireMention state to the implicit mention calculation:

1
2
3
4
5
6
7
8
9
const implicitMention = Boolean(
  !isDirectMessage &&
  ctx.botUserId &&
  message.thread_ts &&
  (
    message.parent_user_id === ctx.botUserId ||
    (!shouldRequireMention && hasSlackThreadParticipation(account.accountId, message.channel, message.thread_ts))
  )
);

Workaround (Configuration)

Until the fix is deployed, users can:

  1. Disable thread replies entirely by configuring channel settings to only respond in direct messages
  2. Use separate threads for bot interactions to avoid triggering the implicit mention behavior
  3. Manually mention the bot in all thread replies to ensure proper gating

Prevention

For Developers

  1. Review mention-gating logic to ensure thread participation is not conflated with being mentioned
  2. Add unit tests for the resolveMentionGating() function covering the thread participation edge case
  3. Document the distinction between “implicit mention” and “thread participation” in the codebase

For Operations

  1. Test mention gating after upgrading OpenClaw to ensure the fix is working
  2. Monitor bot behavior in Slack channels with requireMention: true for unexpected responses
  3. Review logs for bot participation in threads and verify that only explicitly mentioned messages trigger responses

Additional Information

  • Affected version: OpenClaw 2026.3.23-2
  • Operating system: Amazon Linux 2023.10.20260302
  • Install method: npm global
  • Model: openai/gpt-5.4
  • Related code file: /usr/lib/node_modules/openclaw/dist/runtime-api-BI9wNO54.js
  • Severity: Annoying (creates unnecessary noise on Slack threads)
  • Frequency: Consistent - every subsequent untagged message in a participated thread triggers a response

References

  • GitHub Issue: openclaw#64277
  • Affected function: resolveMentionGating() and hasSlackThreadParticipation()