How OpenMAIC Handles Lease Coordination for Session Claims in the Agent Runtime

OpenMAIC uses a token-based lease mechanism stored in localStorage and an in-memory map to ensure only one active agent owns a workspace session at any time, with lease validation before every operation and graceful interruption handling when leases are contested.

The lease coordination system in OpenMAIC's agent runtime prevents race conditions and guarantees exclusive access to workspace sessions. When multiple browser tabs or agent instances compete for the same session, this mechanism ensures deterministic ownership and clean handoffs. The implementation centers on lib/workbench/workspace-session-memory.ts, which provides the core primitives for claiming, validating, and releasing session leases.

Lease Acquisition: Claiming a Session

When an agent initiates a session, it must first acquire a lease from the shared lease manager. This process generates a unique token that serves as proof of ownership for the duration of the session.

The acquisition logic in lib/workbench/workspace-session-memory.ts handles three concurrent storage targets:

  • A UUID-based lease token created via crypto.randomUUID()
  • localStorage persistence using the LAST_WORKSPACE_SESSION_STORAGE_KEY constant for survival across reloads
  • An in-memory Map (activeLeases) for fast synchronous validation
// lib/workbench/workspace-session-memory.ts
export async function claimSession(
  sessionId: string,
  storage: Storage,
): Promise<void> {
  // Generate a unique lease token
  const lease = crypto.randomUUID();
  // Store token in localStorage for persistence
  storage.setItem(LAST_WORKSPACE_SESSION_STORAGE_KEY, lease);
  // Keep token in the in‑memory map for fast checks
  activeLeases.set(sessionId, lease);
}

The dual-storage approach balances durability (localStorage) with performance (in-memory lookups). This allows sub-millisecond validation checks during critical path operations while maintaining lease state through browser restarts.

Lease Validation: Enforcing Exclusive Access

Before executing any session-specific operation, the runtime validates that its held lease matches the stored token. This check prevents stale agents from performing destructive operations on sessions they no longer own.

The validation function compares the localStorage lease against the in-memory entry:

// lib/workbench/workspace-session-memory.ts
function isLeaseValid(sessionId: string, storage: Storage): boolean {
  const storedLease = storage.getItem(LAST_WORKSPACE_SESSION_STORAGE_KEY);
  return storedLease === activeLeases.get(sessionId);
}

// Example usage in an agent action
if (!isLeaseValid(currentSessionId, localStorage)) {
  emit('session_interrupted', { reason: 'lease lost' });
  return; // abort the action
}

Validation failures trigger the session_interrupted event with reason "lease lost". This event-driven architecture decouples lease detection from response handling, allowing different runtime components to react appropriately.

Lease Release: Graceful Session Termination

When an agent completes its work or loses focus, it explicitly releases its lease. This cleanup is mandatory for proper resource management and prevents lease leaks that would block future session claims.

The releaseSession function in lib/workbench/workspace-session-memory.ts performs atomic cleanup:

// lib/workbench/workspace-session-memory.ts
export function releaseSession(sessionId: string, storage: Storage): void {
  activeLeases.delete(sessionId);
  storage.removeItem(LAST_WORKSPACE_SESSION_STORAGE_KEY);
}

Lease release occurs in three scenarios:

  • User-initiated session switch — the agent voluntarily surrenders the current session
  • Page unload event — the browser invokes cleanup handlers before navigation
  • Lease loss detection — validation failure prompts defensive release to avoid conflicts

Handling Interruptions: Recovery from Lease Contention

When lease contention occurs—typically from multiple tabs attempting to claim the same session—the runtime broadcasts session_interrupted events. Components subscribe to these events and execute graceful degradation logic.

The UI layer in components/workbench/WorkspaceShell.tsx demonstrates this pattern:

// components/workbench/WorkspaceShell.tsx
useEffect(() => {
  const handler = ({ reason }: { reason: string }) => {
    if (reason === 'lease lost') {
      // Gracefully close the current session UI
      closeCurrentSession();
    }
  };
  eventBus.on('session_interrupted', handler);
  return () => eventBus.off('session_interrupted', handler);
}, []);

The event bus architecture enables multiple listeners to react to lease changes without tight coupling between the lease manager and individual components.

Persistence and Recovery Across Reloads

The lease system supports session recovery after browser refreshes. When the runtime initializes, it checks localStorage for existing lease tokens via rememberWorkspaceSession and validateRememberedWorkspaceSession.

This recovery flow handles two edge cases:

  • Valid token — the runtime seamlessly reclaims the session if the lease hasn't expired or been claimed by another agent
  • Stale token — validation fails against the current session state, triggering lease cleanup and preventing phantom session ownership

The test suite in tests/workbench/workspace-session-memory.test.ts verifies both persistence scenarios and ensures lease integrity across page lifecycle events.

Key Source Files and Responsibilities

File Responsibility
lib/workbench/workspace-session-memory.ts Core lease implementation: claimSession, releaseSession, isLeaseValid, rememberWorkspaceSession
tests/workbench/session-fold.test.ts Integration tests for session_interrupted event with "lease lost" reason
tests/workbench/workspace-session-memory.test.ts Unit tests for lease persistence, validation, and cleanup
components/workbench/WorkspaceShell.tsx UI event handler for lease-loss notifications
components/workbench/WorkspaceRail.tsx Session navigation with lease-aware activation logic

Summary

  • Lease tokens stored in localStorage and in-memory Maps provide durable, fast session ownership verification
  • Validation before operations ensures only the current lease holder can mutate session state
  • Event-driven interruption handling via session_interrupted enables graceful recovery from contention
  • Explicit release on session end prevents resource leaks and blocks stale claims
  • Cross-reload persistence allows seamless session recovery with automatic stale lease detection

Frequently Asked Questions

What happens when two tabs try to claim the same OpenMAIC session?

The second tab's claimSession call generates a new lease token that overwrites the localStorage entry. When the first tab next validates its lease via isLeaseValid(), the token mismatch triggers a session_interrupted event with reason "lease lost". The first tab's UI components respond by closing the session view, leaving only the second tab with active ownership.

How does OpenMAIC detect and recover from stale leases after a browser crash?

On initialization, rememberWorkspaceSession retrieves any existing token from localStorage and calls validateRememberedWorkspaceSession. This function checks the token against the current session state on the server or in shared memory. Invalid or expired tokens are cleared automatically, allowing the new agent instance to claim a fresh lease without manual intervention.

Why does OpenMAIC use both localStorage and an in-memory Map for lease storage?

The in-memory Map provides O(1) lookup performance for high-frequency validation checks during agent operations. localStorage provides durability across page reloads and browser tabs, ensuring lease state survives crashes and navigation. This dual-layer design optimizes for both speed and reliability without sacrificing correctness.

Can the lease coordination mechanism handle server-side session validation?

The current implementation focuses on client-side coordination between browser tabs and agent instances. The storage parameter in claimSession and validateRememberedWorkspaceSession is injectable, allowing future extensions to wrap server-validated storage backends. The core lease logic remains agnostic to the storage implementation details.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →