Skip to content

feat(slack): sticky thread routing — bypass @mention in active threads#16223

Closed
iamfuntime wants to merge 3 commits intoopenclaw:mainfrom
iamfuntime:feat/slack-sticky-thread-routing
Closed

feat(slack): sticky thread routing — bypass @mention in active threads#16223
iamfuntime wants to merge 3 commits intoopenclaw:mainfrom
iamfuntime:feat/slack-sticky-thread-routing

Conversation

@iamfuntime
Copy link

@iamfuntime iamfuntime commented Feb 14, 2026

Summary

  • Add sticky thread routing so follow-up messages in active Slack threads are routed to the bot without requiring an explicit @mention
  • Track per-thread activity with a configurable TTL (stickyThreadTtlMs)
  • New sticky-threads module with in-memory Map and automatic expiry

Problem

Users in active Slack threads had to @mention the bot on every message, even when the bot was already engaged in the conversation. This created unnecessary friction in ongoing discussions.

Closes #16133

Changes

File What
src/slack/monitor/sticky-threads.ts NewStickyThreadStore class with touch() / isSticky() / cleanup
src/config/types.slack.ts Add stickyThreadTtlMs to Slack provider type
src/config/zod-schema.providers-core.ts Schema validation for the new field
src/config/schema.help.ts Help text for stickyThreadTtlMs
src/config/schema.labels.ts UI label for the setting
src/slack/monitor/context.ts Expose sticky-thread store on monitor context
src/slack/monitor/provider.ts Instantiate store at provider startup
src/slack/monitor/message-handler/prepare.ts Touch the store when bot replies in a thread
src/slack/monitor/message-handler/dispatch.ts Check sticky status to bypass @mention requirement

Test plan

  • Manually tested: bot responds in thread without @mention after initial interaction
  • Confirmed TTL expiry stops routing after inactivity
  • Lint and format hooks pass (0 warnings, 0 errors)
  • CI checks on this PR

🤖 Generated with Claude Code

Greptile Summary

This PR adds sticky thread routing for Slack, allowing follow-up messages in threads where the bot has already replied to bypass the @mention requirement. The implementation uses an in-memory tracker (StickyThreadTracker) with 24-hour TTL and 10K max entries, gated by a new stickyRouting boolean config option (defaults to true).

  • Adds StickyThreadTracker in src/slack/monitor/sticky-threads.ts with record()/isActive() lifecycle and automatic TTL-based pruning
  • Extends implicitMention logic in prepare.ts to check sticky thread status alongside existing parent_user_id check
  • Records sticky thread state in dispatch.ts after successful bot reply, excluding DMs
  • Threads per-chat-type replyToMode override from prepare.ts through to dispatch.ts via PreparedSlackMessage, fixing a latent issue where dispatch used the global ctx.replyToMode instead of the resolved per-chat-type mode
  • Config plumbing: adds channels.slack.thread.stickyRouting to schema, types, help text, and labels

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk — the feature is opt-out (default on), well-gated, and the sticky tracking is correctly scoped to non-DM threads where the bot has actively replied.
  • The implementation is clean and well-integrated with existing patterns. The sticky thread tracker is simple and correct, with proper null-checks throughout. The per-chat-type replyToMode threading fix in dispatch.ts is a good improvement. Minor: the TTL is hardcoded (not configurable via config despite PR description mentioning stickyThreadTtlMs), and Date.now() is called twice in record() — neither is a blocking concern. No unit tests were added for the new sticky-threads module.
  • Pay close attention to src/slack/monitor/message-handler/prepare.ts (implicit mention logic expansion) and src/slack/monitor/message-handler/dispatch.ts (replyToMode source change from ctx to prepared).

Last reviewed commit: bba3cf1

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

When a user has recently interacted in a Slack thread, route follow-up
messages directly to the bot without requiring an @mention. This reduces
friction in ongoing conversations by tracking thread activity with a
configurable TTL (stickyThreadTtlMs).

Adds a new sticky-threads module, config schema fields, and integration
into the monitor message pipeline.

Closes openclaw#16133

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openclaw-barnacle openclaw-barnacle bot added channel: slack Channel integration: slack size: S labels Feb 14, 2026
…ype replyToMode

DM threads were being recorded in the sticky store even though
implicitMention already guards DMs. Additionally, the monitor resolved
replyToMode once at startup ignoring per-chat-type overrides
(replyToModeByChatType.direct / dm.replyToMode).

- Add !prepared.isDirectMessage guard to sticky thread recording
- Resolve replyToMode per chat type in prepare.ts, pass through
  PreparedSlackMessage so dispatch.ts uses the effective value
- Use prepared.replyToMode instead of ctx.replyToMode in dispatch.ts
  for thread targets, reply plan, and sticky recording
- Fix test fixture to include top-level replyToMode on account

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@sourman
Copy link
Contributor

sourman commented Feb 26, 2026

tested working. I rebased on latest main @iamfuntime . context still bloating unnecessarily (as if the stick thread is not in session context) I tried to address that here but it needs more work #27609

@sourman
Copy link
Contributor

sourman commented Feb 26, 2026

obviously since it is in memory this approach does not survive gateway restarts. no @ has to be sent

@sourman
Copy link
Contributor

sourman commented Feb 27, 2026

@iamfuntime! rebased on latest main in draft PR: #28902
planning to do a bit more work there to reduce context bloat similar to #27609 and #27654

@Takhoffman
Copy link
Contributor

Thanks for the contribution and the detailed work here.

Closing this PR for now because it is superseded by a tighter Workstream 3 path that we are landing to avoid overlapping Slack threading/session changes in parallel.

What we are keeping:

  • sticky follow-up behavior, but without broad config surface expansion in this pass

If you want, I can cross-reference any specific test or edge case from this PR into the active salvage PRs so your coverage is preserved.

@Takhoffman Takhoffman closed this Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack close:superseded PR close reason size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack: add autoThread mention bypass for bot-participating threads (parity with Discord)

5 participants