What Is Leased Execution in the OpenMAIC Agent Runtime?

Leased execution is a fault-tolerant coordination mechanism that uses PostgreSQL-backed leases to ensure exactly-once execution of long-running agent conversations across distributed worker processes.

OpenMAIC implements a robust leased execution model to manage durable, stateful agent sessions across multiple worker processes. This architecture treats PostgreSQL as the source of truth for coordination, enabling safe concurrent execution and automatic recovery from crashes. Understanding how leased execution works is essential for deploying resilient agent runtimes at scale.

The Lease-Coordinated Execution Model

At the core of OpenMAIC's runtime is a state machine that assumes PostgreSQL is the source of truth for all coordination concerns. According to the source code comments in lib/server/agent-runtime/runner.ts, the system manages claims, lease generations, event ordering, cancellation, and recovery through database-backed leases. A critical constraint ensures that no client connection lives longer than a single lease, preventing orphaned sessions and resource leaks.

This design allows multiple worker processes to safely pick up and continue interrupted sessions without manual intervention.

The Lease Lifecycle in OpenMAIC

The leased execution flow follows a strict lifecycle from acquisition to release, ensuring exclusive access to session state throughout execution.

Claiming a Session

Workers initiate execution by calling store.claimNextSession(workerId, pid, options), defined in packages/@openmaic/storage/src/agent-session/types.ts (lines 92-97). This method atomically scans for eligible sessions and acquires an exclusive lease, returning a ClaimedAgentSession object containing the session id, attempt number, and lease metadata.

If no sessions are available, the method returns null, allowing workers to poll or idle until work arrives.

Runtime Verification and Validation

During execution, the runner validates lease ownership before every write operation. The leaseMatches(session, WORKER_ID, attempt) helper function in runner.ts (lines 78-84) verifies that the current worker still holds the valid lease. If another worker has claimed the session due to TTL expiration or explicit takeover, the lease check fails and execution aborts immediately.

Heartbeat Management and TTL

While processing a session, the worker must periodically call store.heartbeat(sessionId, WORKER_ID) to maintain the lease. The heartbeat interval is controlled by config.heartbeatIntervalMs, defined in lib/server/agent-runtime/agent-runtime-config.ts. If a worker crashes or becomes unresponsive, the lease TTL (configured via leaseTtlMs) expires automatically, allowing other workers to claim and recover the session.

Graceful Lease Release

Upon successful completion, the runner explicitly calls store.releaseLease(sessionId, WORKER_ID) to free the session for future processing. As implemented in runner.ts (lines 1756-1761), this operation is idempotent—if the lease was already lost due to timeout, the call becomes a no-op rather than throwing an error.

Fault Tolerance and Lease Loss Detection

The system detects failed workers through AgentSessionLeaseLostError exceptions. The isLeaseLostError utility in runner.ts (lines 17-25) identifies these specific PostgreSQL errors and triggers the abort controller, converting the session into a lease-lost state. This mechanism prevents split-brain scenarios where multiple workers might attempt to mutate the same session simultaneously.

The lease also carries an attempt counter that increments only when a worker takes over a stale lease from a crashed predecessor, as documented in types.ts (lines 86-90). Clean releases do not increment the counter, preventing unnecessary retry exhaustion when workers shut down normally.

Implementation in the OpenMAIC Source Code

The following TypeScript example demonstrates the complete leased execution pattern as implemented in the OpenMAIC runtime:

// 1️⃣ Claim a session (usually done by a dedicated "worker" process)
const store = await getAgentSessionStore();
const claim = await store.claimNextSession(
  WORKER_ID,               // e.g. `${randomUUID().slice(0,8)}:${process.pid}`
  process.pid,
  { maxAttempts: 5, leaseTtlMs: 30_000 }
);
if (!claim) {
  console.log('No session ready for this worker');
  return;
}

// 2️⃣ Run the session – `runSession` contains the lease‑loss checks
await runSession({ running: new Map() }, claim);

// 3️⃣ Inside `runSession` a typical write looks like:
await store.appendRunEvent(
  sessionId,
  WORKER_ID,
  { ts: Date.now(), attempt, type: 'message', data: /* event data */ }
);
// The helper `enqueue` in `runner.ts` will call `writeRequiredSessionEntry`
// which checks the lease and aborts if it has been stolen.

// 4️⃣ Heartbeat (kept alive while the loop runs)
setInterval(() => store.heartbeat(sessionId, WORKER_ID), config.heartbeatIntervalMs);

// 5️⃣ Graceful release after the session finishes
await store.releaseLease(sessionId, WORKER_ID);

Key implementation details include the writeRequiredSessionEntry method (used by the enqueue helper) which catches AgentSessionLeaseLostError and sets the leaseLost flag, and the atomic transaction boundary that ensures lease checks and state mutations occur together.

Key Files in the Leased Execution Architecture

Understanding the following files is essential for working with OpenMAIC's leased execution:

Summary

  • Leased execution in OpenMAIC uses PostgreSQL as the source of truth to coordinate distributed worker processes.
  • Workers acquire exclusive access through claimNextSession, which returns lease metadata including an attempt counter.
  • Runtime safety is enforced through leaseMatches validation before every write operation.
  • Heartbeats maintain lease viability; TTL expiration allows automatic recovery by other workers.
  • The isLeaseLostError mechanism safely handles crashes and prevents duplicate execution.

Frequently Asked Questions

What happens when a worker crashes during session execution?

If a worker process crashes, its heartbeat calls cease. Once the leaseTtlMs duration expires in PostgreSQL, the lease becomes available for other workers. A new worker can then call claimNextSession to take over the session, incrementing the attempt counter to track recovery events. The new worker resumes processing from the last committed state, ensuring no events are lost or duplicated.

How does OpenMAIC ensure exactly-once execution of agent events?

Exactly-once semantics are guaranteed by validating the lease inside database transactions. Every write operation uses writeRequiredSessionEntry, which checks lease ownership via leaseMatches before appending events. If the lease has been transferred to another worker, the transaction aborts with AgentSessionLeaseLostError, preventing the stale worker from mutating session state.

What is the purpose of the attempt counter in the lease metadata?

The attempt counter, defined in types.ts (lines 86-90), tracks how many times a session has been recovered from a failed worker. It increments only when claimNextSession takes over a stale lease, not during graceful releases. This counter enables the maxAttempts configuration option, which prevents infinite recovery loops when a session consistently causes worker crashes.

Can multiple workers process the same agent session simultaneously?

No. The leased execution model enforces mutual exclusion at the database level. When a worker claims a session via claimNextSession, it acquires an exclusive lease that other workers cannot violate. The leaseMatches check in runner.ts (lines 78-84) ensures that even if a worker temporarily loses database connectivity, it cannot write to the session after another worker has claimed it.

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 →