openclaw - ✅(Solved) Fix [Slack] Subagent results lose thread_ts in DM assistant threads — cross-thread contamination with concurrent requests [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#63659Fetched 2026-04-10 03:42:21
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
cross-referenced ×3commented ×1referenced ×1

When Slack's Agents & Assistants feature is enabled, DM messages arrive with thread_ts (assistant thread context). The main agent's first response correctly uses this thread_ts, but subagent results lose the thread context — appearing as new top-level messages or, worse, contaminating unrelated threads when multiple conversations are active simultaneously.

Root Cause

Root Causes

Fix Action

Workaround

Runtime patches on compiled JS files:

  • provider-*.js: Cache inbound thread_ts per sessionKey via globalThis, restore in deliverNormally fallback
  • send-*.js: In postSlackMessageBestEffort, check globalThis cache when threadTs is undefined for DM channels (channelId.startsWith("D"))
  • store-*.js: Replace removeThreadFromDeliveryContext(deliveryContextFromSession(existing)) with deliveryContextFromSession(existing) to preserve threadId

PR fix notes

PR #63798: fix(slack): preserve thread context for Agents & Assistants DM root messages

Description (problem / solution / changelog)

Summary

  • Fix resolveSlackThreadContext to preserve messageThreadId for thread-root messages where thread_ts == ts (Slack Agents & Assistants DM pattern)
  • Without this fix, subagent tool calls running in the same turn lose thread context after the first reply, causing sendMessage to fall through to the top-level channel
  • Add test coverage for the new behavior across all replyToMode values

Closes #63659


This PR was developed with AI assistance (Claude). Built with islo.dev

Changed files

  • extensions/slack/src/threading.test.ts (modified, +20/-0)
  • extensions/slack/src/threading.ts (modified, +11/-3)

PR #63840: fix(slack): preserve thread context for Agents & Assistants DM root messages

Description (problem / solution / changelog)

Summary

Preserves thread context for Agents & Assistants DM root messages in Slack integration.

Closes #63659

Testing

  • Relevant tests pass

This PR was developed with AI assistance (Claude). All code has been reviewed and tested. Built with islo.dev

Changed files

  • extensions/slack/src/threading.test.ts (modified, +42/-0)
  • extensions/slack/src/threading.ts (modified, +17/-3)
  • src/agents/pi-embedded-runner/run.overflow-compaction.harness.ts (modified, +2/-0)
RAW_BUFFERClick to expand / collapse

Summary

When Slack's Agents & Assistants feature is enabled, DM messages arrive with thread_ts (assistant thread context). The main agent's first response correctly uses this thread_ts, but subagent results lose the thread context — appearing as new top-level messages or, worse, contaminating unrelated threads when multiple conversations are active simultaneously.

Root Causes

1. replyToMode: "first" consumes threadTs on first reply

createReplyReferencePlanner in reply-threading marks hasReplied=true after the first response. Subsequent responses (subagent results) get undefined threadTs. Even with replyToMode: "all", subagent result turns create new replyPlans without the original incomingThreadTs.

2. removeThreadFromDeliveryContext strips stored threadId

In store session management (store-*.js), when a subagent result updates the session without an explicit threadId, removeThreadFromDeliveryContext() deletes the previously stored thread context from the delivery context.

3. Single-value thread cache causes cross-thread contamination

When using a per-channel cache to preserve thread_ts across turns, concurrent DM conversations (e.g., a deploy request in thread A and a market report in thread B) overwrite each other's cached thread_ts. Results from thread B's subagent end up as replies in thread A.

Proposed Fix

The thread_ts from the originating DM session should be preserved per-session across subagent result turns:

  1. Cache thread_ts per sessionKey (not per channel) on inbound in provider
  2. Restore per-session thread_ts in postSlackMessageBestEffort when outbound threadTs is missing for DM channels
  3. Remove removeThreadFromDeliveryContext call from session delivery context merging — preserve existing threadId when no explicit override is provided
  4. Alternatively, extend createSlackReplyDeliveryPlan to accept a fallback threadTs from the session store

Reproduction

  1. Enable Agents & Assistants in Slack App settings
  2. DM the bot with a task requiring subagent delegation (e.g., deploy via Saya)
  3. First response (delegation status) appears in the assistant thread ✓
  4. Subagent result appears as a new top-level message

Cross-thread contamination:

  1. Open two assistant threads simultaneously in the same DM
  2. Request different tasks in each (e.g., deploy in thread A, market report in thread B)
  3. Thread B's result appears in thread A ✗

Affected Versions

v2026.4.5, v2026.4.7, v2026.4.8 (all npm versions when Slack Agents & Assistants is enabled)

Workaround

Runtime patches on compiled JS files:

  • provider-*.js: Cache inbound thread_ts per sessionKey via globalThis, restore in deliverNormally fallback
  • send-*.js: In postSlackMessageBestEffort, check globalThis cache when threadTs is undefined for DM channels (channelId.startsWith("D"))
  • store-*.js: Replace removeThreadFromDeliveryContext(deliveryContextFromSession(existing)) with deliveryContextFromSession(existing) to preserve threadId

Environment

macOS, local gateway mode (non-Docker), Slack Socket Mode

extent analysis

TL;DR

To fix the issue of subagent results losing thread context in Slack's Agents & Assistants feature, cache the thread_ts per sessionKey and restore it when outbound threadTs is missing for DM channels.

Guidance

  • Implement a per-session cache for thread_ts in the provider to preserve the thread context across subagent result turns.
  • Modify postSlackMessageBestEffort to restore the per-session thread_ts when the outbound threadTs is missing for DM channels.
  • Remove the removeThreadFromDeliveryContext call from session delivery context merging to preserve the existing threadId.
  • Consider extending createSlackReplyDeliveryPlan to accept a fallback threadTs from the session store as an alternative solution.

Example

// In provider-*.js
globalThis.threadTsCache = {};
// Cache inbound thread_ts per sessionKey
globalThis.threadTsCache[sessionKey] = thread_ts;

// In postSlackMessageBestEffort
if (channelId.startsWith("D") && !threadTs) {
  threadTs = globalThis.threadTsCache[sessionKey];
}

Notes

The proposed fix requires modifications to the provider, postSlackMessageBestEffort, and store modules. The workaround using runtime patches on compiled JS files can be applied as a temporary solution.

Recommendation

Apply the workaround by caching the thread_ts per sessionKey and restoring it when outbound threadTs is missing for DM channels, as this approach preserves the thread context across subagent result turns and prevents cross-thread contamination.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING