← Back to PRs

#15969: fix: per-thread session isolation for Slack DMs when replyToMode is "all"

by neeravmakwana open 2026-02-14 03:54 View on GitHub →
channel: slack stale size: S
## Summary - When `replyToMode` is `"all"`, top-level Slack DMs now get their own session key (scoped by the message's `ts`), so each new message starts a fresh conversation instead of sharing context with all prior unrelated messages. - Thread replies continue to share the same session as their parent message, so conversations within a thread remain coherent. - No behavior change when `replyToMode` is not `"all"` — the existing shared session behavior is fully preserved. ## Problem When `replyToMode` is set to `"all"` in Slack DM configuration, the bot replies in a thread under each message. Users naturally expect each thread to be an independent conversation. However, all top-level DMs currently share a single persistent session (`agent:<agentId>:main`), which causes: 1. Context leakage between unrelated conversations (e.g., asking about diapers once causes all subsequent queries to only return diapers) 2. The bot reusing stale answers from prior turns instead of doing fresh work 3. Unnecessary token usage from accumulating unrelated context ## Fix In `src/slack/monitor/message-handler/prepare.ts`, the `threadId` passed to `resolveThreadSessionKeys` now uses the message's own `ts` as `threadId` for top-level messages when `replyToMode === "all"`: \`\`\`typescript threadId: isThreadReply ? threadTs : ctx.replyToMode === "all" ? threadContext.messageTs : undefined, \`\`\` This produces session keys like `agent:main:main:thread:1770865253.355799` for each top-level message. When a user replies in that thread, `thread_ts` equals the parent's `ts`, so both resolve to the same session key. ## Conflict resolution Rebased onto latest `main` to resolve a merge conflict caused by upstream test refactoring: - `prepare.inbound-contract.test.ts` was renamed to `prepare.test.ts` and consolidated with other test suites (`a7f6c956`, `8181f51d`, `aae290ee`, `2f67564c`) - Rewrote our 3 new tests to use the shared helpers introduced by those refactors (`createThreadSlackCtx`, `createThreadAccount`, `prepareWithDefaultCtx`), consistent with the rest of the test suite ## Test plan - [x] Added test: two separate top-level DMs with `replyToMode=all` produce different session keys - [x] Added test: a top-level message and its thread reply share the same session key - [x] Added test: `replyToMode=off` preserves the existing shared session behavior (no regression) - [x] All existing tests pass (5,199 tests, 0 failures) - [x] `pnpm build` passes - [x] `pnpm check` passes (pre-existing TS error in `fast-tool-stubs.ts` unrelated to this PR) - [x] `pnpm test` passes AI-assisted: Yes (Cursor + Claude). Fully tested locally. I understand what the code does.

Most Similar PRs