Skip to content

fix(subagent): route nested announce to parent even when parent run ended#18043

Merged
steipete merged 1 commit intoopenclaw:mainfrom
Operative-001:fix/nested-spawn-announce-routing-18037
Feb 16, 2026
Merged

fix(subagent): route nested announce to parent even when parent run ended#18043
steipete merged 1 commit intoopenclaw:mainfrom
Operative-001:fix/nested-spawn-announce-routing-18037

Conversation

@Operative-001
Copy link
Contributor

@Operative-001 Operative-001 commented Feb 16, 2026

Summary

  • Problem: Nested subagent announcements bypass the parent and go directly to grandparent. When Newton (depth-1) spawns Birdie (depth-2), Birdie's result announces to Jaris (main) instead of Newton, leaving Newton waiting forever.
  • Why it matters: Completely breaks the new nested subagent spawning feature — parent orchestrators never receive child results
  • What changed: Only fallback to grandparent when parent SESSION is deleted, not just when parent run has ended

Change Type

  • Bug fix

Scope

  • Gateway / orchestration (subagent announce routing)

Linked Issue/PR

User-visible / Behavior Changes

Nested subagent results now correctly route to their immediate parent:

Previous behavior: Birdie → Newton → Jaris (bypassed parent)
New behavior: Birdie → Newton → Jaris (proper parent-child chain)

This enables the autonomous delegation workflow:

  • Newton spawns Birdie for QA
  • Birdie approves/rejects
  • Newton receives Birdie's result, acts on it
  • Newton reports final result to Jaris

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Root Cause Analysis

In runSubagentAnnounceFlow(), when isSubagentSessionRunActive(parent) returns false, the code immediately fell back to grandparent. But "run ended" ≠ "session gone":

  • Newton's run ends after spawning Birdie (agent turn completes)
  • Newton's SESSION is still alive, waiting for child results
  • isSubagentSessionRunActive(Newton) → false (no active run)
  • Code fell back to Jaris ❌

Fix: Before falling back, check if parent SESSION still exists via loadSessionEntryByKey(). Only fallback when session is truly deleted.

Evidence

  • 2 new regression tests in subagent-announce.format.e2e.test.ts:
    • routes to parent subagent when parent run ended but session still exists
    • falls back to grandparent only when parent session is deleted

Compatibility / Migration

  • Backward compatible? Yes - fixes incorrect behavior without changing expected paths
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Parent session exists but is abandoned (not actually listening)
  • Mitigation: This is already handled by the session timeout/cleanup mechanism. If parent is abandoned long enough, session entry gets deleted → fallback triggers correctly.

Greptile Summary

Fixes nested subagent announce routing so that child results are delivered to their immediate parent subagent instead of incorrectly bypassing to the grandparent. The root cause was that runSubagentAnnounceFlow fell back to the grandparent whenever isSubagentSessionRunActive(parent) returned false, but a parent whose run has ended may still have an active session waiting for child results. The fix adds a loadSessionEntryByKey check: only fall back to the grandparent when the parent session entry is truly gone (no valid sessionId), not merely when the parent has no active run.

  • src/agents/subagent-announce.ts: Before falling back to the grandparent, checks if the parent session entry still exists with a valid sessionId. If the session is alive, the announce is delivered to the parent (which starts a new agent turn). Fallback only occurs when the session is deleted.
  • src/agents/subagent-announce.format.e2e.test.ts: Adds two regression tests covering both branches: routing to a parent whose run ended but session exists, and falling back to grandparent when the parent session is deleted.

Confidence Score: 5/5

  • This PR is safe to merge — it narrows a fallback condition with a well-scoped check and includes comprehensive regression tests.
  • The change is minimal and surgical: it adds one additional check (loadSessionEntryByKey for parent session existence) before triggering the grandparent fallback path. The logic is sound — distinguishing "run ended" from "session deleted" is the correct fix for the described bug. Existing tests remain compatible because the test fixture's Proxy returns entries without sessionId for auto-generated subagent keys, preserving the original fallback behavior in those scenarios. Two new regression tests directly validate both branches of the fix.
  • No files require special attention

Last reviewed commit: 1bc812c

…nded

When a depth-2 subagent (Birdie) completes and its parent (Newton) is a
depth-1 subagent, the announce should go to Newton, not bypass to the
grandparent (Jaris).

Previously, isSubagentSessionRunActive(Newton) returned false because
Newton's agent turn completed after spawning Birdie. This triggered the
fallback to grandparent even though Newton's SESSION was still alive and
waiting for child results.

Now we only fallback to grandparent if the parent SESSION is actually
deleted (no sessionId in session store). If the parent session exists,
we inject into it even if the current run has ended — this starts a new
agent turn to process the child result.

Fixes openclaw#18037

Test Plan:
- Added regression test: routes to parent when run ended but session alive
- Added regression test: falls back to grandparent only when session deleted
@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S labels Feb 16, 2026
@steipete steipete merged commit 6931ca7 into openclaw:main Feb 16, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Nested Subagent Spawning - Announce Chain Routing Issue

2 participants