You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] Subagent epoch that burns its entire output budget on reasoning (zero tool calls, zero output) settles as completed with an empty closing message
#10357
Hello — I searched the discussions before posting; the closest threads I found are #9124 (terminated sub-agent output unrecoverable), #5903 (thinking-only final response discards a workflow run), and #4666 (spawn backend drops reasoningEffort). The case below looks like a distinct sibling on the normal-settlement path of continuable subagents: no termination, no schema — just a completed verdict over a run that never called a tool. If my analysis is off, corrections are very welcome.
Symptom
A background continuable child (subagent({ run_in_background: true })) settled as completed after ~20 minutes with:
an empty closing message (no Its closing message: block in the notice);
zero disk artifacts (the child never created its working directories);
get_subagent_status before settle: "no activity observed".
The dispatch was a self-contained mechanical rewrite brief (rewrite 13 markdown files, script-verified acceptance). The parent could not tell "the child never started working" from "the child worked and failed" — the same ambiguity class as #9124, but reached via a normal settlement.
What the child's session log shows
The child session log (.dsh/sessions/<workspace>/<subagentId>/session.v4.jsonl.zstd, multi-frame zstd) tells the whole story:
exactly 1 turn / 1 step for its whole lifetime;
the assistant message's content blocks are ["reasoning"] only — no text, no tool_use;
So the model spent the entire output budget on reasoning, the provider ended the response cleanly (no truncation error surfaced), and the epoch folded to completed.
Source localization (0.2.0-rc.2)
In @deepseek-ai/dsh-subagent/lib/index.js:
createActivationObserver initializes captured = { stopReason: "completed" } as the default (~L301);
epochStopReason (~L343–352): case void 0: case "completed": return droppedUnrun ? "aborted" : "completed" — an epoch whose event suffix contains no closing turn/end still reports completed;
observeRun attaches lastAssistantMessage only when output.length > 0 — hence a settlement notice without a closing message.
Net effect: a reasoning-only epoch (zero tool calls, zero assistant text) is indistinguishable, from the parent side, from a successful run. The settlement machinery has no signal a parent could use to treat this as anything but success.
Why it matters
The dispatch's value lives entirely on disk. A completed with an empty closing message reads as success, so the orchestrator may proceed (or report success) while the deliverable never existed. Cost side: the child burned its full output budget (~32k tokens) producing nothing observable.
Suggested directions (non-prescriptive)
When an epoch ends with zero tool calls and zero non-empty assistant text while output tokens are at/near the cap, consider reporting it as max-tokens (or a dedicated reason) rather than completed.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Hello — I searched the discussions before posting; the closest threads I found are #9124 (terminated sub-agent output unrecoverable), #5903 (thinking-only final response discards a workflow run), and #4666 (spawn backend drops reasoningEffort). The case below looks like a distinct sibling on the normal-settlement path of continuable subagents: no termination, no schema — just a
completedverdict over a run that never called a tool. If my analysis is off, corrections are very welcome.Symptom
A background continuable child (
subagent({ run_in_background: true })) settled ascompletedafter ~20 minutes with:Its closing message:block in the notice);get_subagent_statusbefore settle: "no activity observed".The dispatch was a self-contained mechanical rewrite brief (rewrite 13 markdown files, script-verified acceptance). The parent could not tell "the child never started working" from "the child worked and failed" — the same ambiguity class as #9124, but reached via a normal settlement.
What the child's session log shows
The child session log (
.dsh/sessions/<workspace>/<subagentId>/session.v4.jsonl.zstd, multi-frame zstd) tells the whole story:["reasoning"]only — notext, notool_use;inputTokens: 32,853,outputTokens: 32,000(exactly the output cap),reasoningTokens: 31,955;turn/endreason:completed.So the model spent the entire output budget on reasoning, the provider ended the response cleanly (no truncation error surfaced), and the epoch folded to
completed.Source localization (0.2.0-rc.2)
In
@deepseek-ai/dsh-subagent/lib/index.js:createActivationObserverinitializescaptured = { stopReason: "completed" }as the default (~L301);epochStopReason(~L343–352):case void 0: case "completed": return droppedUnrun ? "aborted" : "completed"— an epoch whose event suffix contains no closingturn/endstill reportscompleted;observeRunattacheslastAssistantMessageonly whenoutput.length > 0— hence a settlement notice without a closing message.Net effect: a reasoning-only epoch (zero tool calls, zero assistant text) is indistinguishable, from the parent side, from a successful run. The settlement machinery has no signal a parent could use to treat this as anything but success.
Why it matters
The dispatch's value lives entirely on disk. A
completedwith an empty closing message reads as success, so the orchestrator may proceed (or report success) while the deliverable never existed. Cost side: the child burned its full output budget (~32k tokens) producing nothing observable.Suggested directions (non-prescriptive)
max-tokens(or a dedicated reason) rather thancompleted.output.length === 0— e.g. "(no assistant text, no tool calls — likely reasoning-only exhaustion)". That alone converts a silent loss into an actionable one, and aligns with [Bug] Terminated sub-agent output is unrecoverable: no closing message, no registry entry, no read-back path #9124's ask on the terminated path.get_subagent_status, so parents can cheaply detect this shape.Current workaround (confirmed effective)
reasoning_effort: "low"explicitly for mechanical/rewrite briefs (withprovider+modelsupplied paired);completed, run a three-point check: closing message non-empty / heartbeat file ends with done / disk artifacts exist.With the workaround, the same brief completes in ~2 minutes with all deliverables verified on disk.
Environment
@deepseek-ai/dsh-subagent0.2.0-rc.2)subagent({ run_in_background: true }), continuablereasoning_effortnot passed → default highThanks for reading — happy to provide the full session-log excerpt (already sanitized) if useful.
All reactions