Repository navigation
[Tech Debt][runtime][java][python] Clarify subagent group cleanup and internal fault propagation #1322
Description
Search before asking
- I searched in the issues and found no dedicated issue tracking these follow-ups.
Description
Track two lifecycle and error-handling follow-ups raised during the review of #1320, which fixes #1279 for individual deferred and async awaits in ToolCallAction. These follow-ups are outside that PR's scope.
1. Define cleanup semantics after a caught group await failure
Java SubagentFutureGroup.awaitAll() and Python's group await prepare pending phased handles before executing them. If a member's prepare() throws, execution exits before the per-handle execute() cleanup runs. The failing member and other outstanding members can remain in the pending-call registry.
If the exception propagates out of the user Action, the Action already fails. The contract needs clarification when the caller catches the exception and wants to finish the Action normally: who owns cleanup, and what should happen to the failed member and the remaining members?
Discuss and document the intended behavior before choosing an implementation. Calling group.cancel() is not currently a guaranteed cleanup solution: it invokes each member's cancellation sequentially, can stop at the first cancellation error, and cancellation semantics differ across handle types. Merely untracking every member must not be treated as proof that any underlying work has stopped.
Review discussion: #1320 (comment)
2. Preserve direct propagation of internal framework faults
For internal subagents, ordinary child Action failures become failed SubagentResults and resolve their handles. Framework-side faults in bootstrap, waiting, or durable result completion should instead fail the Action/job and allow recovery.
Currently, InternalSubagentFuture can propagate such a fault without clearing its pending registration. When ToolCallAction catches that exception and converts it into a failed tool response, Action finalization subsequently fails on the unresolved handle. The eventual failure is expected, but the original framework fault is obscured by a secondary lifecycle error.
Clarify and enforce which failures must propagate through ToolCallAction, preserving the original cause and recovery semantics. Adding unconditional finally cleanup alone would not address this: it could allow a framework fault to be treated as a handled tool error and let the Action finish normally.
Review discussion: #1320 (comment)
Completion criteria
- Define and document the group contract for both propagated and caught await failures, including outstanding members and failures during cleanup.
- Ensure internal framework faults reach the runtime with their original cause, while ordinary child failures remain failed results.
- Keep Java and Python behavior aligned and add regression coverage at the Action lifecycle / ToolCallAction boundary.
Are you willing to submit a PR?
- I'm willing to submit a PR!
Activity