Skip to content

fix(subagents): fall through to gateway call when steer+fallback fail#75669

Closed
yozakura-ava wants to merge 3 commits into
openclaw:mainfrom
yozakura-ava:fix/telegram-subagent-delivery-drop
Closed

fix(subagents): fall through to gateway call when steer+fallback fail#75669
yozakura-ava wants to merge 3 commits into
openclaw:mainfrom
yozakura-ava:fix/telegram-subagent-delivery-drop

Conversation

@yozakura-ava

Copy link
Copy Markdown
Contributor

Summary

When a subagent completes and the parent session has an active but non-consuming Pi run (e.g., between turns, waiting for LLM response), the completion announcement is silently dropped instead of being delivered.

Fixes #75663

Root Cause

In sendSubagentAnnounceDirectly, when steer returns false (run not consuming) and the completion fallback also fails (often empty completionFallbackText), the function returns { delivered: false } as a dead-end — even though a working callGateway("agent", ...) path exists 30 lines below.

Changes

src/agents/subagent-announce-delivery.ts (~10 lines changed)

  • Removed early return { delivered: false } in the catch block of sendCompletionFallback
  • Removed early return { delivered: false } after the fallback try block
  • Both paths now fall through to the existing callGateway("agent", { expectFinal: true }) call

src/agents/subagent-announce-delivery.test.ts (+2 tests)

  • Test: steer fails + fallback throws → falls through to gateway call ✓
  • Test: steer succeeds → returns steered, gateway not called (regression) ✓

Impact

  • Telegram: Subagent results will now be delivered even when parent session is idle between turns
  • WebChat: Unaffected (already worked via polling)
  • Cron announcements: Will also benefit from this fix

Testing

  • Existing tests pass (no regressions)
  • 2 new tests covering the fixed failure paths
  • Manual reproduction confirmed the bug and the fix resolves it

Risk

Low. The gateway call path already exists and works — we are just removing a dead-end that prevented it from being reached. No new dependencies, no architectural changes.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels May 1, 2026
@clawsweeper

clawsweeper Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

Summary
The PR removes active-requester fallback failure early returns in subagent completion delivery, adds focused regression tests, and adds an Unreleased changelog entry for #75663.

Reproducibility: yes. Against current main, call completion delivery with expectsCompletionMessage true, an active requester session id, queueEmbeddedPiMessage returning false, and direct fallback returning false or throwing; the code returns delivered:false before reaching callGateway.

Next step before merge
No repair job is needed; the source PR already contains the narrow code, test, and changelog fix, so the next action is maintainer review plus required validation.

Security
Cleared: Cleared: the diff only touches agent delivery control flow, colocated tests, and changelog text, with no dependency, CI, secret, permission, install, or publishing changes.

Review details

Best possible solution:

Land this focused fallthrough change after maintainer review and required validation, keeping the paired #75663 issue open until merge closes it.

Do we have a high-confidence way to reproduce the issue?

Yes. Against current main, call completion delivery with expectsCompletionMessage true, an active requester session id, queueEmbeddedPiMessage returning false, and direct fallback returning false or throwing; the code returns delivered:false before reaching callGateway.

Is this the best way to solve the issue?

Yes. Reusing the existing gateway agent delivery path after steer and direct fallback fail is the narrowest maintainable fix, while preserving early returns when steering or fallback succeeds.

What I checked:

Likely related people:

  • bek91: Commit 0e1d324 introduced the active-requester wake path for subagent completions while keeping dormant sessions externally deliverable, which is the branch this PR adjusts. (role: introduced behavior; confidence: high; commits: 0e1d324dd842; files: src/agents/subagent-announce-delivery.ts, src/agents/subagent-announce-delivery.test.ts, src/agents/subagent-announce-delivery.runtime.ts)
  • steipete: Recent commits changed active steering defaults, trimmed subagent helper exports, and centralized delivery evidence in the same delivery files shortly before this PR. (role: recent maintainer; confidence: high; commits: 30a2b3049ae0, 33e527d1fcc2, 9e9df8f2c578; files: src/agents/subagent-announce-delivery.ts, src/agents/subagent-announce-delivery.test.ts, src/agents/subagent-announce-dispatch.ts)
  • vincentkoc: Commit a1b6567 added fallback subagent completion delivery behavior near the path this PR now lets execution reach. (role: adjacent owner; confidence: medium; commits: a1b656705992; files: src/agents/subagent-announce-delivery.ts, src/agents/subagent-announce-delivery.test.ts)
  • sfuminya: Commit 2c57d70 preserved requester route handling for subagent completion delivery, part of the delivery-target contract used by the fallthrough path. (role: adjacent owner; confidence: medium; commits: 2c57d70a10db; files: src/agents/subagent-announce-delivery.ts, src/agents/subagent-announce-delivery.test.ts)

Remaining risk / open question:

  • No targeted tests or changed-gate were run in this read-only review; maintainer merge should still require the focused test file and normal changed-lane validation.
  • The latest head only shows automation/label check runs from the public metadata inspected here, so functional CI still needs to gate the merge.

Codex review notes: model gpt-5.5, reasoning high; reviewed against a3564ae546f5.

@yozakura-ava yozakura-ava force-pushed the fix/telegram-subagent-delivery-drop branch from 3c03af3 to 7f88a15 Compare May 1, 2026 13:54
@yozakura-ava

Copy link
Copy Markdown
Contributor Author

Review Feedback Addressed

Pushed an updated commit (7f88a15) that addresses both review findings:

1. Changelog entry added

Added to CHANGELOG.md under Unreleased / Fixes:

- Subagents: fall through to gateway agent call when embedded-run steering and direct fallback both fail, so background subagent completions reach push-based channels (Telegram) instead of silently returning delivered:false. Fixes #75663. Thanks @yozakura-ava.

2. Throw test now exercises the actual catch path

Added internalEvents with a task_completion event to the fallback-throws test so completionFallbackText is populated and sendCompletionFallback actually invokes sendMessage (which throws), exercising the removed catch path. Added expect(sendMessage).toHaveBeenCalled() to confirm.

Signing

Commit is SSH-signed. Will add the signing key to GitHub verified keys shortly.

yozakura-ava and others added 3 commits May 2, 2026 15:15
When a subagent completes and the parent session has an active but
non-consuming Pi run, steer correctly returns false. The completion
fallback (direct channel send) often fails too (empty text, no target).
Previously both failure paths returned { delivered: false } as a dead-end,
preventing the working callGateway('agent', ...) path from being reached.

Fix: Remove early returns in the steer-fallback block. Let execution
fall through to the existing gateway call that starts a new run and
delivers the message.

Adds two tests:
- steer fails + fallback throws → falls through to gateway call
  (with internalEvents so sendCompletionFallback actually exercises sendMessage)
- steer succeeds → returns steered, gateway not called (regression)

Includes CHANGELOG.md entry under Unreleased/Fixes.

Closes: openclaw#75663

Co-Authored-By: Paperclip <noreply@paperclip.ing>
The post-gateway fallback retry checks hasVisibleGatewayAgentPayload
before retrying sendCompletionFallback. Without visible payloads in the
mock response, the second fallback attempt also throws and the outer
catch returns delivered:false. Fix: mock returns result.payloads with
text so the retry is skipped and delivery succeeds.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
ClawSweeper P2: the catch block on the fallback failure path no longer
reads the error variable. Use catch {} to satisfy the
unicorn/prefer-optional-catch-binding lint rule.
@yozakura-ava yozakura-ava force-pushed the fix/telegram-subagent-delivery-drop branch from 3be199c to c1d30f9 Compare May 2, 2026 15:15
@yozakura-ava

Copy link
Copy Markdown
Contributor Author

Closing — upstream has structurally changed the subagent completion delivery infrastructure since this PR was opened (removed agent-mediated completion path, added sendMessage-based fallback). Opening a new PR with a remediated fix against the current codebase.

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: Subagent completion announcements silently drop on Telegram when parent session is idle between turns

1 participant