← Back to PRs

#19419: feat(slack): track thread participation for implicit mentions

by Utkarshbhimte open 2026-02-17 19:39 View on GitHub →
channel: slack size: XS
## Summary - **Problem:** When the bot replies in a Slack thread it didn't start, it loses track of that thread. Future messages in the thread are ignored unless they explicitly @mention the bot. - **Why it matters:** Users expect the bot to continue participating in conversations it joined. Without this, the bot goes silent mid-thread — confusing and broken-feeling. - **What changed:** Added in-memory thread participation tracking. When the bot delivers a reply in a thread, it records that thread. Future messages in tracked threads are treated as implicit mentions. - **What did NOT change (scope boundary):** No persistence (resets on restart). No changes to explicit mention handling, DM logic, channel allowlists, or any other gating. Name-based mention detection (`mentionPatterns`) is unaffected. ## Change Type (select all) - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Docs - [ ] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [ ] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [ ] Memory / storage - [x] Integrations - [ ] API / contracts - [ ] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR - Related: Slack thread participation tracking request ## User-visible / Behavior Changes - Bot now continues responding in Slack threads it has previously replied to, without requiring an explicit @mention or being the thread starter. - Behavior resets on gateway restart (in-memory only). ## Security Impact (required) - New permissions/capabilities? `No` - Secrets/tokens handling changed? `No` - New/changed network calls? `No` - Command/tool execution surface changed? `No` - Data access scope changed? `No` ## Repro + Verification ### Environment - OS: Linux (Railway container) - Runtime/container: Node v22.22.0 - Model/provider: anthropic/claude-opus-4-6 - Integration/channel: Slack - Relevant config: `groupPolicy: "open"`, `mentionPatterns: ["draper"]` ### Steps 1. In a Slack channel where the bot is active with `requireMention: true`, have someone start a thread 2. @mention the bot in a reply — bot responds 3. Send a follow-up message in the same thread **without** @mentioning the bot ### Expected - Bot processes the follow-up message and responds (implicit mention via thread participation) ### Actual (before this PR) - Bot ignores the follow-up — only tracks threads where `parent_user_id === botUserId` ## Evidence - Code review of the 3 changed files (context.ts, prepare.ts, dispatch.ts) - Manual verification: bot was deployed with these changes and successfully tracked thread participation in live Slack conversations ## Human Verification (required) - **Verified scenarios:** Bot replies in thread → follow-up messages in same thread are processed without @mention - **Edge cases checked:** Thread the bot started (still works via `parent_user_id`), threads in DMs (not affected — DMs don't check `implicitMention`), multiple threads simultaneously - **What you did NOT verify:** Behavior under extremely high thread volume (Set memory growth), persistence across restarts (intentionally not implemented) ## Compatibility / Migration - Backward compatible? `Yes` - Config/env changes? `No` - Migration needed? `No` ## Failure Recovery (if this breaks) - **How to disable/revert:** Revert commit `a894bbe9` — single commit, clean revert - **Files/config to restore:** `src/slack/monitor/context.ts`, `src/slack/monitor/message-handler/prepare.ts`, `src/slack/monitor/message-handler/dispatch.ts` - **Known bad symptoms:** Bot responding in threads it shouldn't be in (unlikely — only tracks threads where it actively delivered a reply) ## Risks and Mitigations - **Risk:** In-memory Set grows unbounded over long uptimes with high thread volume - **Mitigation:** Set only stores `channelId:threadTs` strings (~50 bytes each). Even 10K threads = ~500KB. Can add TTL/LRU eviction in a follow-up if needed. <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds in-memory thread participation tracking to the Slack integration so the bot continues responding in threads it has previously replied to, without requiring an explicit `@mention`. When the bot successfully delivers a reply (`anyReplyDelivered = true`), it records the `channelId:threadTs` pair in a `Set<string>` on the monitor context. Future messages in those threads are treated as implicit mentions via a new `hasParticipatedInThread` check added alongside the existing `parent_user_id === botUserId` condition. The overall approach is sound and the scope is appropriately narrow. Two issues found: - **Type mismatch in `dispatch.ts`**: `MessageThreadId` is typed as `string | number | undefined`, but the resolved value is passed directly to `recordThreadParticipation` which expects a `string`. The identical pattern in `src/slack/threading-tool-context.ts` (line 20–25) correctly wraps the value with `String(threadId)`. In practice Slack timestamps are always strings, but this is a latent type bug. - **Implementation detail leaked in public type**: `participatedThreads: Set<string>` is included in `SlackMonitorContext` and the `createSlackMonitorContext` return value, but it is never accessed directly outside `context.ts`. Only `recordThreadParticipation` and `hasParticipatedInThread` are needed in the public interface. Exposing the raw `Set` unnecessarily couples consumers to the internal storage representation. - No tests were added for the new `participatedThreads` logic or the updated `implicitMention` path in `prepare.ts`. <h3>Confidence Score: 3/5</h3> - Safe to merge with minor fixes — the type mismatch is a latent bug that doesn't affect current behavior since Slack timestamps are always strings, and no functional bugs are present. - The core logic is correct and the feature works as described. The type mismatch (passing `string | number` where `string` is expected) is a real issue that could fail TypeScript strict checking and is inconsistent with how the same pattern is handled elsewhere in the codebase. The raw Set being exposed in the public type is a minor design concern. Missing test coverage for the new flow slightly reduces confidence. No security or behavioral regressions identified. - src/slack/monitor/message-handler/dispatch.ts — the String() conversion fix is the only change needed before merge. <sub>Last reviewed commit: cd0cedd</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs