[BUG] Background Agent tasks persist as "running" in /workflows after full process restart on both dispatch and viewing hosts
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Background Agent subagent task records survive a full Claude Code process restart on both the dispatch host AND independent viewing hosts, continuing to display as "running" in /workflows indefinitely.
After dispatching multiple background Agent subagents (run_in_background: true) in a session, the subagents complete normally — tool-result notifications fire, results visible inline, the orchestrator continues working with the returned data. However, the /workflows UI continues to show those tasks as actively running, with elapsed-time counters incrementing past completion. This persists through:
- Full Claude Code CLI restart on the dispatch host
- Independent restart of Claude.ai web UI and Claude Code on a separate viewing host
- Multiple dispatch/restart cycles over a multi-day project (2026-06-04 through 2026-06-06)
TaskStop invoked on the affected IDs returns "No task found" (the orchestrator-side namespace doesn't match the /workflows UI's view) yet the UI keeps showing them active. IDs derived from the .output filenames in ~/AppData/Local/Temp/claude/.../tasks/ are likewise unreachable by TaskStop. State surviving a clean restart of both clients on different machines strongly suggests server-side state retention without a corresponding reap on client reconnect.
What Should Happen?
Either of these would resolve it:
- Reap on client reconnect. When a Claude Code client establishes a session with completed background-task records older than some sane threshold (e.g. last result-notification + 1 hour), the server-side state machine transitions them to a terminal state and the UI reflects that.
- Transition on result-notification. When a background Agent subagent's tool-result notification fires (the same event the orchestrator already consumes inline), the server-side task-lifecycle state machine should transition the task to
completed. Today the notification appears to reach the orchestrator but not flow through to the/workflowsUI's data source.
Either way: /workflows should be a real-time reflection of in-flight work, not a monotonically-growing ledger of historical dispatches.
Error Messages/Logs
Error Messages/Logs: (empty — no error output; this is a silent state-leak, not a crash)
Steps to Reproduce
- Open a Claude Code CLI session on Host A.
- From the model, dispatch ≥3 background Agent subagents in a single message:
Agent({ description: "smoke test 1", subagent_type: "general-purpose",
prompt: "say hello and exit", run_in_background: true })
Agent({ description: "smoke test 2", subagent_type: "general-purpose",
prompt: "say hello and exit", run_in_background: true })
Agent({ description: "smoke test 3", subagent_type: "general-purpose",
prompt: "say hello and exit", run_in_background: true })
- Wait for each
<task-notification>with<status>completed</status>to arrive in the conversation (typically 30-90s per subagent). - Open
/workflowsfrom Host A — observe the three tasks listed as actively running. - Quit the Claude Code CLI on Host A entirely (close the terminal window or
Ctrl-Dout, ensure process is dead). - Independently restart any Claude.ai web UI or Claude Code instance on Host B.
- Open
/workflowsfrom either host.
Result: the three smoke-test tasks are still listed as actively running, with elapsed-time counters incrementing past their actual completion times. Try invoking TaskStop on any of the IDs — it returns "No task found", but the UI still shows them active.
Continue dispatching subagents over a multi-day window and the zombie set accumulates monotonically. After ~48 hours of normal use we observed 20+ zombie entries in /workflows, blocking practical use of the UI as a status surface.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.165 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Local workaround built around the issue
We hit this in the context of building a local agent-orchestration framework. Since the /workflows UI namespace was opaque to our TaskStop calls, we built a parallel append-only audit graph on our own bus to track the truth:
agent.dispatchedevent logged before everyAgenttool call (carries task_id, prompt summary, expected scope, parent run id).agent.completedevent logged when the tool-result notification fires (carries exit status, result summary, usage).agent.stoppedevent logged on everyTaskStopattempt — includingnamespace_hit: falsecases, which are the orchestrator-side mismatch this bug exposes.- A periodic reaper queries
dispatchedwithout matchingcompleted/stoppedpast a stale threshold and emitsagent.zombieevents for our dashboard.
The pattern works around the harness opacity but doesn't address the underlying state persistence. Our local bus correctly identifies zombies; the /workflows UI is still showing them as live because its data source apparently doesn't know they're dead.
Why this matters for Claude Code itself
If the server-side task-lifecycle state machine had a last_notification_at timestamp and a passive sweep, it could self-diagnose stuck dispatches the same way our reaper does — dispatched without completed for N hours = zombie, mark terminal. Same pattern, just one altitude up.
Environment notes
- Both hosts (X dispatch, Yviewing) on the same LAN
- Different Anthropic API plans — issue reproduces on Max plan
- No proxy/firewall between hosts and Anthropic API
- Background subagents were
general-purposetype for the affected cases
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗