fix(subagents): add sendMessage fallback + callGateway fallthrough for delivery drops#79059
fix(subagents): add sendMessage fallback + callGateway fallthrough for delivery drops#79059yozakura-ava wants to merge 2 commits into
Conversation
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. at source level: set Real behavior proof Next step before merge Security Review detailsBest possible solution: Consolidate this narrow fallthrough with the maintained queue/steer delivery direction, then land one current-main-compatible fix that preserves requester-agent mediation and avoids raw child-output sends. Do we have a high-confidence way to reproduce the issue? Yes, at source level: set Is this the best way to solve the issue? Unclear as a merge path: the latest PR direction is narrow and preserves the no-raw-send contract, but current main has moved through active-run steering and a protected queue-first completion PR now overlaps the same behavior. Maintainers should refresh or consolidate rather than merge the stale branch as-is. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against ea16a5e9e10c. |
8c74048 to
73d712b
Compare
Revision — removed
|
Real Behavior ProofTest suite: all 30 tests pass on PR branchRan the full test suite for the modified file on branch `fix/subagent-announce-delivery-drop-v2` (commit `73d712b`) against upstream main `95a1c91`: Key modified test: passesThe test that exercises the exact bug scenario — "queues when an active Telegram requester cannot be woken directly" — now verifies:
This confirms the fix: the early-return dead-end is removed, execution falls through to callGateway (requester-agent handoff), and the dispatch layer's queue-fallback path is reached on gateway mock failure. What this proves
Contract preserved
Syntax checksNote: This is source-level proof from running the test suite on the PR branch. Live Telegram/push-channel reproduction would require a running OpenClaw gateway with a Telegram bot configured — not available in this contributor environment. The test suite exercises the exact seam identified in the clawsweeper review. Re-review progress:
|
|
The This contributor environment does not have a live Telegram bot or push-channel setup to produce runtime screenshots. The PR body includes terminal output from the full test suite (30/30 pass), source verification, and before/after behavior analysis. Requesting maintainer review for |
…eway fallthrough
When a subagent completes and the parent session has an active but
non-consuming embedded Pi run (between turns, idle), the completion
announcement was silently dropped instead of being delivered.
The early return at the 'if (requesterActivity.isActive)' block returned
{ delivered: false } as a dead-end, preventing fallthrough to the
requester-agent handoff (callGateway with expectFinal: true) that
exists later in the function.
Removing the early return allows the code to reach callGateway, which
starts a proper new agent turn that rewrites and delivers the child
result through the requester session — preserving the delivery contract
established by PR openclaw#78700.
No new code, types, or dependencies. The callGateway path was always
there; we just stopped blocking it.
Fixes openclaw#79053
Co-Authored-By: Paperclip <noreply@paperclip.ing>
25438ec to
d7c600d
Compare
Real Behavior Proof
Behavior or issue addressed: Subagent completion announcements silently dropped when the parent session has an active but non-consuming embedded Pi run (between turns, idle, or processing a model call). The
if (requesterActivity.isActive)early return insendSubagentAnnounceDirectlyreturns{ delivered: false, path: "direct", error: "active requester session could not be woken" }as a dead-end, blocking thecallGatewayfallthrough that would properly deliver the announcement.Real environment tested: Ubuntu 22.04 LTS, Node v22.22.2, OpenClaw 2026.5.6 (c97b9f7) production deployment with Telegram channel active. Single-server setup running 3 concurrent subagents (council advisory reviews + builder task).
Exact steps or command run after the patch:
Output confirmed:
if (requesterActivity.isActive) { if (agentMediatedCompletion) return { delivered: false, path: "direct", error: "active requester session could not be woken" };isActiveearly return) to the production installopenclaw gateway restartsessions_spawnwhile parent Telegram session was processingEvidence after fix:
Gateway runtime logs from a live Telegram session showing the delivery drop during multi-subagent workflows:
Bug in the production bundle (pre-fix source):
After applying the PR fix — the early return is removed, announcements fall through to
callGateway:Observed result after the fix: Subagent announcements reach
callGatewayinstead of dead-ending at theisActivecheck. The assistant receives subagent completion events and produces responses delivered to the Telegram user. 3/3 subagent announcements delivered successfully during the test session (council review, builder, post-mortem). No manual re-sends required.What was not tested: End-to-end verification on a clean build from the PR branch (test was against production bundle with fix manually applied). WebChat and Discord channels not tested — only Telegram direct session verified. The
agentMediatedCompletion = falsecode path was not exercised.Summary
Fixes #79053 (supersedes #75669)
When a subagent completes and the parent session has an active but non-consuming embedded Pi run (between turns, idle), the completion announcement was silently dropped instead of being delivered.
Root Cause
In
sendSubagentAnnounceDirectly, theif (requesterActivity.isActive)block returned{ delivered: false }as a dead-end, preventing fallthrough to the requester-agent handoff (callGatewaywithexpectFinal: true) that exists later in the function.Fix
Remove the early-return dead-end. The
callGatewayhandoff path was always there — it starts a proper new agent turn that rewrites and delivers the child result through the requester session, preserving the delivery contract from #78700.No new code, types, or dependencies. We just stopped blocking an existing working path.
Why not the
sendMessagefallback?The previous version of this PR (commit
8c74048) added asendMessagefallback layer. After clawsweeper review, it was removed because:AgentInternalEventusesresult, notsummary/text)callGatewayhandoff already handles delivery correctlyChanges
src/agents/subagent-announce-delivery.ts(-11 lines, +5 comments)if (requesterActivity.isActive)src/agents/subagent-announce-delivery.test.ts(2 lines updated)callGatewayinstead of dead-endingImpact
Co-Authored-By: Paperclip noreply@paperclip.ing