Skip to main content
The run-state journal records the execution cursor of an agent run so a crash mid tool-loop can resume without re-executing side-effecting tools or re-billing LLM calls.

Quick Start

1

Simple Usage

Open a run, append a couple of events, then close it.
2

Resume after a crash

Compute replay_index() and drive the loop — journalled model calls and tools return their recorded results instantly, so the LLM is not re-billed and side-effecting tools are not re-run.

How It Works

The loop is re-driven from the top on resume; recorded steps return cached results while real work restarts at the first un-journalled step. The journal, run ledger, checkpoints, and inbound journal are four adjacent persistence primitives — pick correctly with this map.

Configuration Options

The journal is a zero-dependency SQLite primitive with a single constructor argument. RunJournal(db_path=None) constructor Event kinds — the five boundaries the journal records: JournalEvent dataclass RunMeta dataclass RunJournal public methods Import the primitive and its event kind constants directly:

Common Patterns

Three patterns cover the full open → journal → resume lifecycle. Journal every boundary as it happens. Record a model_decision, tool_call, tool_result, and iteration at each step.
Resume with memoised replay. Look up each step in replay_index(); a hit skips re-execution.
Discover interrupted runs on gateway startup. Any run still running after a crash is a resume candidate.

Best Practices

The five event kinds cover every point where re-execution would be either wasteful (model_decision) or unsafe (tool_call/tool_result, approval). Omitting a boundary means that boundary re-runs on resume.
last_iteration() reads this to restore the loop cursor exactly on resume; without it the resumed loop must scan the journal to find its position.
open_run(..., checkpoint_id=...) (or a later set_checkpoint) is what lets a resume restore the workspace to a consistent state before replaying — otherwise replay may run against a workspace that has drifted.
The full (seq, kind) position-aware compare is the determinism guardrail — perfect for test coverage of your loop wiring, unnecessary on every replay step in production.

Run Ledger

Tracks run status (queued/running/done) — the journal tracks the per-event cursor.

Checkpoints

Workspace file snapshots bound via checkpoint_id for restore-before-replay.

Durable Approvals

Approval decisions journalled as KIND_APPROVAL events for pause-for-approval HITL.

Inbound Journal

Webhook dedup and in-flight recovery — a different scope from run-state replay.