-
-
Notifications
You must be signed in to change notification settings - Fork 52.6k
Description
Summary
When a sub-agent completes and its requester is itself a sub-agent (depth ≥ 1), the announce path intentionally strips channel, to, threadId, and sets deliver: false. This is correct — the completion goes back as a system message to the parent session, not directly to the messaging surface.
However, this means the root threadId is lost through the spawn chain. When the depth-0 orchestrator (e.g. Kalki) receives the completion and relays it to Slack, it has no thread context to pass along. The result: completions post as new channel messages instead of replies in the originating thread.
Reproduction
- User sends a message in a Slack thread (e.g.
#fitlife-war-room) - Kalki (depth 0) spawns Kartikeya (depth 1) as orchestrator
- Kartikeya spawns worker agents (depth 2): Vishwakarma-BD, Narada-BD, etc.
- Workers complete → announce back to Kartikeya (depth 1) — threadId stripped ✅ (correct,
deliver: false) - Kartikeya completes → announce back to Kalki (depth 0) — threadId stripped ✅ (correct,
deliver: false) - Kalki relays results to Slack → posts to channel, not thread ❌
Root Cause
src/agents/subagent-announce.ts lines 312-316:
const requesterIsSubagent = requesterDepth >= 1;
// ...
channel: requesterIsSubagent ? undefined : origin?.channel,
accountId: requesterIsSubagent ? undefined : origin?.accountId,
to: requesterIsSubagent ? undefined : origin?.to,
threadId: requesterIsSubagent ? undefined : threadId,
deliver: !requesterIsSubagent,The threadId from the original spawn context (ctx.agentThreadId, captured at line 85 of subagent-spawn.ts) is available but gets dropped when the requester is a sub-agent. The root thread context is never propagated through multi-depth spawn chains.
Expected Behavior
The root-level threadId should be preserved and available to the depth-0 agent when it delivers completions. Two possible approaches:
Option A: Propagate root threadId through spawn chain
Store the originating threadId (from the root user message) as a separate field (e.g. rootThreadId) that survives through all spawn depths. The depth-0 announce path can then use it for delivery.
Option B: Include threadId in completion system message metadata
When announcing back to a sub-agent requester (deliver: false), include the original threadId in the system message metadata so the parent agent can extract and use it when posting to the messaging surface.
Impact
Any multi-agent workflow triggered from a Slack/Discord thread will have completions posted to the channel instead of the thread. This clutters channels and breaks conversational context.
Environment
- OpenClaw version: 2026.2.13
- Observed on: Slack (likely affects any threaded messaging surface)