Skip to content

Sending a message kills a thread's running background tasks when instructions drifted between turns #1217

Description

@sholub-dev

Version: bb 0.36.0 (macOS), claude-code threads

Problem

A thread with a long-running backgrounded command loses it the moment the user sends the next message, whenever the server-composed thread instructions changed since the CLI session started. The task instantly flips to "interrupted" (same second as the message, before the agent replies) and the underlying process is dead.

Instructions drift without any user action: the Memory plugin renders the memory catalog into thread instructions, so any memory write arms the next message to kill all running background tasks. AGENTS.md edits and plugin dynamic instructions do the same.

Steps to reproduce

In the bb app (Memory plugin enabled — it is by default), one claude-code thread, three messages:

  1. Send: "Run sleep 600 as a background command, then reply done."
    The timeline now shows a running background task.
  2. Send: "Save a memory: my favorite color is blue."
    (Any memory write works — this silently changes the instructions bb will send next turn.)
  3. Send: "Is the sleep still running?"

The moment message 3 is sent, the background task flips to interrupted — before the agent starts answering. The process is actually dead: pgrep -f "sleep 600" returns nothing, and a new claude --resume process appears at the same second.

No Memory plugin? Step 2 can be replaced by adding any line to ~/.bb/AGENTS.md.

Without step 2, message 3 leaves the task running — that is the defect boundary: the kill only happens when instructions changed since the session started.

Root cause

  1. The server recomposes thread instructions on every turn submission.
  2. On the next turn, reconfigureThreadIfNeeded (packages/agent-runtime/src/runtime.ts) sees the changed instructions and issues thread/resume.
  3. The claude-code adapter settles every open background task as interrupted on any accepted resume, and the bridge replaces the live CLI session (its session construction config changed) — killing the still-running background processes.

Observed in production event data: a watch task ran 13:10–18:41; the user's message "aren't you done yet?" produced client/turn/requested and the task's item/backgroundTask/completed (status interrupted) with identical timestamps, and a new claude --resume <session> process appeared at that second.

Expected

Delivering a user message must not destroy running background work in order to apply an instruction refresh. The refresh can wait until the thread has no open background tasks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions