[BUG] Background Agent tasks persist as "running" in /workflows after full process restart on both dispatch and viewing hosts

Open 💬 6 comments Opened Jun 6, 2026 by R8ze

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:

  1. 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.
  1. 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 /workflows UI'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

  1. Open a Claude Code CLI session on Host A.
  2. 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 })

  1. Wait for each <task-notification> with <status>completed</status> to arrive in the conversation (typically 30-90s per subagent).
  2. Open /workflows from Host A — observe the three tasks listed as actively running.
  3. Quit the Claude Code CLI on Host A entirely (close the terminal window or Ctrl-D out, ensure process is dead).
  4. Independently restart any Claude.ai web UI or Claude Code instance on Host B.
  5. Open /workflows from 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.dispatched event logged before every Agent tool call (carries task_id, prompt summary, expected scope, parent run id).
  • agent.completed event logged when the tool-result notification fires (carries exit status, result summary, usage).
  • agent.stopped event logged on every TaskStop attempt — including namespace_hit: false cases, which are the orchestrator-side mismatch this bug exposes.
  • A periodic reaper queries dispatched without matching completed/stopped past a stale threshold and emits agent.zombie events 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-purpose type for the affected cases

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗