Workflow tool: `args` never reaches the script sandbox (all invocation forms — named, scriptPath, resume)
Summary
A workflow script that reads the documented args global fails with its own "args required" guard in every invocation form — the args value passed to the Workflow tool never reaches the script's sandbox context.
Environment
- Claude Code CLI 2.1.226 and 2.1.227 (observed on both), macOS (darwin 25.6.0)
- Model: claude-fable-5
- Script stored under
.claude/workflows/(project scope)
Reproduction
Script begins (after the meta block) with the documented guard pattern:
if (!args || !args.mode || !args.planFiles || !args.planFiles.length) {
throw new Error('args required: {mode, featureDir, planFiles[], specPath, distilledPath}')
}
All three invocation forms fail identically, in 4–16 ms, before any agent spawns:
Workflow({name: "plan-gate-review", args: {mode: "gate", planFiles: [...], ...}})— named workflow resolved from.claude/workflows/Workflow({scriptPath: "<session script copy>", args: {...}})— fresh launch by pathWorkflow({scriptPath: "...", resumeFromRunId: "wf_...", args: {...}})— the resume form that the failure notification's own recovery text recommends
In forms 2 and 3, args was passed as a proper JSON object (form 1's first attempt used a JSON-encoded string — a documented mistake — but the object forms fail the same way).
Failure output (identical each time):
Error: args required: {mode, featureDir, planFiles[], specPath, distilledPath}
at <anonymous> (workflow.js:13:9)
at workflow.js:157:1275
at runInContext (native)
at lBp (/$bunfs/root/src/entrypoints/cli.js:6680:9138)
Run IDs from the observing session, if useful for server-side correlation: wf_4e51f736-a79 (two attempts), wf_4c0c123e-3c6.
Expected
Per the tool description, args is "the value passed as Workflow's args input, verbatim (undefined if not provided)" — a script guard on args.mode should pass when an object with mode is supplied.
Actual
The script's sandbox context sees no args (guard throws as if undefined), regardless of invocation form. The tool layer accepts the parameter; the runInContext script environment apparently never receives the global.
Impact
Parameterized/named workflows are effectively unusable: every invocation requires generating a per-use script copy with the argument values embedded as constants, which defeats the .claude/workflows/ registry and the args-based reuse the tool documents (e.g. while (budget.total && ...) patterns are fine, but any args.<field> parameterization is dead).
Workaround
Embed defaults in the script and fall back when args is absent:
const EMBEDDED = { mode: 'gate', /* ... */ }
const A = (typeof args !== 'undefined' && args && args.mode) ? args : EMBEDDED
With that pattern the same script runs to completion (a 14-agent run finished normally), confirming the defect is isolated to args delivery, not script execution.
Secondary (related, minor): diagnostics false-positives on workflow scripts
The session language server parses workflow scripts as plain modules, so the runtime-valid top-level return produces cascading false diagnostics ("'x' is declared but its value is never read" for values used in the return object). Separately, when subagents copy project code into the session scratchpad for sandboxed execution, the main session surfaces spurious missing-import diagnostics from those partial copies. Both are cosmetic but erode trust in the diagnostics stream.
---
🤖 Filed with Claude Code on the operator's instruction.