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

> Understand background agent session lifecycle state machine transitions. Explore active, archived, and terminal states and automatic reactivation with this technical guide.

- Repository: [Cole Murray/background-agents](https://github.com/ColeMurray/background-agents)
- Tags: deep-dive
- Published: 2026-07-13

---

**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`](https://github.com/ColeMurray/background-agents/blob/main/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`](https://github.com/ColeMurray/background-agents/blob/main/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`](https://github.com/ColeMurray/background-agents/blob/main/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`](https://github.com/ColeMurray/background-agents/blob/main/packages/shared/src/types/statuses.ts), while `SessionState` is declared in [`packages/shared/src/types/sessions.ts`](https://github.com/ColeMurray/background-agents/blob/main/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`](https://github.com/ColeMurray/background-agents/blob/main/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

```typescript
// 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"

```

```typescript
// 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"

```

```typescript
// 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

- **Active** sessions transition to **archived** via `POST /internal/archive`, stopping prompt processing until explicitly restored.
- **Archived** sessions return to **active** via `POST /internal/unarchive`, requiring participant authorization.
- **Terminal states** (completed, failed, cancelled, archived) automatically revert to **active** when receiving new prompts via `POST /internal/prompt`.
- The state machine is enforced by the Durable Object in [`packages/control-plane/src/session/durable-object.ts`](https://github.com/ColeMurray/background-agents/blob/main/packages/control-plane/src/session/durable-object.ts) and validated by integration tests in [`packages/control-plane/test/integration/session-lifecycle.test.ts`](https://github.com/ColeMurray/background-agents/blob/main/packages/control-plane/test/integration/session-lifecycle.test.ts).
- State definitions reside in [`packages/shared/src/types/sessions.ts`](https://github.com/ColeMurray/background-agents/blob/main/packages/shared/src/types/sessions.ts) and [`packages/shared/src/types/statuses.ts`](https://github.com/ColeMurray/background-agents/blob/main/packages/shared/src/types/statuses.ts).

## 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`](https://github.com/ColeMurray/background-agents/blob/main/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`](https://github.com/ColeMurray/background-agents/blob/main/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`](https://github.com/ColeMurray/background-agents/blob/main/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】.