Skip to content

Sub-agent announce drops threadId for depth≥1 requesters — completions post to channel instead of thread #22118

@bharatindia123-a11y

Description

@bharatindia123-a11y

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

  1. User sends a message in a Slack thread (e.g. #fitlife-war-room)
  2. Kalki (depth 0) spawns Kartikeya (depth 1) as orchestrator
  3. Kartikeya spawns worker agents (depth 2): Vishwakarma-BD, Narada-BD, etc.
  4. Workers complete → announce back to Kartikeya (depth 1) — threadId stripped ✅ (correct, deliver: false)
  5. Kartikeya completes → announce back to Kalki (depth 0) — threadId stripped ✅ (correct, deliver: false)
  6. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions