Skip to main content
Gateway agents journal every turn by default, so an interrupted turn can be resumed by run id without re-firing side-effecting tools or re-billing LLM calls. The gateway does not auto-resume on restart — you resume a turn yourself with ExecutionConfig(durable=True, resume_run_id=..., journal_path=...), the same journal, and the recorded task (see Resuming an interrupted turn). No flag needed for journalling — it auto-enables whenever your session store is durable (the shipped default). Two explicit opt-outs are supported for the zero-overhead path.

Quick Start

Migration (PR #4218). Prior releases required gateway.durable_runs: true to opt in. The default is now on whenever your session store is durable — no config change needed to gain crash-safe journalling (resume stays a manual step). Want the old zero-overhead behaviour? Set gateway.durable_runs: false or gateway.reliability: "off".
1

Zero-config default (every turn is journalled)

Sessions persist by default, so durable runs are already on — no gateway: block required:
Restart the gateway mid-run; the interrupted turn is left running in the RunJournal. To finish it without re-charging the card or re-billing the model, resume it by run id — see Resuming an interrupted turn.
2

Opt out (zero-overhead path)

Two explicit escape hatches turn durable runs off:
In-memory sessions disable it too — with session.persist: false there is no durable store to journal against, so durable runs silently stay off.
3

Override per agent

A per-agent durable flag wins in both directions — opt one agent out even when the gateway default is on, or opt one in even when it’s off:
4

Toggle the default off from the environment

gateway.durable_runs accepts an ${ENV_VAR}-substituted string. Because ${DURABLE} renders as a string, the value is coerced explicitly — "false"/"0"/"no"/"off"/"" disable, and "true"/"1"/"yes"/"on" enable:
"false" really means false here. Without this coercion, bool("false") would be truthy and silently enable durability.

How It Works

Each gateway agent journals its turn to the core RunJournal whenever durable runs are on — decided from config plus the effective session store. Resuming is a separate, manual step: a turn resumed by run id replays journalled steps and runs only the un-journalled ones.

Choosing whether durable runs run

Precedence ladder: per-agent durable > explicit gateway.durable_runs > gateway.reliability: "off" (forces off) > effective session store (auto-on when durable, off when in-memory).
The durable-runs decision is re-evaluated on every load path — initial load, full-restart reload, and selective reload — so restarting the gateway keeps durability wired.
Zero overhead when off. On an opted-out path the execution hot path is unchanged and ExecutionConfig is never imported.
Graceful degrade. If ExecutionConfig can’t be imported (an older core), the gateway logs a warning and the agent runs non-durably — the gateway never fails to start over durability.

Resuming an interrupted turn

Nothing resumes interrupted turns automatically. List them from the journal and resume each with its recorded task:
Autonomous and goal loops (run_autonomous, run_goal) cannot be resumed by run id — only a single chat() turn can. A crash inside those loops loses the loop cursor (iteration, stage, spend baseline). Treat gateway durability as per-turn resume, not per-loop resume.

How to opt out

There are three ways to end up with durable_runs=false, plus one silent fallback:
  1. Explicit off — set gateway.durable_runs: false.
  2. Reliability off — set gateway.reliability: "off" (the immediate-teardown posture forces durable runs off for the zero-overhead path).
  3. No durable store — set session.persist: false; with no store to journal against, durable runs auto-default to off.
  4. Silent fallback — session.persist: true but the persistent store failed to initialise (e.g. absent or read-only ~). The gateway logs the fallback and stays non-durable — worth checking, because operators otherwise assume their intent is honoured.

Configuration Options

The underlying agent primitive is ExecutionConfig(durable=True) — see that page for journal_path, resume_run_id, and the resume contract.

Common Patterns

Fleet-wide durability with a chit-chat escape hatch — durable runs are already on by default, so opt out only the agents that make small talk:
Toggle by environment — durable in production, off in ephemeral CI:

Best Practices

The default ~/.praisonai/runs/journal.db is lost when a container is recreated. Configure a mounted volume so the journal survives restarts — see Durable Tool Runs.
Durable runs only auto-enable when the session store instantiates. On an absent or read-only home directory the store degrades to in-memory and durable runs silently stay off — check the gateway log for the fallback if you expected crash-safe journalling.
Small-talk agents don’t need journalling. Set durable: false on them, keeping the hot path clean for stateless turns even while the gateway default is on.
Durable gateway runs and session persistence are different layers — one journals the in-flight turn so it can be resumed, the other restores conversation history. Both survive a restart and work together.

Durable Tool Runs

The underlying agent primitive — ExecutionConfig(durable=True).

Run-State Journal

The SQLite journal durable runs write to.

Gateway Session Persistence

The durable store durable runs auto-enable against.

Gateway Reliability

reliability: "off" forces durable runs off.