Background task completion notifications lost after CLI process restart; stalled-stream agent deaths surface late

Status Open
Maintainer reply None cached
Activity 3 comments · opened Jul 7, 2026

Environment

  • Claude Code CLI (native install), macOS (darwin 25.5), model claude-opus-4-8[1m] / claude-fable-5 sessions

Symptom 1: completion records lost across CLI restart

When the CLI process exits while background work (Agent tool subagents, Workflow tool runs) is still executing, the next session receives notifications like:

No completion record was found for background workflow "..." from the previous session. It may have been stopped (via the UI or TaskStop — these leave no transcript marker), or it may have been running when the previous Claude Code process exited.

The underlying subagent transcripts/journals are still on disk, but the orchestrating conversation gets no completion notification and must manually resume every run (Workflow resumeFromRunId / SendMessage). With several concurrent background tasks this silently drops the coordinator's state.

Expected: on restart, the harness reconciles still-running/finished background tasks and delivers completion (or explicit orphaned-task) notifications automatically.

Symptom 2: background agents dying instantly on "Response stalled mid-stream", notification sometimes delayed

Several background Agent-tool subagents terminated within seconds with:

Agent terminated early due to an API error: API Error: Response stalled mid-stream. The response above may be incomplete.

In one case the agent stopped (transcript ~136 bytes) and the completion task-notification did not reach the main conversation across multiple subsequent turns (~3+ min), while an external observer could already see the task as stopped. A retry via SendMessage works, but the coordinator only learns about the death late or via manual polling.

Expected: terminal API errors on background agents should surface a completion notification promptly on the next turn boundary.

Impact

Long autonomous multi-agent sessions (5-10 background tasks) require manual babysitting of task liveness, defeating the purpose of background orchestration.

Repro sketch

  1. Launch several background Agent/Workflow tasks.
  2. Restart the CLI process (or hit a mid-stream API stall).
  3. Observe missing completion records / late notifications in the resumed session.

View original on GitHub ↗

3 Comments

kcarriedo · 2 months ago

Both symptoms you've described point to the same underlying gap: the orchestrating session has no durable record of "which subagent runs were live when I exited," so on restart it cannot distinguish completed-but-unreported work from work that never ran.

On symptom 1 (completion records lost across restart): the reconciliation you're asking for requires the harness to maintain a write-ahead log of in-flight background tasks that survives the CLI process. Right now the JSONL transcripts are the only on-disk artifact, and they're the subagent's own record, not a coordinator-side manifest. What that means in practice: if you are running a wrapper or polling layer above Claude Code, you can maintain this manifest externally -- each Agent tool dispatch gets written to a local file with its correlation ID and expected-completion window, and on restart your wrapper replays the manifest to surface the orphaned tasks. Not a substitute for native reconciliation, but it makes the restart case manageable.

On symptom 2 (stalled-stream deaths surface late): the delayed notification on a background agent that died within seconds is the harder failure mode. From the outside, the only way to detect it without native liveness signaling is a timeout watchdog: if a background agent hasn't emitted any output within N seconds of spawn, treat it as stalled and surface an alert to the coordinator. The 136-byte transcript is a useful tell -- any background agent with a completed transcript under a few KB terminated before doing meaningful work and should trigger a fast-path alert.

For long autonomous sessions (5-10 background tasks), the manual babysitting problem comes down to one missing primitive: a heartbeat receipt from each background agent that the coordinator can poll without blocking. The workaround -- and it's a workaround -- is to have the first tool call in each background agent's prompt write a "started" marker to a shared scratch location the coordinator can check independently.

Tracking this for a tool that coordinates multiple Claude Code sessions with external state. The "background task started but not reported" edge is one of the harder correctness problems from outside the process.

(Disclosure: Kyle Carriedo, building Claudeverse -- claudeverse.ai -- which tracks session lifecycle across Claude Code runs.)

Sergio-3 · 22 days ago

Same symptom here, and I think the cause is now pinned down. I've put the analysis on #75037 rather than duplicating it here, since that thread was already digging into it: the accurate "had already completed, only the notification was lost" wording does exist in the binary, but it sits behind a handover that the SDK embedding path never reaches, so what surfaces is always the "no completion record" variant regardless of version.

Your repro is the part I don't have, so if these are the same thing it seems worth keeping this one open.

samvallad33 · 22 days ago

Background task completion notifications lost after CLI restart hide stalled-stream agent deaths from operators. Concrete context loss then looks like a quiet hang. Would a crash and resume suite covering SIGKILL lock notification delivery down?