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
workflow schema agents: offer one in-session corrective turn when the final message never calls structured_output (run is discarded today)
#5903
The workflow tool's agent(prompt, { schema }) hook runs a one-shot child whose final value is captured via the child-scoped structured_output tool (attachStructuredRuntime in dsh-subagent-in-process-driver). In dsh-workflow-worker-thread's worker (worker.cjs), when the child run ends with stopReason === "completed" but result.structured === void 0 (the model finished without ever calling structured_output), the worker returns null — a failed result with no retry and no signal beyond the null.
Problem
This discards the entire child run even when the child did all of its real work. In production we drive deterministic multi-stage engineering pipelines (schema-validated stage agents with 50–200 tool calls per stage) through the workflow tool. With thinking-capable models served behind Anthropic-protocol gateways, long agentic chains occasionally end with a thinking-only final response — the gateway injects a placeholder text block to keep the protocol shape valid, the final assistant message is plain text, structured stays undefined, and the worker nulls the run. The orchestrator's only recourse is a full stage re-run (fresh child, all work redone).
Measured impact in our setup: re-runs caused by this failure mode accounted for roughly half of total orchestration wall time in a ~2-hour pipeline (two full IMPLEMENT re-runs in one run; the same death mode also hit other stages).
Note the asymmetry: when the model does call structured_output with invalid arguments, ToolArgsError surfaces validation violations and the agent loop self-corrects in-session. The only unrecoverable gap is "never called the tool at all" — which is precisely the case where all completed work is thrown away.
Proposed fix
When opts.schema !== void 0 && result.structured === void 0 && result.stopReason === "completed" (run not cancelled, child still disposable): instead of returning null immediately, append one corrective user turn to the same child run/session, e.g.
Your final answer must be reported by calling the structured_output tool. Re-submit your final result now as a single structured_output tool call. Do not redo any work and do not add explanations.
Then re-check the captured value; if still missing (cap of 1 corrective turn), fall back to today's null behavior. The child session already holds the full context, so the corrective turn is one cheap model call versus a complete stage re-run.
A lighter-weight alternative: expose a per-call knob (e.g. agent(prompt, { schema, structuredRetry: 1 }), default 0 = current behavior) so orchestrators opt in.
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.
Context
The
workflowtool'sagent(prompt, { schema })hook runs a one-shot child whose final value is captured via the child-scopedstructured_outputtool (attachStructuredRuntimeindsh-subagent-in-process-driver). Indsh-workflow-worker-thread's worker (worker.cjs), when the child run ends withstopReason === "completed"butresult.structured === void 0(the model finished without ever callingstructured_output), the worker returnsnull— a failed result with no retry and no signal beyond the null.Problem
This discards the entire child run even when the child did all of its real work. In production we drive deterministic multi-stage engineering pipelines (schema-validated stage agents with 50–200 tool calls per stage) through the workflow tool. With thinking-capable models served behind Anthropic-protocol gateways, long agentic chains occasionally end with a thinking-only final response — the gateway injects a placeholder text block to keep the protocol shape valid, the final assistant message is plain text,
structuredstaysundefined, and the worker nulls the run. The orchestrator's only recourse is a full stage re-run (fresh child, all work redone).Measured impact in our setup: re-runs caused by this failure mode accounted for roughly half of total orchestration wall time in a ~2-hour pipeline (two full IMPLEMENT re-runs in one run; the same death mode also hit other stages).
Note the asymmetry: when the model does call
structured_outputwith invalid arguments,ToolArgsErrorsurfaces validation violations and the agent loop self-corrects in-session. The only unrecoverable gap is "never called the tool at all" — which is precisely the case where all completed work is thrown away.Proposed fix
When
opts.schema !== void 0 && result.structured === void 0 && result.stopReason === "completed"(run not cancelled, child still disposable): instead of returningnullimmediately, append one corrective user turn to the same child run/session, e.g.Then re-check the captured value; if still missing (cap of 1 corrective turn), fall back to today's
nullbehavior. The child session already holds the full context, so the corrective turn is one cheap model call versus a complete stage re-run.A lighter-weight alternative: expose a per-call knob (e.g.
agent(prompt, { schema, structuredRetry: 1 }), default 0 = current behavior) so orchestrators opt in.Environment
@deepseek-ai/dsh-workflow-worker-thread,@deepseek-ai/dsh-subagent-in-process-driver)All reactions