fix(delegate_task): add hard-timeout protection for subagent execution - #11591
Closed
ronatube wants to merge 1 commit into
Closed
fix(delegate_task): add hard-timeout protection for subagent execution#11591ronatube wants to merge 1 commit into
ronatube wants to merge 1 commit into
Conversation
- Wrap single-task path in Thread with configurable timeout (default 60min)
- Propagate interrupt signal to all pending children on parent interrupt
- Add overall batch hard-timeout (default 120min)
- Return {"status": "timeout"} or {"status": "error"} instead of hanging
Root cause: bare _run_single_child() call had no timeout, no interrupt
propagation, and no exception handling — could block parent indefinitely.
httpx blocking I/O cannot be interrupted by Python-level signals, so a
Thread wrapper with join(timeout) is used instead.
Collaborator
Contributor
|
Thanks for this contribution, @ronatube! The protections you've described here were already shipped in PR #13770 (merged 2026-04-22), which landed in v2026.4.23. This is an automated hermes-sweeper review. What's already in
Closing as implemented. If you believe there are gaps not covered by #13770, please reopen with a specific reproduction case against |
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
The single-task path in
delegate_task()had no timeout, no interrupt propagation, and no exception handling — a bare call to_run_single_child()that could block the parent agent indefinitely. The batch path had interrupt-flag checking but did not actually callchild.interrupt()on pending children.Changes
tools/delegate_tool.py1. Single-task path
Wrapped the bare
_run_single_child()call in athreading.Threadwith:HERMES_DELEGATE_TASK_TIMEOUT)child.interrupt()call on timeout + 10s grace period before force-unblocking{"status": "timeout", ...}or{"status": "error", ...}instead of hanging2. Batch path interrupt propagation
child.interrupt()calls for all pending children when parent is interruptedHERMES_DELEGATE_BATCH_TIMEOUT)3. Cleanup - Removed unused
as_completedimportRoot Cause
All observed hangs (450+ minutes) were
delegate_taskcalls where:tool=terminalmultiple times in a loopThreadPoolExecutorthread was blocked onhttpx— a blocking I/O call that cannot be interrupted by Python-level signals/stopcommand set_interrupt_requestedbut could not break throughConfigurability
HERMES_DELEGATE_TASK_TIMEOUTHERMES_DELEGATE_BATCH_TIMEOUTBackwards Compatibility
statusvalues: "timeout" and "error"Files Changed:
tools/delegate_tool.py(+118/-15)Testing: Syntax verified, deployed to production, Gateway restarted successfully.