fix(subagent): route nested announce to parent even when parent run ended#18043
Merged
steipete merged 1 commit intoopenclaw:mainfrom Feb 16, 2026
Merged
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Change Type
Scope
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:
Security Impact
Root Cause Analysis
In
runSubagentAnnounceFlow(), whenisSubagentSessionRunActive(parent)returns false, the code immediately fell back to grandparent. But "run ended" ≠ "session gone":isSubagentSessionRunActive(Newton)→ false (no active run)Fix: Before falling back, check if parent SESSION still exists via
loadSessionEntryByKey(). Only fallback when session is truly deleted.Evidence
subagent-announce.format.e2e.test.ts:routes to parent subagent when parent run ended but session still existsfalls back to grandparent only when parent session is deletedCompatibility / Migration
Risks and Mitigations
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
runSubagentAnnounceFlowfell back to the grandparent wheneverisSubagentSessionRunActive(parent)returned false, but a parent whose run has ended may still have an active session waiting for child results. The fix adds aloadSessionEntryByKeycheck: only fall back to the grandparent when the parent session entry is truly gone (no validsessionId), 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 validsessionId. 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
loadSessionEntryByKeyfor 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 withoutsessionIdfor auto-generated subagent keys, preserving the original fallback behavior in those scenarios. Two new regression tests directly validate both branches of the fix.Last reviewed commit: 1bc812c