# How Session Statuses Are Managed and Customized in Craft Agents

> Learn how Craft Agents manages and customizes session statuses. Discover how LLM agents modify, persist, and propagate status metadata for UI updates and automations.

- Repository: [Craft Ai Agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss)
- Tags: how-to-guide
- Published: 2026-07-03

---

**Craft Agents treats session statuses as first-class metadata that can be modified by LLM agents, persisted to disk, and propagated through a central event system to update the UI and trigger automations.**

In the `craft-ai-agents/craft-agents-oss` repository, a **session** represents a discrete unit of work that transitions through defined lifecycle states. Understanding how **session statuses** flow from storage through the automation layer to the user interface is essential for building custom agent workflows and extending the platform.

## Architecture of Session Status Management

The status lifecycle follows a consistent path from type definition to persistent storage, through the manager API, and finally to agent tools and UI components.

### Core Data Structures

Session metadata is defined in [`packages/shared/src/sessions/types.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/sessions/types.ts), where the `SessionMetadata` interface holds the optional `sessionStatus` field alongside other metadata like `isFlagged` and `labels`. This type definition serves as the source of truth for what constitutes a valid session state throughout the system.

### Persistent Storage Layer

When a status update occurs, the system writes to disk via [`packages/shared/src/sessions/storage.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/sessions/storage.ts). The `setSessionStatus()` function calls `updateSessionMetadata()` to atomically update the JSONL header on disk, ensuring durability before any in-memory state changes are acknowledged.

### The SessionManager Event Hub

The `SessionManager` class in [`packages/server-core/src/sessions/SessionManager.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/server-core/src/sessions/SessionManager.ts) provides the primary API for status manipulation. When `setSessionStatus(sessionId, status)` is invoked, it updates the in-memory `ManagedSession` instance, persists the change through the storage layer, and emits a `session_status_changed` event. This event acts as the central synchronization mechanism that both the automation system and the Electron UI subscribe to.

## How Agents Modify Session Statuses

Agents do not directly access the filesystem. Instead, they invoke dedicated tools that bridge the gap between the LLM runtime and the core session management API.

### The set-session-status Tool

Located in [`packages/session-tools-core/src/handlers/set-session-status.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/session-tools-core/src/handlers/set-session-status.ts), the `set-session-status` tool exposes status modification to LLM agents. When an agent decides to transition a session from `todo` to `in-progress` or `done`, it generates a JSON-encoded tool call:

```json
{
  "toolName": "mcp__session__setSessionStatus",
  "args": { "sessionId": "abc123", "status": "done" }
}

```

The handler validates the arguments and executes:

```typescript
await ctx.setSessionStatus(args.sessionId, status);

```

This updates the on-disk header and triggers the event emission from `SessionManager`.

### Context Binding for Self-Management

For the tool to function, the execution context must have access to the `setSessionStatus` function. This binding occurs lazily during session initialization through [`packages/shared/src/agent/session-self-management-bindings.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/agent/session-self-management-bindings.ts). The module attaches the status management helpers to the agent's execution context, allowing self-managing agents to update their own session state without external intervention.

## Automation and UI Integration

Status changes are not passive data updates; they act as triggers for downstream workflows and real-time UI updates.

### Reacting to Status Changes

The automation system in [`packages/shared/src/automations/automation-system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/automation-system.ts) listens for the `session_status_changed` event. Developers can define rules that trigger when a session enters a specific state:

```json
{
  "condition": "state",
  "field": "sessionStatus",
  "to": "done",
  "actions": [{ "type": "setLabel", "label": "reviewed" }]
}

```

When the event fires, the condition parser evaluates the transition and applies the specified actions, enabling fully automated post-processing workflows when sessions complete.

### UI Reflection and Event Propagation

The Electron-based UI reflects status changes through a multi-layered approach. In [`apps/electron/src/renderer/playground/registry/session-list.tsx`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/renderer/playground/registry/session-list.tsx), the component renders status badges using the current `session.sessionStatus` value:

```tsx
<span className={`status-badge ${session.sessionStatus}`}>
  {session.sessionStatus}
</span>

```

The event propagation path bridges the main and renderer processes. When `SessionManager` emits `session_status_changed`, the main process forwards it through `window.electronAPI.sessionCommand`, which is consumed in [`apps/electron/src/renderer/contexts/NavigationContext.tsx`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/renderer/contexts/NavigationContext.tsx) to update the React state and re-render the affected components.

## Customizing Session Statuses

Extending the system to support custom statuses requires updates to configuration, validation, and optionally the UI presentation layer.

### Defining New Status Identifiers

Status IDs are not hardcoded but defined in the workspace configuration at [`workspace/statuses.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/workspace/statuses.json). The validation logic in [`packages/shared/src/statuses/validation.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/statuses/validation.ts) ensures that only configured status values are accepted by the API. Adding a new status requires only updating this JSON configuration file; no code changes are necessary unless you need custom validation logic.

### Updating UI Components

To display new statuses with appropriate visual cues, extend the mapping in [`packages/shared/src/statuses/default-icons.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/statuses/default-icons.ts). This file maps status IDs to icon and color definitions. The UI pulls the complete list of allowed statuses via `statusConfigsToSessionStatuses()` (as seen in [`AppShell.tsx`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/AppShell.tsx)), ensuring that custom statuses appear in dropdowns and filter lists automatically once configured.

### Creating Automation Rules

Custom statuses can serve as triggers for automations immediately after configuration. Since the automation system references status values by string in [`packages/shared/src/automations/conditions.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/conditions.ts), rules can target new statuses without code modifications:

```json
{
  "condition": "state",
  "field": "sessionStatus",
  "to": "needs-review",
  "actions": [{ "type": "notify", "channel": "slack" }]
}

```

## Summary

- **Session statuses** in Craft Agents are stored as metadata in `SessionMetadata` and persist through atomic JSONL header updates via `setSessionStatus()`.
- The **SessionManager** coordinates all status changes, emitting a `session_status_changed` event that synchronizes the automation system and UI.
- LLM agents manipulate statuses through the `set-session-status` tool, which is bound to the execution context via **session-self-management-bindings**.
- The **automation system** reacts to status transitions to trigger follow-up actions, while the **Electron UI** reflects changes in real-time through event propagation across process boundaries.
- **Customization** requires only updating [`workspace/statuses.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/workspace/statuses.json) and optionally extending [`default-icons.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/default-icons.ts), with validation handled automatically by the schema in [`validation.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/validation.ts).

## Frequently Asked Questions

### How do I programmatically change a session status from outside the agent?

Use the CLI interface to send a session command that invokes the manager directly:

```typescript
// apps/cli/src/index.ts
await window.electronAPI.sessionCommand(sessionId, {
  type: 'setSessionStatus',
  state: 'in-progress',
});

```

This command routes to `SessionManager.setSessionStatus`, bypassing the need for an active agent run while maintaining the same persistence and event propagation guarantees.

### What happens if an agent tries to set an invalid status?

The request fails at the validation layer. Before the tool executes `ctx.setSessionStatus`, the system validates the status ID against the workspace configuration in [`packages/shared/src/statuses/validation.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/statuses/validation.ts). Invalid statuses are rejected with an error returned to the agent, preventing corruption of the session metadata.

### Can I create automation rules that trigger when a status leaves a specific state rather than enters one?

The current automation system in [`packages/shared/src/automations/conditions.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/conditions.ts) primarily supports targeting the destination state (`to` field). However, because the `session_status_changed` event contains both old and new values, you can implement complex logic by checking the transition pair within custom automation handlers, though the JSON rule format focuses on the target state for simplicity.

### Where is the session status actually stored on disk?

Session statuses are stored in the JSONL header of the session file itself. The `updateSessionMetadata()` function in [`packages/shared/src/sessions/storage.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/sessions/storage.ts) performs an atomic update to this header, ensuring that the status persists even if the process crashes immediately after the change.