Workflow tool: stall watchdog kills actively-working subagents every ~8-9 min; identical-key retry loop burned ~580k tokens with zero progress
Summary
The Workflow tool's stall watchdog repeatedly killed a subagent that was actively working (making successful tool calls right up to the kill), then restarted it from scratch with no transcript carry-over. The agent's task (fix a reviewed MR in a mid-size TypeScript repo: clone, npm ci, spin up a test Postgres, then edit code) legitimately needs more than the watchdog window, so every attempt was killed mid-recon and the retry loop never converged. 4 attempts × full repo re-exploration ≈ 580k tokens burned with zero lines of code written.
Environment
- Claude Code v2.1.226, macOS (darwin 25.5.0)
- Main session model: claude-fable-5; workflow subagent: sonnet (
{"agentType":"workflow-subagent","spawnDepth":1,"model":"sonnet"}) - Workflow run: 4 phases, first phase = single
agent()call (code-fix task),model: 'sonnet'
What happened
journal.jsonl for the run contains only 4 started events — same cache key, 4 different agentIds, no agent_end, no completions:
started key=v2:3a8f4dee… agentId=a994a0391e377b2d4 (12:56)
started key=v2:3a8f4dee… agentId=aa6f071d9f3db4795 (13:05)
started key=v2:3a8f4dee… agentId=a91a95270858c39c4 (13:14)
started key=v2:3a8f4dee… agentId=ac765560269554cc0 (13:22)
Kill interval is a steady ~8–9 minutes. Each attempt's transcript (~430–460 KB) shows the agent mid-work — successful Read/Bash/Grep tool calls with results flowing — and then terminates with:
[Request interrupted by user]
No user interrupted anything; that's the runner's watchdog. Each restart began from zero: re-clone checks, re-reading the same files, re-doing environment setup (the 4th attempt did get as far as npm ci + starting a Postgres test container — then was killed too when we stopped the run manually).
Why this is a design problem, not just a tuning problem
- "Stalled" is detected by wall-clock, not by activity. The agent was demonstrably not stalled — tool calls were succeeding continuously. A watchdog should look at "time since last tool event", not "time since agent start".
- Retry discards the transcript. Even if a kill is justified, restarting with zero memory of the previous attempt guarantees the same ~9 minutes of recon is re-purchased each round. For any task whose honest duration exceeds the window, this is an unbounded token-burning loop with guaranteed zero progress.
- No surfacing. The main session got no notification that attempts were being killed and retried; we only found out by inspecting
journal.jsonland the per-agent transcripts after noticing token spend (~580k) wildly out of proportion to the task.
In an earlier run the same watchdog produced visible "stall-retry after 708s / 451s" messages and those (planning) agents happened to finish within the window on retry — so the mechanism exists and sometimes recovers. It becomes pathological exactly when the per-agent task is legitimately longer than the window, which is common for real coding tasks (npm ci alone can eat several minutes).
Expected
- Watchdog keyed to tool-call inactivity, not total runtime (or at minimum a much larger / configurable per-agent budget).
- On retry: resume or at least seed the successor with the predecessor's transcript/summary.
- A cap on identical-key retries + a
log()-visible warning to the parent session when a retry happens.
Workaround
Killed the workflow (TaskStop), re-ran the same brief as a plain background Agent (no watchdog) reusing the surviving clone/node_modules/test-DB — completed normally.