Skip to content

In-turn background work (Workflow / run_in_background / Workflow-backed skills) is SIGKILLed at the turn boundary under the claude-cli runtime #97919

Description

@alfredjbclaw

Summary

Under the claude-cli agent runtime, any background work started inside a turn — the Workflow tool, Bash run_in_background, or a skill built on them (e.g. deep-research) — is SIGKILLed at the next turn boundary and never delivers. The tools' contracts ("runs in the background, returns immediately, notifies on completion") assume a host process that outlives the turn. The claude-cli runtime provides no such host: it spawns a fresh, ephemeral claude -p … --output-format stream-json process per turn as a child of the gateway and reaps it when the turn ends. Everything launched in-process dies with it.

This is the unifying root cause behind a cluster of separately-reported symptoms (#94677, #85068, #76259). They've each been treated as an isolated bug; they're the same process-model mismatch viewed from different angles.

Steps to reproduce

  1. On the claude-cli runtime, start any long in-process background job in a turn — e.g. invoke the Workflow tool, or Bash with run_in_background: true, or a Workflow-backed skill.
  2. End the turn (send the next message, or simply let the turn complete).
  3. Observe the job never produces its deliverable. On resume you get one of:
    • a completion record that was never enqueued (job launched at T, session ended at T+10m, zero notification);
    • an explicit "status":"killed" in the task notification;
    • "No completion record was found for background … it may have been running when the previous process exited."

Evidence

  • Process model. Live ps shows several short-lived claude -p … --output-format stream-json processes, all children of the gateway, each with an etimes spanning a single turn. There is no persistent model process for background work to attach to.
  • Transcripts. Across multiple real sessions that invoked Workflow, the failure is consistent: workflows return "status":"killed" the instant the next user turn begins, and in-turn watchers/monitors are stopped at the same boundary. The kill is correlated 1:1 with the turn boundary, not with the job's own state.

Why this matters

The affected surfaces are advertised as the supported way to run long/async work. On the most common CLI runtime they cannot fulfil that contract, and the failure is silent — the user sees a launch acknowledgement and then nothing, with no error surfaced in the channel. The natural workaround (re-launch / resumeFromRunId) re-dies the same way, so the work is effectively unreachable.

Relationship to existing issues

Delivery-side work that a proper fix would dovetail with: #80450 (explicit detached-longwork delivery ownership), #94153 (persist completions to a queue), #96190 (parent wake after isolated run).

Suggested direction

Two independent halves:

  1. Survival — long independent work should not be hosted in the per-turn process. Either give the runtime a persistent host for background jobs, or have these tools launch detached (own session / reparented to init) so a turn boundary can't reap them.
  2. Delivery — a detached job's result needs an explicit, durable route back to its originating session/channel that survives the originating turn ending (overlaps with [Feature]: Make detached longwork final delivery ownership explicit #80450 / feat: Persist subagent completion announcements to message queue instead of direct session dispatch #94153 / RFC: opt-in cron.jobs[].notifyOnCompletion for parent wake after isolated cron run #96190).

As a data point: detaching the worker via its own session group so it reparents to init, snapshotting the origin (session key + channel + thread) at launch, and routing the result back to that origin on completion is sufficient to make long jobs both survive and deliver correctly — including concurrent jobs from different sessions, since each carries its own origin snapshot. Happy to share the reference implementation if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions