Skip to content

[Bug]: Subagent completion announce bypasses main LLM since v2026.2.19 (send path regression) #22099

@yuemori

Description

@yuemori

GitHub Issue

[Bug]: Subagent completion announce bypasses main LLM since v2026.2.19 (send path regression)

Summary

After upgrading from v2026.2.17 to v2026.2.19, subagent completion announcements from sessions_spawn are delivered directly to the channel via method: "send" instead of being routed through the main session's LLM via method: "agent". This causes raw ✅ Subagent X finished messages to appear in the channel, and the main agent never processes or responds to the completion.

Steps to reproduce

  1. Configure a multi-agent setup with at least one subagent (e.g., reviewer) in openclaw.json.
  2. From a Discord (or other messaging) channel session, use sessions_spawn to spawn a subagent task:
    sessions_spawn(agentId="reviewer", task="Review this text: 'hello world'. Score 1-10.", label="test-review")
    
  3. Wait for the subagent to complete (~5-30s).
  4. Observe the announce delivery in the channel and main session transcript.

Expected behavior

The main session's LLM receives the subagent result as a [System Message] (user role), processes it, and responds in its own voice with a natural summary. This is the behavior observed in v2026.2.17.

Main session transcript entry (v2026.2.17, working):

{
  "role": "user",
  "content": "[System Message] [sessionId: ...] A subagent task \"test-review\" just completed successfully.\n\nResult: ...\n\nA completed subagent task is ready for user delivery. Convert the result above into your normal assistant voice..."
}

The main LLM is triggered by this user-role message and responds naturally.

Actual behavior

The completion message is posted directly to the channel as a raw ✅ Subagent X finished message via method: "send". The main session transcript records it as an assistant message with model: "delivery-mirror", and the main LLM is never invoked.

Main session transcript entry (v2026.2.19, broken):

{
  "role": "assistant",
  "model": "delivery-mirror",
  "provider": "openclaw",
  "content": [{"type": "text", "text": "✅ Subagent main finished\n\n..."}]
}

No main LLM trigger occurs. Raw text appears in the channel.

Note: Cron job announcements are not affected — they continue to use the agent path correctly, because cron does not pass expectsCompletionMessage (defaults to false).

Version

v2026.2.19 (regression from v2026.2.17)

Operating system

Ubuntu 24.04 (WSL2) / Linux 6.6.87.2-microsoft-standard-WSL2

Install method

npm global (Node.js v22.22.0, npm v10.9.2)

Logs, screenshots, and evidence

Verification via downgrade

Downgraded to v2026.2.17 via npm install -g openclaw@2026.2.17 and spawned an identical reviewer subagent. The announce was delivered via agent path — the main LLM received a [System Message] (user role), was triggered, and responded in its own voice. Upgrading back to v2026.2.19 reproduces the send path behavior.

Gateway log comparison

v2026.2.17 (working — main LLM triggered, no send):

2026-02-20T18:04:33.843Z [ws] ⇄ res ✓ agent.wait 4598ms conn=44510f06…5542 id=55d8ae47…2260

v2026.2.19 (broken — send bypasses main LLM):

2026-02-20T17:06:27.850Z [ws] ⇄ res ✓ agent.wait 111243ms conn=31201895…34fc id=39da93d3…a335
2026-02-21T02:06:28.413Z [ws] ⇄ res ✓ send 518ms channel=discord conn=85f68926…a776 id=bc31cf90…b829

Note the send call after agent.wait in v2026.2.19, which directly posts to the channel without triggering the main LLM.

Root cause: introducing commit

Commit: 289f215b3fix(agents): make manual subagent completion announce deterministic
Date: 2026-02-18
Files changed: src/agents/subagent-announce.ts (+95/-32), src/agents/subagent-announce.format.e2e.test.ts (+84)

Subsequent related commits in the same release:

  • e8816c554Agents: fix subagent completion delivery to origin channel
  • 0bf1b38ccAgents: fix subagent completion thread routing

Source code analysis

v2026.2.17 sendSubagentAnnounceDirectly() in src/agents/subagent-announce.ts:

  • Only has method: "agent" path with deliver: true
  • Main LLM is always triggered for announce delivery
  • No completionMessage, completionDirectOrigin, or hasCompletionDirectTarget parameters

v2026.2.19 sendSubagentAnnounceDirectly():

  • New send path added by commit 289f215b3:
    if (params.expectsCompletionMessage && hasCompletionDirectTarget && params.completionMessage?.trim()) {
        await callGateway({
            method: "send",
            params: { channel, to, message: completionMessage, ... }
        });
        // Direct channel post — no LLM trigger
    }
  • hasCompletionDirectTarget is true whenever the requester session has a known channel + to (always true for Discord/Telegram/etc. channel sessions)
  • expectsCompletionMessage is hardcoded to true in sessions_spawn (both versions — this was not changed)
  • New completionMessage uses a simple ✅ Subagent X finished format (via new buildCompletionDeliveryMessage())
  • The original agent path still exists as a fallback but is never reached for channel sessions because hasCompletionDirectTarget is always true

Why cron is unaffected

Cron jobs call runSubagentAnnounceFlow without expectsCompletionMessage, so it defaults to false. The send path condition (params.expectsCompletionMessage && ...) is never met, and cron always falls through to the agent path.

Impact and severity

  • Affected: All users who spawn subagents via sessions_spawn from channel sessions (Discord, Telegram, Slack, etc.)
  • Severity: High — breaks the primary subagent orchestration workflow. The main agent can no longer process, summarize, or act on subagent results.
  • Frequency: 100% reproducible on v2026.2.19; confirmed working on v2026.2.17 via downgrade.
  • Consequence:
    • Raw, unprocessed completion messages appear in user channels
    • Main agent cannot chain subagent results (e.g., planner → reviewer → worker pipeline)
    • Main agent loses context about subagent completions (recorded as assistant/delivery-mirror, not triggering LLM)
    • Users must manually ask the main agent to check results

Additional information

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