# How the OpenMAIC Agent Runtime Handles Sessions: Architecture and Lifecycle

> Discover how the OpenMAIC agent runtime handles sessions, managing user conversations and classroom states through server-side creation, URL routing, and localStorage persistence for isolated contexts.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: architecture
- Published: 2026-09-08

---

**The OpenMAIC agent runtime manages sessions as opaque identifiers that bind user conversations to specific classroom states, coordinating between server-side session creation, URL-based routing, and localStorage persistence to maintain isolated conversational contexts.**

The THU-MAIC/OpenMAIC repository implements a sophisticated **agent runtime session handling** system that treats each session as a unique identifier sandboxing conversation history while maintaining associations with specific course contexts. This architecture enables students to maintain multiple parallel conversations with AI agents, each tied to distinct learning materials, without state bleeding between contexts.

## Core Components of the Session Architecture

### URL Generation and Routing ([`session-urls.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/session-urls.ts))

Located at [`lib/server/agent-runtime/session-urls.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/session-urls.ts), this module generates type-safe URLs for session operations. The `workspaceResumeHref(sessionId)` function encodes session identifiers for safe inclusion in workspace URLs, while `sessionCreateUrl()` points to the `/api/agent/sessions` endpoint. These utilities ensure that session transitions remain bookmarkable and shareable through standard HTTP routes.

### Client-Side Persistence ([`workspace-session-memory.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/workspace-session-memory.ts))

The [`lib/workbench/workspace-session-memory.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/workspace-session-memory.ts) file manages the **last-opened session** in the browser's `localStorage`. Key functions include:

- `rememberWorkspaceSession(id, storage)` — Stores the ID under `LAST_WORKSPACE_SESSION_STORAGE_KEY`
- `readLastWorkspaceSessionId(storage)` — Retrieves the stored identifier
- `forgetWorkspaceSession(id, storage)` — Removes stale entries when sessions are deleted
- `validateRememberedWorkspaceSession(id, loadedIds, storage)` — Validates that remembered IDs still exist among currently loaded sessions

### Pane State Management ([`workspace-panes.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/workspace-panes.ts))

The runtime represents the UI layout through "panes" defined in [`lib/workbench/workspace-panes.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/workspace-panes.ts). Each pane maintains a `sessionId` and `courseId` pair. Functions like `withSession(panes, newSessionId)` and `withCourse(panes, newCourseId)` update specific dimensions while preserving the other, enabling users to switch sessions without losing their current course context. The `workspaceLayout(panes)` function returns `'session'`, `'course'`, or `'both'` to control the visible interface layout.

## The Session Lifecycle

### Creating a New Session

Session creation begins with a POST request to `/api/agent/sessions`. The agent server generates a fresh, opaque `sessionId`, records the owner, and returns the identifier as JSON. This server-side generation guarantees uniqueness while establishing the initial ownership context for the conversation.

### Persisting Session State

After creation, the client persists the session using `rememberWorkspaceSession(newSessionId, localStorage)`. Simultaneously, the application updates the browser URL via `workspaceResumeHref(sessionId)`, encoding the identifier as a query parameter for subsequent page loads.

### Resuming Sessions from URLs

When users navigate to the workspace, [`lib/server/agent-runtime/resume.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/resume.ts) parses the `?session=` query parameter. The [`resume.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/resume.ts) module validates the identifier and reconstructs the agent's conversation context, loading the associated classroom state and history. This URL-driven approach enables deep-linking to specific conversational contexts.

### Switching Between Sessions

Users can switch sessions via the session rail interface. The runtime invokes `withSession(currentPanes, 'new-session-id')` to update the pane state while optionally preserving the `courseId`. This operation updates the URL to reflect the new session without triggering a full page reload, maintaining the existing course context when applicable.

### Cleanup and Validation

When sessions are deleted, `forgetWorkspaceSession` removes the identifier from `localStorage`. The `validateRememberedWorkspaceSession` function prevents stale IDs from being resumed by checking against currently loaded sessions, ensuring that only valid, active sessions can be restored.

## Session Isolation and Ownership

The runtime enforces **session isolation** through predicates like `agentOwnsActiveCourse` and `agentOwnsPaneCourse`. These functions verify that an agent-created course remains editable only within the session that created it. This ownership model prevents cross-session contamination while allowing intentional session-course coupling when a session owns specific educational content.

## Implementation Examples

Creating and navigating to a new session:

```typescript
// Request new session from agent runtime
const response = await fetch('/api/agent/sessions', { method: 'POST' });
const { sessionId } = await response.json();

// Generate resumable URL and navigate
import { workspaceResumeHref } from '@/lib/workbench/workspace-panes';
window.location.href = workspaceResumeHref(sessionId);

```

Persisting to localStorage:

```typescript
import { rememberWorkspaceSession } from '@/lib/workbench/workspace-session-memory';

// Store for future retrieval
rememberWorkspaceSession(sessionId, localStorage);

```

Switching sessions while preserving course context:

```typescript
import { withSession } from '@/lib/workbench/workspace-panes';

// Update session while keeping current course
const updatedPanes = withSession(currentPanes, 'session-42');
// URL becomes: /workspace?session=session-42&course=currentCourseId

```

## Summary

- The OpenMAIC agent runtime uses **opaque session identifiers** to isolate conversational contexts and bind them to specific classroom states.
- **URL-driven state** in [`session-urls.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/session-urls.ts) and [`resume.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/resume.ts) enables deep-linking and shareable conversation contexts through query parameters.
- **localStorage persistence** via [`workspace-session-memory.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/workspace-session-memory.ts) maintains the last-opened session across browser restarts while validating against stale entries.
- **Pane-based architecture** in [`workspace-panes.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/workspace-panes.ts) decouples session and course state, allowing flexible switching between conversations while preserving educational content context.
- **Ownership predicates** enforce that agent-created courses remain editable only within their originating sessions, preventing cross-session contamination.

## Frequently Asked Questions

### How does OpenMAIC store session state between page reloads?

The runtime persists session identifiers in the browser's `localStorage` using the functions in [`lib/workbench/workspace-session-memory.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/workspace-session-memory.ts). Specifically, `rememberWorkspaceSession` stores the ID under `LAST_WORKSPACE_SESSION_STORAGE_KEY`, while [`lib/server/agent-runtime/resume.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/resume.ts) reads the `?session=` query parameter on initialization to restore the full conversation context. This dual approach ensures sessions survive browser restarts while remaining addressable via shareable URLs.

### Can users switch between multiple agent sessions without losing their course progress?

Yes. The [`workspace-panes.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/workspace-panes.ts) module manages `sessionId` and `courseId` as independent dimensions. When calling `withSession(panes, newSessionId)`, the runtime updates only the session identifier while preserving the existing `courseId`. This allows students to switch between different conversational contexts while maintaining their position in course materials and preventing disruption to their learning flow.

### What prevents a session from accessing courses created by other sessions?

The runtime implements ownership predicates `agentOwnsActiveCourse` and `agentOwnsPaneCourse` that verify whether the current session ID matches the creator of the active course. These checks ensure **session isolation**, guaranteeing that agent-generated content remains editable only within the session that instantiated it. This prevents accidental cross-session interference while maintaining strict boundaries between different user conversations.

### Where does the session ID originate in the OpenMAIC architecture?

Session IDs are generated server-side by the agent runtime endpoint at `/api/agent/sessions`. When the client sends a POST request, the backend creates a new database entry, assigns an opaque unique identifier, records the owner, and returns the ID to the client. This server-authoritative approach ensures global uniqueness and establishes the security context for subsequent agent operations.