How the Agent Workbench Manages Durable Sessions Across Server Restarts
The OpenMAIC Agent Workbench persists the last-opened session ID in the browser’s localStorage and validates it against the server’s live session catalogue on startup, enabling seamless workspace resumption even after server restarts or browser closures.
The THU-MAIC/OpenMAIC repository implements a robust durability mechanism that decouples session continuity from server runtime state. Rather than relying on ephemeral server-side memory, the Workbench stores a reference to the active workspace session client-side, then verifies its validity against the backend’s current session list. This approach ensures users can close their browser—or experience a full server restart—and still return to their exact workspace context.
Client-Side Persistence Architecture
The durability strategy centers on the localStorage API, which survives browser restarts and server outages. When a user opens a workspace, the Workbench writes the current session identifier to a dedicated storage key defined as LAST_WORKSPACE_SESSION_STORAGE_KEY. This key stores the ID in URL-encoded format, ensuring safe string handling across page reloads.
Because the session token resides in the browser rather than server memory, the Workbench’s durability is independent of backend process lifecycles. The server merely provides a catalogue of currently active sessions, and the client-side logic in lib/workbench/workspace-session-memory.ts determines whether the remembered session can safely resume.
The Session Recovery Workflow
Resuming a session follows a strict four-phase pipeline implemented in workspace-session-memory.ts. Each phase is exposed as a discrete utility function to ensure testability and clear separation of concerns.
Step 1: Persisting the Active Session
When a workspace gains focus, the Workbench calls rememberWorkspaceSession(sessionId, storage) to record the identifier. This function writes the encoded session ID to localStorage under the dedicated workspace key, establishing the durability anchor.
import { rememberWorkspaceSession } from '@/lib/workbench/workspace-session-memory';
// Store the current session when the workspace opens
rememberWorkspaceSession('session-42', window.localStorage);
Step 2: Reading the Stored Session
On every page load—including those following a server restart—the Workbench invokes readLastWorkspaceSessionId(storage) to retrieve the previously stored identifier. This function returns the decoded session ID or null if no valid entry exists.
import { readLastWorkspaceSessionId } from '@/lib/workbench/workspace-session-memory';
// Retrieve the last-opened session on application startup
const lastId = readLastWorkspaceSessionId(window.localStorage);
// → 'session-42' or null if the storage is empty
Step 3: Validating Against Server State
The critical durability check occurs in validateRememberedWorkspaceSession(storedId, loadedSessionIds, storage). This function compares the client-side memory against the array of live session IDs fetched from the backend. If the stored ID is absent from the server’s list—indicating the session expired or was deleted during the outage—the function purges the stale entry from localStorage and returns null.
import { validateRememberedWorkspaceSession } from '@/lib/workbench/workspace-session-memory';
const liveIds = ['session-42', 'session-99']; // Fetched from the backend API
const validId = validateRememberedWorkspaceSession(
lastId,
liveIds,
window.localStorage
);
// → 'session-42' if valid, or null if the session no longer exists
If validation fails, the Workbench triggers a fallback mechanism defined in lib/workbench/workspace-rail-tab.ts, redirecting the user to the default “sessions” rail rather than attempting to resurrect a dead workspace.
Step 4: Building the Resume URL
Once validation succeeds, workspaceResumeHref(sessionId) constructs the navigation target. This function returns a formatted URL string pointing to /workspace?session=<encodedId>, allowing the application router to restore the exact workspace context.
import { workspaceResumeHref } from '@/lib/workbench/workspace-session-memory';
const href = workspaceResumeHref(validId!);
// → '/workspace?session=session-42'
Implementation Details in workspace-session-memory.ts
The core logic resides in lib/workbench/workspace-session-memory.ts, which exports the four primary functions governing session lifecycle memory. The module handles URL encoding automatically to prevent injection issues and storage corruption, ensuring that session identifiers containing special characters survive the round-trip through localStorage.
The companion test suite in tests/workbench/workspace-session-memory.test.ts provides comprehensive coverage of the durability logic, including edge cases such as malformed storage entries, empty server catalogues, and concurrent session overwrites. These tests verify that the Workbench correctly forgets invalid sessions and maintains storage hygiene.
Handling Stale Sessions and Fallback Behavior
When validateRememberedWorkspaceSession detects a mismatch between the stored ID and the server’s live session list, it immediately clears the obsolete entry from localStorage to prevent infinite retry loops. The UI layer in lib/workbench/workspace-rail-tab.ts detects this null state and renders the default sessions list, allowing users to select a valid workspace or create a new one. This validation step is crucial for maintaining consistency after server restarts, which wipe volatile session state while potentially preserving the session catalogue in persistent storage.
Summary
- Client-side storage: The Workbench uses
localStoragewithLAST_WORKSPACE_SESSION_STORAGE_KEYto survive server restarts. - Validation layer: The
validateRememberedWorkspaceSessionfunction inworkspace-session-memory.tsfilters stale IDs against the server’s live session list. - Automatic cleanup: Invalid sessions are purged from storage immediately upon detection, preventing dead links.
- Graceful fallback: When validation fails,
workspace-rail-tab.tsroutes users to the default sessions rail. - URL generation: Valid sessions resume via
workspaceResumeHref, which constructs/workspace?session=<id>navigation targets.
Frequently Asked Questions
Where is the session ID physically stored?
The session ID is stored in the browser’s localStorage under the key LAST_WORKSPACE_SESSION_STORAGE_KEY. This client-side storage persists across browser restarts and server outages, providing the durability mechanism that allows the Workbench to remember your last workspace even after the backend process restarts.
What happens if my session was deleted while the server was restarting?
The validateRememberedWorkspaceSession function checks the stored ID against the list of active sessions returned by the server. If the ID is not found in the live catalogue, the function removes the stale entry from localStorage and returns null, causing the Workbench to display the default “sessions” rail instead of attempting to open a non-existent workspace.
Does this mechanism work across different browsers or devices?
No. Because the implementation relies on localStorage, which is scoped to the specific browser origin and device, a session remembered on one browser will not automatically appear on another. The durability is per-browser, not per-user account, ensuring privacy but limiting cross-device continuity.
How does the Workbench handle the session list after a server restart?
The Workbench fetches the current session catalogue from the backend during initialization and passes it to validateRememberedWorkspaceSession as the loadedSessionIds parameter. The server restart may change which sessions are available, but the client-side validation logic ensures only currently valid sessions are resumed, while expired ones are silently discarded.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →