Skip to content

fix(harness): keep a Claude task running while its background tasks wake Claude - #3149

Draft
thomasbarrett wants to merge 1 commit into
kagent-dev:mainfrom
thomasbarrett:fix/claude-background-results
Draft

thomasbarrett wants to merge 1 commit into
kagent-dev:mainfrom
thomasbarrett:fix/claude-background-results

Conversation

@thomasbarrett

@thomasbarrett thomasbarrett commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

When Claude starts a Monitor or a background shell and ends its turn, Claude Code emits a result, then another result each time the background task wakes it, and exits only once nothing is left running. The driver took the first result as terminal, so Claude's next reply failed the task with claude emitted activity after its terminal result, and the process group, background job included, was killed.

With this change a Claude harness task lives exactly as long as claude -p does: it ends when Claude exits, and the last result is its outcome.

  • Results with origin.kind: task-notification are no longer dropped by the parser; each one replaces the outcome so far.
  • Text after a result starts a new paragraph, so replies don't run together in one text artifact.
  • An approval request after a result takes the normal input-required path instead of failing.

The task stays working while background tasks run, so its Actor isn't suspended under them; cancellation still kills the process group. Claude Code bounds how long that can be: in unattended runs a background command is stopped after 30 minutes unless Claude asks for longer, at most 2 hours, and a Monitor watch lasts at most 30 minutes (tools reference). Claude can restart either. testdata/stream-background.jsonl is modelled on Claude Code 2.1.296's output for a Monitor (each wake-up is a fresh init, assistant reply and task-notification result); 2.1.296 behaves the same for a run_in_background shell.

Not in this PR: reporting background_tasks_changed as a status update, so a task waiting on a job isn't silent, and an overall bound on how long a task can run.

Tested with go test ./harness/claude/... ./harness/runtime/... and make -C go lint. The new process test fails on main with the error above. Not run in a cluster.

🤖 Generated with Claude Code

…ake Claude

When a background task or Monitor wakes Claude after its first result,
Claude Code emits another result per wake-up and exits only once nothing
is left running. The driver treated the first result as terminal, so the
next reply failed the task with "claude emitted activity after its
terminal result" and the process group, background job included, was
killed.

The turn now ends when Claude exits, with the last result as its outcome.
Replies after a result start a new paragraph, and approval requests after
a result take the normal input-required path.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Barrett <thomas@fluidstack.io>
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant