How the Session Recovery Journal Ensures Idempotency for Commands in Prime Agent

The session recovery journal guarantees idempotency by maintaining an in-memory map of the latest record per session, comparing incoming commands against existing entries for identical busy flags, operation types, and sessionFile paths, and only appending to the log when the state actually changes.

Prime Agent, developed by PrimeIntellect-ai/prime-agent, implements a robust crash recovery mechanism through its session recovery journal system. This design ensures that daemon processes can replay actions after restarts without duplicating work, making the session recovery journal idempotency strategy critical for reliable distributed task execution.

How the Recovery Journal Achieves Idempotency

The WorkerRecoveryJournal class in packages/coding-agent/src/modes/daemon/worker-recovery-journal.ts implements a four-stage deduplication strategy that prevents duplicate command recording.

Maintaining the Latest Record per Session

When the journal initializes, the parseRecords method reads the on-disk JSON-L file and populates an in-memory Map<string, WorkerRecoveryRecord> keyed by activeSessionId [lines 24-55]. This map always holds the most recent state for each active session, enabling O(1) lookups during the deduplication check.

Deduplicating Before Appending

The core idempotency logic resides in the record method [lines 66-74]. When receiving a new record (excluding version and recordedAt fields), the method looks up the previous entry for the same activeSessionId and compares the busy flag, operation, and sessionFile fields. If all three properties match the existing record, the method returns early without writing to disk. This comparison ensures that identical commands produce no side effects upon retry.

Compacting Stale Entries

After each successful write, the journal evaluates whether all entries are non-busy (!entry.busy). When this condition is met, the compact method rewrites the file to contain only the latest snapshot [lines 82-84]. This compaction eliminates accumulated duplicate records from previous states while preserving the idempotency guarantee, as the single retained entry represents the definitive state.

Implementation Details in worker-recovery-journal.ts

The record method prevents unnecessary disk writes by comparing state triplets. When the incoming record differs from the cached entry, the method serializes the new record, appends it to the JSON-L file, and updates the in-memory map [lines 75-81].

The following example demonstrates the idempotent behavior using the WorkerRecoveryJournal class:

import { WorkerRecoveryJournal } from "packages/coding-agent/src/modes/daemon/worker-recovery-journal.js";

// Create a journal that writes to a JSONL file
const journal = new WorkerRecoveryJournal("/tmp/worker.recovery.jsonl");

// First attempt – record a new operation
journal.record({
  activeSessionId: "sess‑123",
  sessionId: "sess‑123",
  busy: true,
  operation: "runTool",
  sessionFile: "/tmp/session‑123.json",
});

// Second attempt – same data, idempotent (no new line is written)
journal.record({
  activeSessionId: "sess‑123",
  sessionId: "sess‑123",
  busy: true,
  operation: "runTool",
  sessionFile: "/tmp/session‑123.json",
});

// A changed operation – a new line is appended
journal.record({
  activeSessionId: "sess‑123",
  sessionId: "sess‑123",
  busy: false,
  operation: "complete",
  sessionFile: "/tmp/session‑123.json",
});

Running this code produces exactly two lines in the recovery log. The second call matches the previous entry on busy, operation, and sessionFile, triggering the early return at lines 66-74. Only the third call, which changes the operation to "complete" and sets busy to false, generates a new persistent record.

Summary

  • Session recovery journal idempotency relies on an in-memory map keyed by activeSessionId to track the latest state for each session, as implemented in worker-recovery-journal.ts.
  • The record method prevents duplicate writes by comparing the busy flag, operation, and sessionFile fields against existing entries before appending.
  • State changes trigger append-only writes to the JSON-L file, while identical commands return early without disk I/O.
  • Log compaction removes stale entries when all sessions become non-busy, maintaining a minimal recovery footprint without breaking idempotency guarantees.
  • A similar design pattern appears in command-recovery-journal.ts for daemon-level command durability.

Frequently Asked Questions

What happens if the same command is recorded twice?

If the incoming record matches the existing entry for activeSessionId on all three compared fields (busy, operation, sessionFile), the record method returns early without appending to the log file [lines 66-74]. This ensures that retrying identical commands generates no duplicate entries, maintaining strict session recovery journal idempotency even during network retries or process restarts.

How does the journal handle crashes during compaction?

The compaction mechanism rewrites the entire file only when all entries report busy: false. Since compaction occurs after successful writes and operates on the in-memory map state, a crash during the rewrite leaves the original file intact. The next initialization will call parseRecords from the existing file [lines 24-55], and the compaction will retry once the daemon stabilizes without data loss.

What is the difference between WorkerRecoveryJournal and CommandRecoveryJournal?

Both classes implement identical session recovery journal idempotency patterns but target different scopes. WorkerRecoveryJournal handles session state for individual worker processes, tracking activeSessionId and tool execution status. command-recovery-journal.ts applies the same deduplication logic to daemon-level commands, ensuring that high-level orchestration actions also replay exactly once after recovery.

Does compaction affect idempotency guarantees?

No, compaction preserves idempotency by retaining only the latest record for each session when all operations complete. Since the compacted file still contains the definitive state triplets (busy, operation, sessionFile), subsequent record calls compare against the correct baseline. The deduplication logic at lines 66-74 remains valid whether operating against the full log or a compacted snapshot.

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 →