# How the Multi-Session Inbox and Archive Workflow Works in Craft Agents

> Discover how the multi-session inbox and archive workflow in Craft Agents separates active conversations from storage using session status and an archive flag. Streamline your agent management.

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

---

**The multi-session inbox and archive workflow in Craft Agents uses a dual-filter system combining `sessionStatus` categories and an `isArchived` boolean flag to separate active conversations from long-term storage.**

Craft Agents OSS organizes every conversation into persistent session folders under a workspace directory. The workflow distinguishes between active work in the **Inbox** and long-term storage in the **Archive** using metadata flags stored in each session's header, enabling users to manage hundreds of conversations without clutter.

## Session Storage Architecture

Each conversation ("session") resides in a dedicated folder at `{workspaceRootPath}/sessions/{id}`. This folder contains a `session.jsonl` file holding the transcript and a metadata header (see **SessionStorage**). The system tracks two critical pieces of metadata to power the inbox and archive views:

- **`sessionStatus`** (string): A user-controlled status ID (e.g., `todo`, `done`) defined in [`packages/shared/src/statuses/types.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/statuses/types.ts)
- **`isArchived`** (boolean): An explicit flag that moves a session to the Archive view, accompanied by an `archivedAt` timestamp

The status configuration defines each status as either **open** or **closed**, and the helper `getStatusCategory` maps status IDs to these categories.

## The Dual-Filter System

The UI distinguishes between Inbox and Archive through two orthogonal filters:

**Status Category Filtering**
The `sessionStatus` field determines whether a session is considered "active work" based on the workspace-wide status configuration. Statuses like `todo` or `in-progress` map to the `open` category, while `done` maps to `closed`.

**Archive Flag Filtering**
The `isArchived` boolean in [`packages/shared/src/sessions/types.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/sessions/types.ts) (lines 80-82) explicitly moves sessions out of the active pool. When `true`, the session appears only in the Archive view regardless of its status category.

## How Inbox and Archive Filtering Works

The core filtering functions live in [`packages/shared/src/sessions/storage.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/sessions/storage.ts):

```typescript
// Inbox – open category, excludes archived
export function listInboxSessions(workspaceRootPath: string): SessionMetadata[] {
  return listActiveSessions(workspaceRootPath).filter(s => {
    const category = getStatusCategory(workspaceRootPath, s.sessionStatus || 'todo');
    return category === 'open';
  });
}

// Archived – explicit flag
export function listArchivedSessions(workspaceRootPath: string): SessionMetadata[] {
  return listSessions(workspaceRootPath).filter(s => s.isArchived === true);
}

```

The workflow follows this hierarchy:

1. **`listActiveSessions`** filters out any session where `isArchived` is true (lines 60-63 in [`storage.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/storage.ts))
2. **`listInboxSessions`** further filters active sessions by the `open` category using `getStatusCategory` (lines 44-48)
3. **`listArchivedSessions`** retrieves only sessions where `isArchived === true`

## Archiving and Unarchiving Operations

When a user clicks "Archive" in the UI, the event processor handler in [`apps/electron/src/renderer/event-processor/handlers/session.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/renderer/event-processor/handlers/session.ts) updates the session header:

```typescript
// Line 717 – Archiving a session
session: { ...session, isArchived: true, archivedAt: Date.now() },

```

To restore a session, the handler clears the flag at line 734:

```typescript
// Line 734 – Unarchiving a session
session: { ...session, isArchived: false, archivedAt: undefined },

```

Because these flags are stored in the session header (`SessionHeader`), the archival state persists across application restarts. The UI component [`SessionList.tsx`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/SessionList.tsx) reads these lists via `listInboxSessions` and `listArchivedSessions` to render the appropriate views.

## Practical Implementation

Here is how to interact with the inbox and archive workflow programmatically:

```typescript
import { listInboxSessions, listArchivedSessions, setSessionStatus } from '@/shared/sessions';

// 1️⃣ Get the inbox for the current workspace
const inbox = listInboxSessions('/my/workspace');
console.log('Inbox sessions:', inbox.map(s => s.id));

// 2️⃣ Archive a session (e.g., user clicks “Archive”)
function archiveSession(workspace: string, sessionId: string) {
  // Load the session header, modify the flag and write back
  const header = readSessionHeader(workspace, sessionId);
  header.isArchived = true;
  header.archivedAt = Date.now();
  writeSessionHeader(workspace, sessionId, header);
}

// 3️⃣ Move a session to a closed status (e.g., “done”)
async function closeSession(workspace: string, sessionId: string) {
  await setSessionStatus(workspace, sessionId, 'done'); // “done” is a closed status
}

// 4️⃣ List all archived sessions
const archived = listArchivedSessions('/my/workspace');
console.log('Archived:', archived.map(s => s.id));

```

## Summary

- Craft Agents stores sessions in `{workspaceRootPath}/sessions/{id}` with metadata headers containing `sessionStatus` and `isArchived` flags
- The **Inbox** displays active sessions where `isArchived` is false and the status category is `open`
- The **Archive** displays only sessions where `isArchived` is true, regardless of status
- Archiving sets `isArchived: true` and records `archivedAt`, while unarchiving clears both fields
- Status categories (open/closed) provide workflow organization within the active pool, while the archive flag provides long-term storage separation

## Frequently Asked Questions

### What determines if a session appears in the Inbox?

A session appears in the Inbox only if it is not archived (`isArchived !== true`) and its `sessionStatus` maps to the `open` category via the `getStatusCategory` function. This means sessions marked with statuses like `todo` or `in-progress` appear in the Inbox, while sessions with `closed` statuses or the `isArchived` flag set to true are excluded.

### How does archiving differ from changing session status?

Changing a session status to a closed category (e.g., `done`) removes it from the Inbox but keeps it in the active sessions list, meaning it still appears in general session listings. Archiving sets the `isArchived` boolean to true, which removes the session from both the Inbox and active lists entirely, placing it exclusively in the Archive view with a recorded `archivedAt` timestamp.

### Where is the archive state persisted?

The archive state is stored in the session's metadata header within the workspace directory structure. Specifically, the `isArchived` boolean and `archivedAt` timestamp are written to the session header file in `{workspaceRootPath}/sessions/{id}`, ensuring the state survives application restarts and workspace migrations.

### Can archived sessions be restored to the Inbox?

Yes, archived sessions can be restored by clearing the `isArchived` flag. When the event processor handles an unarchive action (line 734 in [`apps/electron/src/renderer/event-processor/handlers/session.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/renderer/event-processor/handlers/session.ts)), it sets `isArchived: false` and `archivedAt: undefined`. The session then reappears in the Inbox if its status category is still `open`, or in the active sessions list if the status is `closed`.