Resumed subagent loses completed status after app-server restart

Open 💬 3 comments Opened Jul 19, 2026 by harjotgill

Summary

When a persisted multi-agent v1 thread tree is resumed after the thread manager or app-server process restarts, descendant threads are reloaded from their rollouts but their in-memory AgentStatus starts at PendingInit.

A completed child therefore loses its persisted Completed(Some(message)) status. A subsequent wait_agent does not return the child's final reply and can time out even though the child completed before the restart.

Reproduction

  1. Start a root thread with SQLite persistence enabled.
  2. Spawn a v1 child agent.
  3. Let the child complete with a final message and flush its rollout.
  4. Shut down the thread manager/app-server cleanly.
  5. Create a new manager over the same state and resume the root rollout.
  6. Read or subscribe to the resumed child's status.

Expected: Completed(Some(final_message)).

Actual: PendingInit (or a wait blocks until timeout).

The child rollout may end with ShutdownComplete; that event represents the prior in-memory session lifecycle and should not erase the preceding turn outcome.

An unfinished persisted TurnStarted should resume as Interrupted, since that turn cannot still be running in a new process.

Proposed fix

Reconstruct the initial status for InitialHistory::Resumed from the latest meaningful status-bearing rollout event, ignoring ShutdownComplete, and convert a trailing Running state to Interrupted. Add restart coverage that asserts descendant final messages survive shutdown/resume.

View original on GitHub ↗

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