# How Maka Classifies Agent Run Recovery After a Crash

> Discover how Maka classifies agent run recovery after a crash. Maka inspects the AgentRun ledger to determine the best recovery action resume retry or escalate.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: internals
- Published: 2026-09-08

---

**When a Maka agent process crashes, the runtime inspects the durable AgentRun ledger to assign a failure class and recovery reason that determine whether to resume, retry, or escalate to manual intervention.**

Apache Maka's runtime handles agent crashes by analyzing the immutable event log rather than blindly replaying execution from the beginning. The classification logic, implemented in [`packages/runtime/src/agent-run-recovery.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run-recovery.ts), reads the persistent **AgentRun ledger** to categorize failures and determine the appropriate recovery strategy. This approach prevents duplicate side-effects while maintaining an auditable history of every crash and recovery decision.

## The AgentRun Ledger as the Source of Truth

The foundation of Maka's crash recovery is the **AgentRun ledger**, an append-only log that records every dispatch, tool call, and outcome up to the point of failure. When a crash occurs, the runtime does not attempt to reconstruct state from scratch. Instead, it loads the most recent `AgentRun` record from this durable log to identify the last known good state and detect anomalies in the event stream.

According to the Apache Maka source code, the ledger stores events as JSON-L lines, allowing the runtime to parse the final entry and determine if the event stream is truncated or malformed. This inspection drives the subsequent classification logic.

## The Six-Step Classification Pipeline

The `classifyAgentRunRecovery` function in [`packages/runtime/src/agent-run-recovery.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run-recovery.ts) executes a deterministic pipeline to categorize the failure:

### 1. Load the Latest AgentRun Entry

The runtime reads the most recent `AgentRun` record from the ledger. This provides the baseline state for all subsequent classification checks.

### 2. Detect Event Corruption

If the JSON cannot be parsed or the event stream appears truncated, the system assigns `failureClass = "event_corrupt"` and `recoveryReason = "corrupt"`. This indicates the ledger itself is damaged and requires manual intervention.

### 3. Identify Application Restart

When the host process has restarted (indicated by a new PID) while a previous `AgentRun` remains open, the classification becomes `failureClass = "app_restarted"` with `recoveryReason = "app_restart"`. This signals a clean process termination rather than a logic error.

### 4. Recognize Child-Process Crashes

If the crash originated from a sandboxed child process—such as a tool container—the ledger contains a `child_crash` marker. The runtime assigns `failureClass = "child_crash"` and `recoveryReason = "child_process"`, indicating an isolated tool failure rather than a systemic agent error.

### 5. Distinguish Normal Termination

When the agent run completed successfully before the host crash, the ledger ends with a `run_completed` event. The system classifies this as `failureClass = "run_completed"` and `recoveryReason = "normal"`, allowing the runtime to skip recovery entirely.

### 6. Default to Unknown

Any situation that does not match the above patterns falls back to `failureClass = "unknown"` and `recoveryReason = "unspecified"`, triggering the conservative "irrecoverable" handling path.

## Recovery Event Structure and Fields

Once classified, the runtime emits a **durable recovery event** (such as `run_failed` or `run_completed`) appended to the log. This event contains specific fields that downstream components use to decide recovery actions:

- **`failureClass`** — The high-level category describing the crash type (e.g., `app_restarted`, `child_crash`).
- **`recoveryReason`** — A short string explaining the specific cause (e.g., `app_restart`, `child_process`).
- **`lastEventType`** — The type of the final event observed before the crash occurred.
- **`eventCorrupt`** — A boolean flag set to `true` when the ledger is malformed or unreadable.

These fields ensure that recovery decisions are data-driven and deterministic across all Maka deployments.

## Recovery Strategy Determination

The classification directly drives the runtime's next actions, ensuring no duplicate side-effects occur while maintaining system integrity:

**Idempotent Actions**
When the `failureClass` indicates that an operation was already persisted (such as a tool call that wrote its result to the ledger), the runtime skips re-execution entirely. This prevents duplicate writes or API calls.

**Retryable Actions**
For classifications like `child_crash` where side-effects are known to be isolated or safely rollbackable, the runtime may re-dispatch the specific tool call rather than restarting the entire agent run.

**Manual Intervention**
When `event_corrupt` or `unknown` classifications appear, the system aborts automatic recovery and surfaces diagnostic information to the operator. This ensures that data corruption does not propagate through automated retry loops.

## Implementation Example

The following TypeScript demonstrates how to invoke the classification logic and branch based on the resulting failure class:

```typescript
import { classifyAgentRunRecovery } from '@maka/runtime';

async function handleCrashRecovery(agentRunId: string) {
  const rec = await classifyAgentRunRecovery(agentRunId);
  
  console.log('Failure class:', rec.failureClass);
  console.log('Recovery reason:', rec.recoveryReason);
  
  switch (rec.failureClass) {
    case 'app_restarted':
      // Safe to resume from the last checkpoint
      await resumeFromCheckpoint(rec.lastEventType);
      break;
    case 'child_crash':
      // Retry the specific tool that crashed
      await retryToolCall(rec.lastEventType);
      break;
    case 'event_corrupt':
    default:
      // Escalate to manual review
      await alertOperator(rec);
  }
}

```

To emit a recovery event after classification, the runtime uses a structure similar to this simplified implementation:

```typescript
function emitRecoveryEvent(
  failureClass: string,
  reason: string,
  lastEvent: string
) {
  const event = {
    type: 'run_failed',
    failureClass,
    recoveryReason: reason,
    lastEventType: lastEvent,
    eventCorrupt: failureClass === 'event_corrupt',
    timestamp: new Date().toISOString(),
  };
  // Append to the immutable runtime log
  runtimeLog.append(JSON.stringify(event));
}

```

## Summary

- Apache Maka classifies agent run recovery by inspecting the durable **AgentRun ledger** rather than replaying execution from scratch.
- The classification logic resides in [`packages/runtime/src/agent-run-recovery.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run-recovery.ts) and evaluates the last known state to assign specific `failureClass` and `recoveryReason` values.
- **Failure classes** include `event_corrupt`, `app_restarted`, `child_crash`, `run_completed`, and `unknown`, each triggering distinct recovery strategies.
- The system guarantees **no duplicate side-effects** by skipping already-persisted operations and only retrying actions known to be safe.
- All recovery decisions produce **durable events** containing `failureClass`, `recoveryReason`, `lastEventType`, and `eventCorrupt` fields for complete auditability.

## Frequently Asked Questions

### What is the AgentRun ledger in Apache Maka?

The **AgentRun ledger** is an append-only event log that records every dispatch, tool call, and outcome during an agent's execution. Stored as JSON-L lines, it serves as the durable source of truth for crash recovery, allowing the runtime to inspect the final state and determine appropriate recovery actions without replaying the entire execution history.

### How does Maka prevent duplicate side-effects during recovery?

Maka prevents duplicates by classifying whether an action was already persisted in the ledger before the crash. When the `failureClass` indicates idempotent completion (such as a tool result already recorded), the runtime skips re-execution. Only operations classified as `child_crash` or similar retryable states are re-dispatched, and only after confirming their side-effects are safely isolated or rollbackable.

### What happens when Maka detects a corrupted event log?

When the runtime encounters unparseable JSON or a truncated event stream, it assigns the `event_corrupt` failure class and immediately aborts automatic recovery. The system surfaces diagnostic information to the operator rather than attempting speculative repair, ensuring that data integrity issues do not propagate through automated retry mechanisms.

### Where is the recovery classification logic implemented?

The core classification logic is implemented in the `classifyAgentRunRecovery` function within [`packages/runtime/src/agent-run-recovery.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run-recovery.ts). Additional architectural context and field semantics are documented in [`docs/archive/runtime-kernel.md`](https://github.com/apache/maka/blob/main/docs/archive/runtime-kernel.md), which describes how the recovery pipeline processes ledger entries to generate recovery events.