#15937: fix(slack): let users control threading instead of system prompt forcing it
docs
channel: slack
agents
stale
size: S
Cluster:
Slack Thread Management Improvements
## Problem
The system prompt currently tells agents to **"Prefer `[[reply_to_current]]`"** — making the threading decision for the user. This removes user agency over a core UX behavior and creates problems when combined with Slack's default settings:
1. **System prompt forces threading** — "Prefer `[[reply_to_current]]`" means agents thread every reply regardless of user preference
2. **`allowTagsWhenOff: true`** (Slack dock) — reply tags override `replyToMode: off`, so even users who configured "no threading" get threading
3. **`thread.inheritParent: false`** (default) — each threaded reply spawns a new `:thread:<threadTs>` session, causing session sprawl
**The core issue:** Threading should be a user preference, not a system prompt default. Users who want threading can configure `replyToMode`. Users who don't want it shouldn't have it forced on them by the agent.
### Evidence
Screenshot from the OpenClaw gateway dashboard showing 5+ separate `:thread:` sessions spawned from a single Slack DM — all created because the system prompt told the agent to thread:
- `agent:main:slack:channel:d0ae412sy9x:thread:1771031274.303499`
- `agent:main:direct:drew:thread:1771031274.303499`
- `agent:main:slack:channel:d0ae412sy9x:thread:1771030280.178839`
- (and more)
## Root Cause
The threading pipeline has four mechanisms that combine poorly when the system prompt overrides user intent:
| Mechanism | Default | Effect |
|-----------|---------|--------|
| System prompt | "Prefer `[[reply_to_current]]`" | Agent always threads (ignoring user config) |
| `allowTagsWhenOff` | `true` (Slack dock) | Reply tags bypass `replyToMode: off` |
| `thread.inheritParent` | `false` | Each thread creates a new session |
| `replyToMode` | `off` | User said "no threading" but gets it anyway |
The `allowTagsWhenOff` design is correct — it lets agents selectively thread when it genuinely makes sense. The problem is the system prompt removing that selectivity by always preferring tags.
## Changes
### Fix 1: Let users decide on threading (system prompt)
**Before:**
```
- Prefer [[reply_to_current]]. Use [[reply_to:<id>]] only when an id was explicitly provided.
```
**After:**
```
- Do not use reply tags by default. Threading behavior is a user preference — follow the user's configured replyToMode and threading settings.
- If the user has not expressed a threading preference, do not assume one. You may ask the user if threading would be helpful for their workflow.
```
The agent still knows reply tags exist and how to use them. It just doesn't force them. If a user configures `replyToMode: all`, threading works. If they leave it at `off`, the agent respects that. If it's unclear, the agent can ask.
**File:** `src/agents/system-prompt.ts`
### Fix 2: Default `inheritParent` to `true`
When threads do occur (via user config or intentional agent choice), they should route to the parent session by default. Session sprawl from orphaned thread sessions is a worse default than unified sessions.
Users who want isolated thread sessions can set `inheritParent: false`.
**File:** `src/slack/monitor/provider.ts`
### Documentation
Added "Thread session inheritance" section to Slack docs.
**File:** `docs/channels/slack.md`
### Tests
- Updated 3 existing tests to match new `inheritParent: true` default
- Added test for explicit `inheritParent: false` opt-out
- All 8 tests pass
**File:** `src/slack/monitor.tool-result.threads-top-level-replies-replytomode-is-all.test.ts`
## Before/After
| Behavior | Before | After |
|----------|--------|-------|
| Who decides threading? | System prompt (agent always threads) | User config (`replyToMode`) |
| Agent default | "Prefer reply tags" | "Don't use reply tags by default" |
| Thread → session mapping | New session per thread | Inherits parent session |
| `inheritParent` default | `false` | `true` |
| User with `replyToMode: off` | Gets threading anyway (via tags) | No threading (tags not used) |
| User with `replyToMode: all` | Gets threading | Gets threading (unchanged) |
## Backward Compatibility
- Users who explicitly set `replyToMode: all` or `first` are unaffected — threading still works
- Users who set `inheritParent: false` are unaffected
- `allowTagsWhenOff: true` is unchanged — agents CAN still thread selectively when it makes sense
- The agent now respects the user's threading config instead of overriding it
Most Similar PRs
#10686: fix(slack): use thread-level sessions for channels to prevent conte...
by pablohrcarvalho · 2026-02-06
76.9%
#22982: fix: prevent stale threadId from routing subagent announces to wron...
by unboxed-ai · 2026-02-21
76.6%
#16186: fix(slack): thread history on subsequent turns, inbound meta contex...
by markshields-tl · 2026-02-14
75.7%
#20406: fix(slack): respect replyToMode when computing statusThreadTs in DMs
by QuinnYates · 2026-02-18
75.0%
#15969: fix: per-thread session isolation for Slack DMs when replyToMode is...
by neeravmakwana · 2026-02-14
74.5%
#23799: fix(slack): finalize replyToMode off threading behavior
by vincentkoc · 2026-02-22
73.4%
#23320: fix(slack): respect replyToMode when incomingThreadTs is auto-created
by dorukardahan · 2026-02-22
73.3%
#19403: feat(slack): add dm.threadSession option for per-message thread ses...
by Vasiliy-Bondarenko · 2026-02-17
73.3%
#19083: Slack: preserve per-thread context and consistent thread replies
by jkimbo · 2026-02-17
72.7%
#23090: fix(slack): thread sessions broken — fork gate + history injection
by Taskle · 2026-02-22
72.0%