#23090: fix(slack): thread sessions broken — fork gate + history injection
channel: slack
size: XS
Cluster:
Slack Thread Management Improvements
## Problem
Thread sessions in Slack DMs are fundamentally broken. Agents lose all thread context after the first turn, making threaded conversations unusable.
## Root Cause
Three independent gates conspire to break thread sessions:
### 1. Session fork gate (`initSessionState`)
The `forkSessionFromParent` call is gated by `isNewSession`, but the session is always pre-created by the outbound reply handler before `initSessionState` runs. So `isNewSession` is always `false` for thread sessions, and forking never fires.
**Fix:** Track `forkedFromParent` flag on the session entry. Gate on `!alreadyForked` instead of `isNewSession`.
### 2. Thread history fetch gate (`prepare.ts`)
```typescript
if (threadInitialHistoryLimit > 0 && !threadSessionPreviousTimestamp) {
```
The `!threadSessionPreviousTimestamp` condition means thread history is only fetched on the very first turn. Once the session exists and has a stored timestamp, this gate blocks all subsequent fetches.
**Fix:** Remove `&& !threadSessionPreviousTimestamp` — always fetch the last N messages.
### 3. Thread history injection gate (`get-reply-run.ts`)
```typescript
const threadContextNote = isNewSession && threadHistoryBody ? ...
```
The `isNewSession &&` condition discards fetched thread history when building the prompt on non-new sessions. Even if history was successfully fetched, it is thrown away.
**Fix:** Remove `isNewSession &&` — always inject thread context when available.
## Changes
| File | Change |
|------|--------|
| `src/auto-reply/session/init-session-state.ts` | Add `forkedFromParent` flag, gate fork on `!alreadyForked` instead of `isNewSession`, add error logging |
| `src/slack/monitor/message-handler/prepare.ts` | Remove `!threadSessionPreviousTimestamp` from fetch gate |
| `src/auto-reply/reply/get-reply-run.ts` | Remove `isNewSession &&` from injection gate |
## Testing
Validated on a live OpenClaw instance with monkeypatched dist:
- Thread history now appears on every turn (sliding window of last 20 messages)
- Session forking fires correctly on first thread interaction
- No regressions on non-thread DM sessions
Most Similar PRs
#20389: fix(slack): inject thread history on first thread turn, not only on...
by lafawnduh1966 · 2026-02-18
76.1%
#16186: fix(slack): thread history on subsequent turns, inbound meta contex...
by markshields-tl · 2026-02-14
76.1%
#10686: fix(slack): use thread-level sessions for channels to prevent conte...
by pablohrcarvalho · 2026-02-06
75.5%
#16893: fix(threads): inject thread starter context on every turn, not just...
by battman21 · 2026-02-15
74.7%
#15969: fix: per-thread session isolation for Slack DMs when replyToMode is...
by neeravmakwana · 2026-02-14
74.4%
#22433: Slack: fix thread context loss after session reset
by stgarrity · 2026-02-21
72.7%
#15937: fix(slack): let users control threading instead of system prompt fo...
by taw0002 · 2026-02-14
72.0%
#19403: feat(slack): add dm.threadSession option for per-message thread ses...
by Vasiliy-Bondarenko · 2026-02-17
71.5%
#12244: fix(slack): preserve thread context for DM thread replies
by junhoyeo · 2026-02-09
70.9%
#5935: fix(slack): persist thread starter body across thread messages
by thisischappy · 2026-02-01
70.7%