Skip to content

[Bug]: Slack: /new and /reset commands broken when sent with mention (fix provided in bug report) #9937

@piotrmasior

Description

@piotrmasior

Slack: /new and /reset commands broken when sent with mention

Bug Summary

In OpenClaw 2026.2.3-1, sending @raspy /new or @raspy /reset in a Slack channel does not trigger a session reset. The message is passed to the agent as regular text instead of being intercepted as a reset trigger. The /status command works fine in the same context.

Environment

  • OpenClaw: 2026.2.3-1
  • Channel: Slack (socket mode)
  • Channel type: group channel (#raspy_with_me)
  • Previously working on: 2026.2.2-3

Root Cause

The Slack channel dock in src/channels/docks.ts (bundled as sandbox-*.js) is missing the mentions property with stripPatterns for Slack's <@USERID> format.

Compare the docks:

Channel Has mentions.stripPatterns? Pattern
Discord Yes <@!?\d+>
WhatsApp Yes E164 phone number patterns
Slack No None

How it breaks

  1. User sends @raspy /reset in Slack
  2. Slack delivers the message body as <@U1234567> /reset
  3. The reset trigger path in initSessionState (reply.ts) calls stripMentions() on the body
  4. stripMentions() checks provider-specific stripPatterns from the channel dock -- but Slack has none
  5. The generic fallback regex /@[0-9+]{5,}/ doesn't match Slack's <@U...> format
  6. strippedForResetLower remains <@u1234567> /reset, which does NOT match the trigger /reset
  7. resetTriggered stays false, and the message goes to the agent as regular text

Why /status still works

/status has a separate code path via directive extraction (extractStatusDirective), which uses a regex (?:^|\s)\/(?:status)(?=$|\s|:) to find /status anywhere in the body text, regardless of prefix. The /new and /reset triggers don't have this fallback -- they rely solely on exact string matching after mention stripping.

Relevant Source Files

  • src/channels/docks.ts -- Slack dock definition (missing mentions config)
  • src/auto-reply/reply/session-state.ts -- initSessionState(), reset trigger matching (~line 63340 in bundled reply-*.js)
  • src/auto-reply/reply/strip-mentions.ts -- stripMentions() function
  • src/auto-reply/reply/directives.ts -- extractStatusDirective() (the working path)

Suggested Fix

Option A (preferred): Add Slack mention strip patterns to the Slack dock, consistent with Discord:

// In the Slack dock definition (src/channels/docks.ts)
slack: {
  // ...existing config...
  mentions: {
    stripPatterns: () => ["<@[A-Z0-9]+>"],  // Slack user mention format
  },
}

Option B (defense in depth): Also make the reset trigger matching more resilient, similar to how directive extraction works -- match the trigger anywhere after a word boundary or whitespace, not just as an exact string:

// In initSessionState (src/auto-reply/reply/session-state.ts)
// Current: exact match only
if (trimmedBodyLower === triggerLower || strippedForResetLower === triggerLower)

// Proposed: also match when preceded by mention/whitespace
if (
  trimmedBodyLower === triggerLower ||
  strippedForResetLower === triggerLower ||
  trimmedBodyLower.endsWith(" " + triggerLower) ||
  strippedForResetLower.endsWith(" " + triggerLower)
)

Workaround Applied

We patched the bundled dist files directly on the Raspberry Pi:

  1. dist/reply-DpTyb3Hh.js -- Added .endsWith(" " + triggerLower) checks to reset trigger matching
  2. dist/loader-BAZoAqqR.js -- Same patch (duplicate code path)

These patches will be overwritten on the next openclaw update.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions