Replies: 3 comments
|
I traced this against
That suggests a narrow event-driven repair: keep an active owned-run set per exact parent lifecycle, include its generation in the existing post-checkpoint and pre-step stale-work fences, and reserve the next Goal round only when the set is empty. The final For current rc.2 containment, synchronous foreground collection avoids the idle admission checkpoint when the parent genuinely cannot progress before the child. Explicit Goal pause/resume also stops automatic rounds, but requires a deliberate resumption owner. A prompt-only “do not poll” policy reduces work inside the round but cannot avoid the parent prefill. I wrote up the source path, race cases, ownership semantics, observability, and a 16-case regression matrix here: https://sandbaseai.github.io/deepseek-harness-handbook/goal-round-subagent-wait.html Disclosure: I maintain the SandBase DeepSeek Harness Handbook. |
|
Confirmed at source, and there is a companion report of the same defect filed hours before yours: #4664 hits the identical busy-loop with a long-running background job instead of a subagent. Same handler, same cause. Worth cross-linking so they get fixed together rather than as two special cases. The mechanism. In ctx.on('agent/status', ({ agent, status }) => {
if (status === 'idle') {
// …only a "goal was cancelled" branch here…
requestDrive(state)
The general shape is that Now the part that matters for your case specifically: the two reports do not have the same fix, and yours is the harder one. For #4664's background jobs, the check is cheap and synchronous — For subagents it splits, and the split is documented in the source.
So:
If your 10–30 minute children are continuable, the cheap version of the fix will not cover you. My suggestion for how to frame the request (and I would say the same on #4664): ask for the admission check to be "is this agent waiting on anything it already started", with jobs and subagents as the first two answers, rather than for a subagent special case. Otherwise the next mechanism that lets an agent legitimately stand still — a pending approval, an external wait — arrives and reopens this thread a third time. One detail from #4664 worth adding to your cost list: their transcript shows the model, forced to speak with nothing new to say, inventing elapsed time ("~15/20/25 min in"). Those sentences land in the session history and later rounds read them as fact. So the empty rounds are not merely expensive, they degrade the context they are paying to re-prefill. Interest disclosure: I maintain a third-party DSH plugin (a Pi-ecosystem compatibility layer). Goal, jobs and subagents are all DSH's own components — we do not touch them and could not fix this; everything above is source verification. |
|
Thanks for the precise report, @uxtracer, and for the source-level split called out above by @denial123789 and @weijiafu14. I implemented and independently reviewed a reference against the current
The reference adds a generic synchronous
Verification includes 114 focused core/goal lifecycle tests, 70 whole-goal/invariant tests with 100% source statements/branches/functions/lines, and real Loader composition in source and built-lib modes proving delayed provider start/result/dispose, no parent goal overlap, and the quiet-completion wake. Host build/lint, client typecheck, Knip, package/constraint/runtime-closure invariants, generated graphs/catalogs/scoped events, type equivalence, and 1003/1003 translation pairings also pass. The pre-push host build and contract typecheck passed on the exact public commit. Scope is deliberately narrower than “all background work.” A continuable child blocks only while an observed activation epoch is active and relies on the existing continuation-manager settlement delivery to wake its parent. Unowned/generic Jobs and merely discoverable settled continuable sessions are not treated as goal dependencies; the general arbitrary-Job policy remains #4664. Full This is a reproducible reference implementation for review, not an upstream merge or adoption claim. |
Uh oh!
There was an error while loading. Please reload this page.
Goal rounds busy-loop while long-running subagents are still active
Problem
When a goal spawns a long-running subagent asynchronously, the parent agent can become idle while the child is still running.
At that point,
goal-round-driverimmediately starts another goal round because the parent agent is idle and the goal is still active/armed.For long-running subagents, for example tasks that take 10–30 minutes, this can create a busy loop of effectively empty goal rounds:
I tried explicitly instructing the parent agent not to poll or inspect subagent status while a child is running.
The model follows that instruction correctly. For example, it may conclude:
However, this only prevents polling inside the goal round.
It does not prevent
goal-round-driverfrom creating the next goal round, so the parent model is still repeatedly invoked just to conclude that it should continue waiting.Why this matters
This is especially expensive for local inference and long-context sessions.
Each empty goal round can cause:
In my workload, individual subagents commonly run for around 10 minutes, so this behavior becomes very noticeable.
For example:
Even if each round produces only a few output tokens, the parent may still pay the cost of repeatedly prefilling a large session context.
Suggested behavior
The goal-round admission logic should distinguish between:
Conceptually:
Ideally, this should be event-driven.
If needed, a wall-clock watchdog could still wake the parent after a configurable timeout to handle stuck or unusually long-running children.
Why prompt-level instructions are not enough
This cannot be solved efficiently through the goal prompt alone.
A prompt can tell the model:
But that instruction only takes effect after the parent LLM has already been invoked.
The unnecessary cost happens one layer earlier, when
goal-round-driverdecides to start another goal round.Therefore the suppression needs to happen in
goal-round-driveror the equivalent scheduling/admission layer.Expected behavior
While a goal is waiting on a long-running owned subagent, the parent agent should remain genuinely dormant and consume no LLM inference.
The next goal round should start when:
This would make
/goalmuch more efficient for agent-team workflows and long-running subagent tasks.All reactions