Subagents keep polling long jobs with shell sleep loops instead of using run_in_background/Monitor notifications
Summary
Subagents launched via the Agent tool repeatedly fall back to waiting for long-running shell jobs by polling: running a Bash command in a loop (until grep -q DONE log; do sleep N; done, tail -f --pid=<pid>, repeated tail/grep/pgrep calls) where every wake-up is a tool round that triggers a new model turn. This happens even when the prompt explicitly forbids it and spells out the alternative: Bash with run_in_background: true (harness re-invokes the agent on exit) or the Monitor tool armed on a completion condition.
As the user I have now had to issue the "stop polling, register the job with the harness and wait for the notification" instruction to four separate agents in two days, in increasingly explicit terms, and it keeps recurring. Each polling wake-up burns tokens for nothing.
What I expect
For a long-running job (build, test suite, benchmark), the agent should launch it once, hand the wait to the harness (run_in_background: true, or nohup … & + one Monitor call with a completion condition), and do nothing until the harness notification arrives. One wait per job.
What happens instead
Observed across four Opus subagents (Claude Code, Agent tool, model: "opus"), each with the rule in its prompt:
- Prompt said "never poll faster than once per 30 s; prefer run_in_background/Monitor". Agent ran a ~10 s check loop on a log file. Corrected mid-run via SendMessage.
- Prompt spelled out the mechanics (
run_in_background: trueornohup+ Monitor; nosleep+tail/grep/pgreploops; ≥ 60 s if unavoidable). Agent complied for later jobs but its report admitted early waiters at 20–25 s intervals. - Prompt as in (2). Agent used
until grep …; do sleep 30–60; doneloops inside Bash calls andtail --pid -fblocking waits — technically slower, still the polling shape rather than the harness notification. - Prompt as in (2) plus a self-report requirement. Agent still ran 60 s sleep loops as Bash tool calls; I had to send a mid-run message forbidding every named pattern before it stopped.
Pattern: the agent treats "wait" as "write a shell loop that returns when done" rather than "register the job and stop". Even when told, it converts the instruction into a slower loop instead of switching mechanism. Stronger prompt wording reduces the frequency but has not eliminated it.
Suggestions
- Make the harness-notification path the obvious default in the Agent/Bash tooling: e.g. when a Bash call is launched with
run_in_background: true, the tool result could state plainly "you will be notified on exit; do not poll", and a foreground Bash call whose command containssleepinside a loop, ortail --pid/tail -f, could be flagged or refused for subagents. - A per-agent rate limit or warning on repeated Bash calls that only read a log/
pgrepwith no other effect. - Document the "one wait per job" pattern in the Agent tool description itself, since prompt-level rules are being paraphrased away.
Environment
Claude Code in a VS Code devcontainer (Linux/WSL2), Agent tool with subagent_type: general-purpose, model: "opus"; parent session on Fable 5.1. Long jobs were cargo builds/tests and benchmark scripts, typically 5–40 minutes each.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗