How AgentRun Ensures Execution Durability in Apache Maka

AgentRun ensures execution durability by validating required persistence stores at construction, staging events with tiered durability levels during runTurn(), and enforcing a terminal durability barrier through finalize() to guarantee canonical persistence.

Apache Maka provides a deterministic runtime for autonomous agents through the AgentRun class, which orchestrates goal execution while ensuring that every state transition meets strict durability guarantees. The durability system operates through a coordinated trio of configuration interfaces, storage abstractions, and execution lifecycle methods defined in packages/runtime/src/agent-run.ts and its dependencies.

Durability Configuration in AgentRunInput

The AgentRunInput interface in packages/runtime/src/agent-run-input.ts defines the contract for durability requirements. It exposes a durability property that accepts "best_effort" or "required", along with optional references to runtimeEventStore and agentRunStore.

When durability is set to "required", the runtime mandates the presence of both stores. The constructor in packages/runtime/src/agent-run.ts enforces this by throwing an error if the stores are missing, preventing accidental volatile execution of critical workflows.

Store Requirements for Required Durability

The validation logic in the AgentRun constructor explicitly checks:

if (this.input.durability === "required" && (!this.input.runtimeEventStore || !this.input.agentRunStore)) {
  throw new Error("Required AgentRun durability needs AgentRunStore and RuntimeEventStore");
}

This ensures that canonical persistence backends are available before any execution begins.

The RuntimeEventStore Abstraction

The RuntimeEventStore interface in packages/runtime/src/runtime-event-store.ts abstracts the persistence layer, exposing a durability property indicating whether the implementation provides "best_effort" or "canonical" guarantees. This interface defines three critical methods: append() for writing events, flush() for forcing durable commits, and applyTerminalBarrier() for final execution sealing.

Event Durability Levels

Each RuntimeEvent carries its own durability flag. Incoming events typically use "best_effort" persistence during initial capture, while outgoing results use "canonical" durability when the execution requires strict guarantees. This staged approach balances performance with safety.

Execution Flow and Durability Guarantees

The AgentRun class implements the core durability logic across three lifecycle stages: initialization, turn execution, and finalization.

Constructor Validation

Upon instantiation, AgentRun validates that required durability configurations have the necessary storage backends. The isDurable() method provides a runtime check by returning true when this.input.durability === "required".

The runTurn() Method

The runTurn() method in packages/runtime/src/agent-run.ts implements a three-stage durability pipeline:

  1. Incoming Event Capture: Records the goal input with "best_effort" durability via runtimeEventStore.append().
  2. Goal Execution: Processes the goal logic without blocking on persistence.
  3. Result Persistence: Writes the outgoing event with durability set to "canonical" if isDurable() returns true, otherwise "best_effort".

Following the append operation, the method explicitly calls await this.input.runtimeEventStore?.flush() when durability is required, ensuring the event reaches stable storage before proceeding.

The Terminal Durability Barrier

The finalize() method applies the terminal durability barrier by invoking applyTerminalBarrier() on the event store. This operation ensures that all pending events achieve canonical durability status, creating a recovery point that allows the system to resume or replay the execution from a known consistent state after a crash.

Practical Implementation Examples

To execute an agent with full durability guarantees:

import { AgentRun } from "./packages/runtime/src/agent-run";
import { SqliteRuntimeStore } from "./packages/storage/src/sqlite-runtime-store";

const store = new SqliteRuntimeStore({ durability: "canonical" });

const run = new AgentRun({
  runtimeEventStore: store,
  agentRunStore: {}, // Required store reference
  durability: "required",
});

await run.runTurn(myGoal);
await run.finalize(); // Enforces terminal durability barrier

For development or non-critical workflows, best-effort execution eliminates the flush overhead:

const run = new AgentRun({
  durability: "best_effort",
  // runtimeEventStore optional for best_effort
});

await run.runTurn(myGoal);
// No finalize barrier required

Summary

  • AgentRun validates durability requirements at construction, throwing errors if required stores are missing when durability: "required" is specified in packages/runtime/src/agent-run.ts.
  • RuntimeEventStore provides the abstraction layer for persistence in packages/runtime/src/runtime-event-store.ts, distinguishing between best_effort and canonical durability levels through the flush() and applyTerminalBarrier() methods.
  • runTurn() stages events with appropriate durability tags, forcing a flush to stable storage when operating in required durability mode.
  • finalize() establishes the terminal durability barrier, ensuring the entire execution is recoverable and consistent across crashes.
  • The system supports both best_effort execution for performance and required execution for critical workflows requiring guaranteed persistence.

Frequently Asked Questions

What happens if I set durability to "required" but forget to provide a RuntimeEventStore?

The AgentRun constructor immediately throws an error with the message "Required AgentRun durability needs AgentRunStore and RuntimeEventStore", preventing the execution from starting in an invalid configuration state.

What is the difference between "best_effort" and "canonical" durability?

Best-effort durability allows the system to acknowledge event writes before they reach stable storage, prioritizing performance. Canonical durability guarantees that events are persisted to durable storage before the operation completes, ensuring recoverability after crashes.

When does AgentRun call the flush() method?

AgentRun invokes flush() on the runtimeEventStore at the end of runTurn() only when isDurable() returns true, which occurs when the input configuration specifies durability: "required".

What is the purpose of the terminal durability barrier?

The terminal durability barrier, applied via applyTerminalBarrier() in the finalize() method, ensures that all events in the execution have achieved canonical durability status, creating a consistent recovery point that allows the system to resume or verify completion after unexpected failures.

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 →