Workflow tool: stall watchdog kills actively-working subagents every ~8-9 min; identical-key retry loop burned ~580k tokens with zero progress

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 9, 2026

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

  1. "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".
  2. 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.
  3. No surfacing. The main session got no notification that attempts were being killed and retried; we only found out by inspecting journal.jsonl and 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.

View original on GitHub ↗