[Docs] Workflow tool args parameter is undocumented; nested-array gotcha causes runtime errors

Resolved 💬 2 comments Opened May 29, 2026 by anipotts Closed Jun 2, 2026

summary

the public workflows page at code.claude.com/docs/en/workflows.md doesn't document the args parameter. only mention of "args" in the entire doc is in the disableWorkflows setting line (line 228). meanwhile the in-tool description has explicit warnings about args marshalling that users only see if they paste a workflow script into a session. this surfaces as runtime errors like #63253.

the gap

grep -in args against the rendered doc returns one unrelated hit. the public doc covers: when to use, bundled workflows, ask claude to write one, ultracode, approve plan, save for reuse, resume, cost, turn off. it does NOT cover:

  • the args parameter on the Workflow tool call
  • the args global available inside the script
  • the marshalling constraints (actual JSON vs stringified)

users hit the workflow scripting layer by accident (looking at the raw script after asking claude to write one) or by reading the in-tool description embedded in claude code itself.

what the in-tool description already says

args: any — the value passed as Workflow's args input, verbatim (undefined if not provided). Pass arrays/objects as actual JSON values in the tool call, NOT as a JSON-encoded string — args: ["a.ts", "b.ts"], not args: "[\"a.ts\", ...]" (a stringified list reaches the script as one string, so args.filter/args.map throw).

this warning is necessary for any user passing structured data into a workflow. omitting it from public docs means users only learn it by hitting #63253-style errors.

proposed insertion

after the "Save the workflow for reuse" section, before "How a workflow runs":

## Parameterize a workflow A workflow can accept structured input via the args parameter on the tool call. The script reads it as a global args variable. Pass args as actual JSON, not a JSON-encoded string: | | example | | --- | --- | | good | args: ["src/a.ts", "src/b.ts"] | | good | args: { files: ["a.ts", "b.ts"], target: "test" } | | bad | args: "[\"src/a.ts\", \"src/b.ts\"]" | A stringified list reaches the script as one string. args.filter and args.map throw. Pass nested arrays inside objects as actual JS arrays, not as JSON-encoded substrings. Inside the script, reference args directly: ``js phase('Review') const findings = await parallel(args.files.map(f => () => agent(Review ${f}, { schema: FINDINGS_SCHEMA }) )) ``

why it matters

#63253 is a real user hitting args.X.map undefined with no idea why. the in-tool warning isn't reaching them because they read the public docs page first. one paragraph in public docs prevents the class of bug.

happy to PR the change if there's a community-accessible docs repo.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗