Session Lifecycle State Machine Transitions in Background-Agents: Complete Technical Guide

Background-agents implements a finite-state machine for session management where SessionState transitions between active, archived, and terminal states through specific HTTP API endpoints, with automatic reactivation when new prompts are received.

The ColeMurray/background-agents repository enforces a rigorous session lifecycle state machine to ensure consistent session behavior across the platform. The primary state is stored in the status field of SessionState (type SessionStatus), defined in packages/shared/src/types/sessions.ts. This state machine governs how sessions move between operational states based on user actions and system events.

Core State Transitions

The control-plane HTTP API exercises three fundamental transitions that modify the session table’s status column. These transitions are enforced by the Durable Object implementation in packages/control-plane/src/session/durable-object.ts.

Archiving Active Sessions

Sessions transition from active to archived via an authorized API call. Only the participant who created the session may trigger this transition.

When a POST /internal/archive request is received, the Durable Object updates the session status to "archived", preventing new prompts from being processed. According to the integration tests in packages/control-plane/test/integration/session-lifecycle.test.ts, this operation immediately halts prompt processing for the session【/cache/repos/github.com/ColeMurray/background-agents/main/packages/control-plane/test/integration/session-lifecycle.test.ts#L36-L54】.

Restoring Archived Sessions

Archived sessions can be restored to active status through explicit unarchiving. The transition from archived to active requires a POST /internal/unarchive request from an authorized participant.

The test suite validates this behavior by first archiving a session, then posting to /internal/unarchive, and verifying the status returns to "active"【/cache/repos/github.com/ColeMurray/background-agents/main/packages/control-plane/test/integration/session-lifecycle.test.ts#L69-L95】. This ensures sessions can be reused without creating new instances.

Automatic Reopening via Prompts

Terminal sessions automatically reactivate when receiving new prompts. The transition from any terminal state—completed, failed, cancelled, or archived—to active occurs when any participant sends a POST /internal/prompt request.

The parameterized test "reopens … session back to active" forces sessions into each terminal status and confirms that new prompts reset the status to "active"【/cache/repos/github.com/ColeMurray/background-agents/main/packages/control-plane/test/integration/session-lifecycle.test.ts#L98-L122】. This enables a seamless "continue later" workflow where users can resume conversations regardless of previous terminal states.

Implementation Architecture

State Definitions

The SessionStatus enum is defined in packages/shared/src/types/statuses.ts, while SessionState is declared in packages/shared/src/types/sessions.ts with the status: SessionStatus field【/cache/repos/github.com/ColeMurray/background-agents/main/packages/shared/src/types/sessions.ts#L89-L104】. Valid statuses include:

  • active - Currently processing prompts
  • archived - Suspended but restorable
  • completed - Finished successfully
  • failed - Terminated with errors
  • cancelled - Aborted by user or system

Control-Plane Enforcement

The Durable Object in packages/control-plane/src/session/durable-object.ts serves as the state machine authority. It validates participant authentication before permitting state changes and persists updates to the session table’s status column. This centralized enforcement ensures that archived sessions cannot accept new prompts until explicitly unarchived, while terminal states can be revived through prompt activity.

Practical Code Examples

// Archive a session (requires creator authorization)
await fetch('http://internal/internal/archive', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ userId: 'user-1' })
});
// session.status becomes "archived"
// Unarchive to restore active status
await fetch('http://internal/internal/unarchive', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ userId: 'user-1' })
});
// session.status becomes "active"
// Re-open any terminal session with a new prompt
await fetch('http://internal/internal/prompt', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    content: 'Resume conversation',
    authorId: 'user-1',
    source: 'web'
  })
});
// session.status resets to "active" regardless of prior terminal state

Summary

Frequently Asked Questions

What triggers a session to transition from archived back to active?

A session transitions from archived to active when an authorized participant sends a POST /internal/unarchive request. Additionally, any new prompt sent to an archived session via POST /internal/prompt will automatically reactivate it, as the system treats archived as a terminal state that can be revived through user activity.

Where is the session status stored in the codebase?

The session status is stored in the status field of the SessionState interface, defined in packages/shared/src/types/sessions.ts as type SessionStatus【/cache/repos/github.com/ColeMurray/background-agents/main/packages/shared/src/types/sessions.ts#L89-L104】. The actual database persistence occurs in the Durable Object implementation at packages/control-plane/src/session/durable-object.ts, which updates the session table’s status column.

Can archived sessions receive new prompts without unarchiving?

No. Archived sessions cannot receive new prompts until they are explicitly unarchived or until a new prompt is sent, which automatically triggers the reopening transition. The state machine enforces that archived sessions block prompt processing until the status changes back to active, either through the unarchive endpoint or the automatic reactivation mechanism.

What are the valid terminal states that can be revived by new prompts?

The valid terminal states that automatically transition to active upon receiving a new prompt are completed, failed, cancelled, and archived. The integration tests in packages/control-plane/test/integration/session-lifecycle.test.ts verify that each of these states can be revived when any participant sends a POST /internal/prompt request【/cache/repos/github.com/ColeMurray/background-agents/main/packages/control-plane/test/integration/session-lifecycle.test.ts#L98-L122】.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →