Why this is coming up
#4499 delegated-task-parent-wake made async child completion start a new parent continuation. Each child terminal creates its own internal queue_after_active message.
#4378 orchestrator-v2-background-waiting makes background work visible as Waiting, but it does not create those parent continuations.
- 1The child finishes.Its status and result are persisted on the parent thread.
- 2A parent wake is queued.The app creates an internal user message telling the parent to call
task_status.
- 3The active parent may handle the result first.Local agent guidance often causes it to poll
task_status while the separate wake remains queued.
- 4The queued wake eventually runs anyway.It reads the same result and can add a status-only assistant response such as "as said earlier" to the timeline.
Key constraint: delivering a completion message is not a silent context update. Delivery invokes the parent model, and the parent thread produces assistant output. Coalescing can reduce several output turns to one, but it cannot make the remaining delivery silent. Only preventing or cancelling delivery before it starts avoids that output.
Viable building blocks
These preserve automatic delivery for genuinely unobserved results while reducing redundant parent runs and their output.
Building block 1 Cancel a wake when another parent run already handled the result
Keep automatic resume for results that nobody has observed, but suppress the wake when an active parent calls task_status first.
This directly addresses the single stale queued message seen in local sessions. It also preserves the current behavior when the parent truly ended before the child finished.
- The system needs a durable connection between "this result was read" and "this queued wake belongs to that result."
task_status is currently treated as a read-only projection query. It would need to record acknowledgment, or a separate command would need to do so.
- This solves redundant wakes one by one, but several unobserved children can still produce several parent runs.
Best use: pair this with coalescing if automatic resume remains part of the product contract. Every wake that is not suppressed still invokes the parent and produces assistant output.
Building block 2 Coalesce unobserved completions into one parent run
Allow at most one queued or active completion continuation for a parent or task cohort. Additional child completions join that pending continuation rather than creating new runs.
- Eight near-simultaneous reviewers can produce one synthesis run instead of eight.
- The prompt can name all completed task IDs and ask the parent to read them together.
- A child that finishes after the synthesis has started may join a single bounded follow-up.
- The design must define the cohort: one originating parent run, one root node, or every app-owned task on the thread.
- Coalescing alone does not help the common case where one result was already handled but its one wake remains queued.
What this preserves: automatic parent resume. What it reduces: several completion-driven assistant outputs become one. What it adds: durable ownership, late-arrival rules, restart behavior, and more race handling.
Should the surviving completion Queue or Steer?
The current ProviderContinuationService uses queue_after_active for every completion. A coalesced implementation can be more selective, but it should not replace Queue with Steer unconditionally.
Potential future policy. Steer can fold a result into an active turn for providers with true in-place steering. Grok does not have that capability in the current adapter, so its coalesced completion should Queue.
First patch decision. Queue every surviving delivery. This removes the reported fan-out without introducing provider-specific active-steering races.
What Steer means for Grok today
GrokProviderCapabilitiesV2 advertises supportsActiveSteering: false and supportsSteeringByInterruptRestart: true. T3 therefore cannot add the completion result to Grok's current native turn. It supersedes the current app-run attempt, interrupts the provider turn, and starts a replacement attempt on the same session.
When Grok's native prompt is still active, the adapter sends session/cancel before the replacement session/prompt. That can interrupt foreground command or file work that had nothing to do with the completed child.
The adapter has a special soft path when the native prompt already settled but background work remains. That path preserves the runtime and background subagents. The scheduler cannot currently see that internal prompt-settled state, however, so it cannot safely select Steer only for that case.
Grok verdict: Queue. The existing Grok replay proves that a simple partial-text turn can be cancelled and reprompted successfully. It does not cover a Grok steer during tool work. Completion delivery should not use interrupt-and-restart as if it were harmless context injection.
Already acknowledged: suppress the completion message entirely.
This first patch: Queue one coalesced completion run after the current work for every provider.
Future true in-place steering: it may Steer only with provider-specific safety and atomic Queue fallback proof.
Either delivery: the parent produces output. Steer folds it into the active turn; Queue creates a follow-up turn.
Thread controls must agree with the delivery policy
"Drop the result" should mean dropping its automatic parent delivery, not deleting the child result. The terminal status and result should remain visible and available through task_status. What changes is whether a server-created prompt still owns the right to invoke the parent model.
Stop must prevent automatic restart
Today, Stop interrupts the active parent run but leaves queued runs in place. When the interrupted run becomes terminal, the orchestrator starts the next queued run. A queued completion can therefore run immediately after Stop and produce another parent response.
App-owned delegated tasks run on separate child threads, so stopping the parent does not stop them either. A child that finishes later can offer a new parent wake after the user already said Stop.
This result is unacceptable: pressing Stop can be followed by an automatic completion turn that restarts parent output without a new user instruction.
The fix needs a durable no-auto-resume barrier for the stopped run or cohort. Stop should cancel an already queued completion, suppress later delivery from its still-running children, and survive process restart. It should preserve their results. Whether Stop also interrupts those children is a separate product decision.
Cancelling a delegated task should cancel its delivery too
task_cancel currently interrupts the child, but the child's interrupted terminal still qualifies for the same automatic wake as a successful async completion. That means "the parent no longer needs this work" can itself trigger another parent turn.
Explicit task cancellation should dispose of that task's pending or future automatic delivery. The interrupted result stays available for inspection, but it must not re-arm the parent.
A new message, Steer, and Restart mean continue
These are not blanket drop signals. The new or replacement parent run may need the child result. If that run reads and handles the result, however, the matching completion wake must be acknowledged and cancelled or merged. It must not run afterward as a stale status-only response.
A user message sent with Queue currently goes behind existing queued work. Steer and Restart replace the active attempt but leave queued completion runs intact. The implementation must define priority so old completion work cannot unexpectedly follow newer user intent.
Queue controls must preserve ownership
The current queue UI exposes server-created completion wakes to the same Edit, Reorder, Steer, and Remove actions as ordinary user messages.
- Remove: cancel the run and durably dispose of its delivery ownership so restart cannot recreate it.
- Steer: reapply the provider-aware rule. In particular, do not promote a Grok completion into interrupt-and-restart steering.
- Edit and Reorder: either hide these actions for server-owned completion wakes or preserve ownership and user-message priority explicitly.
Archive and delete are durable barriers
Archive already cancels queued runs, and the continuation worker drops an offer for an archived thread. Delete cancels queued and active runs and rejects later delivery. The completion design should use the same durable principle and ensure recovery cannot resurrect disposed work.
Settle is unavailable while work is active or queued. Snooze, visit, mark-unread, and provider-session detach do not acknowledge completion results. They should remain presentation or attachment controls, not implicit drop signals.
Stop, task cancellation, archive, or delete: preserve the result, dispose of automatic delivery, and never re-arm it during recovery.
New user work, Steer, or Restart: allow the new run to consume the result, then cancel or merge any stale completion delivery.
Normal child completion: acknowledge if already observed; otherwise join the one bounded coalesced delivery.
Approaches not recommended
These are not equivalent alternatives to the building blocks above. Each has a failure mode that makes it a poor general solution.
Not recommended Remove parent completion prompts entirely
The app would still record the child completion. The subagent row would change from running to completed, failed, cancelled, or interrupted; the result would remain available in that row and through task_status; connected clients would receive the update; and Waiting could clear when no background work remained.
The app would not turn that state change into a new prompt for the parent model. It would create no internal user message, no queued parent run, and no assistant response. This is what notification-only means here: a durable state update that the UI can show, not necessarily a toast or desktop notification.
Why this is not recommended: if the parent model has already ended, it stays ended. It will not read, summarize, or act on the completed child's result until the user sends another message or some unrelated mechanism starts another run. Background work can therefore finish successfully without the parent ever incorporating it, even when acting on that result was the reason for delegating.
It eliminates stale completion queues and forced output, but only by removing automatic async handoff from the product contract. Agents would have to use wait mode or poll task_status before ending whenever the result matters.
Not recommended Treat presentation changes as the fix
There are three different presentation changes, and they do not have the same risk.
- Hide the internal completion prompt: reasonable if it is implementation detail, but delivery still invokes the parent and produces assistant output. That output must remain visible.
- Group the completion run under the originating user turn: a useful companion to scheduling changes. The user can still expand it and understand later references.
- Hide the assistant response: unsafe as the main fix. The provider call, queue pressure, tokens, and repeated work still happen, while later visible responses can refer to history the user cannot see.
Presentation alone does not fix scheduling. It can make the symptom less visible while preserving its cost and context effects.
Not recommended Infer a wait for every sibling
Delay the continuation until every child in a known batch or cohort reaches a terminal state, then accept one parent invocation and its resulting assistant output.
- This gives a bounded parallel review set one clean synthesis point.
- A long-running or stuck child can delay every useful result.
- If the parent is still creating new children, the system cannot know that the set is closed without an explicit batch or join boundary.
- Failure, cancellation, and timeout behavior become part of the batch contract.
Why this is not recommended as the general fix: a long-running child can block every useful result, and the system cannot safely infer that a changing sibling set is complete. Waiting for all belongs in a separate batch or join API with an explicit close boundary, timeout, and failure policy.
Recommended shape
Combine the two viable building blocks. Suppress wakes for results already handled by an active parent, then coalesce the remaining unobserved completions. This preserves automatic resume while accepting at most one completion-driven assistant output for each surviving cohort.
Presentation can support that behavior by hiding the internal prompt and grouping the visible completion run under its originating turn. It should not hide real assistant output.
First: preserve acknowledged results but drop their redundant automatic delivery.
Then: coalesce the remaining unobserved results into one bounded continuation.
On delivery: Queue every surviving delivery in the first patch. Native in-place Steer remains a separately provable future option.
Finally: leave real assistant output visible. Grouping is a later presentation companion, not this scheduling fix.
Implementation update
#5311 delegated-completion-delivery implements this design as an independent CTM follow-up. The originating parent run is the durable cohort boundary.
- Terminal
task_status reads acknowledge the specific task and cancel an unstarted delivery when no owned task remains.
- One queued or active delivery accepts terminal siblings, then at most one bounded successor accepts results that arrive after the first delivery starts.
- Stop, task cancellation, Queue Remove, archive, and delete dispose automatic delivery durably without erasing the child result.
- Server-owned completion messages cannot be edited, reordered, or promoted to Steer. Remove remains available as an explicit ownership-aware dismissal.
Deliberately conservative delivery: this first patch queues every surviving delivery, including providers with true active steering. That preserves foreground work and avoids provider-specific steering races while still removing the reported fan-out. Native in-place steering remains a separately provable future optimization.
The patch keeps real assistant output visible and does not add timeline grouping or hiding. Correct scheduling comes first.
Appendix: local dogfood sample
This is metadata from one local dogfood database on 2026-08-03, not representative product telemetry. No message text, thread title, or thread ID is included.
- 74 delegated completion wakes appeared across five parent threads.
- 41 results had already been read by another parent run before their wake started.
- 21 wakes were cancelled, and every one of those results had already been read.
- 31 results were first observed through their wake run.
- At least 15 completed wake runs only read and acknowledged the result.
- 34 completed wake runs performed some command, file, or other tool work, including 16 that delegated more work.
The wakes are often redundant, but the current data does not support treating every wake as inert.