Workflow: write agents write status reports instead of file content; schema-read agents silently return null; resumed workflow overwrites manual fixes after long delay
Summary
Three related failures observed when using the Workflow tool with large document
assembly tasks. Each is reproducible and has a clear workaround, but together they
make the write step of any document-generation workflow unreliable.
---
Failure 1 — Write agent writes a self-authored status report instead of calling Write with provided content
What was asked:
A write:final agent received a ~900-line Markdown document embedded between<document> tags in its prompt and was told to write every line to a file using the
Write tool.
What happened:
The agent called the Write tool, but the content parameter was a self-authored
summary describing the document structure and authoring standards applied — not the
actual content provided. The output file contained ~108 lines of meta-description
rather than the ~900-line document.
This happened across every attempt regardless of prompt wording, tag style, or
document size reduction. The failure is consistent when the prompt contains
≥ ~200 lines of document content.
Workaround: Bypass the write agent entirely. Extract section content from agent
transcript .jsonl files in the workflow subagents directory using a Python script,
then write the file directly via Python file I/O.
---
Failure 2 — Schema-validated read agent silently returns null; causes workflow early termination
What was asked:
A simple file-read agent was called with schema: { type: 'object', properties: {, asked to read a 214-line
content: { type: 'string' } }, required: ['content'] }
Markdown file and return its content in the content field.
What happened:
The agent was interrupted (the parent task was stopped to resolve an unrelated issue),
leaving the parallel slot as null. When the workflow resumed, the cached result for
the modified agent was also null. The validation check if (nullSections.length > 0) fired, terminating the workflow before the write phase.
{ return { error: '...' } }
The task output file was empty. No error was surfaced to the caller — the workflow
reported "completed" with an empty result.
The secondary issue: using return { error: ... } in a workflow script causes the
task to report "completed" rather than "errored", making silent failure invisible.
Workaround: Replace hard return on validation failure with log() warnings
and fallback content; never return early on null sections.
---
Failure 3 — Resumed workflow's delayed write agent overwrites manually corrected output file
What happened:
After the write phase failed (Failures 1 & 2), the output file was manually corrected
using a Python extraction script. The resumed workflow (resumeFromRunId) had queued
write agents that were still running. Approximately 91 minutes after the resume call,
the workflow's write:final agent completed and overwrote the manually corrected file
with the same status-report content (Failure 1 repeated).
TaskStop had been called earlier on the original task ID but not on the
resumed run. The resumed run continued in the background and its write agents
were never cancelled.
Workaround: Call TaskStop on the resumed task ID before making any manual
corrections to workflow output files.
---
Environment
- Claude Code version: 2.1.168
- Model: claude-sonnet-4-6
- Platform: macOS (darwin 25.5.0)
- Workflow pattern: 6 parallel schema-validated synthesis agents → assemble fullContent
string → write:final agent receives fullContent in prompt
Suggested improvements
- Write agents with large content: Consider a dedicated
WriteFile(path, content)
step in workflow scripts that bypasses agent generation entirely — similar to how
phase() and log() are native workflow primitives rather than agent calls.
- Silent workflow termination: When a workflow script
returns with{ error: ... },
surface this as a failed/errored task status rather than "completed".
- TaskStop scope: When stopping a workflow task, automatically cancel any pending
agents spawned by that run ID, including in resumed runs.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗