Pi Durable is an experimental TypeScript library from Earendil for building AI agents that survive crashes. It was released on 1 October 2026 together with Pi 1.0. Every model request and tool call becomes a small task that saves a checkpoint before the agent moves on. If the process dies, a new process opens the same storage and continues from the last checkpoint. This guide explains what Pi Durable does, how its checkpoint stores and tool replay rules work, which platforms already integrate it, and what to watch out for before you use it.
The short version
What Pi is, and where Pi Durable fits
Pi started as a small, open-source coding agent for the terminal by Mario Zechner. Earendil, the company co-founded by Armin Ronacher, now maintains it in the earendil-works/pi repository under the MIT license. The coding agent runs on one machine and is driven by one person.
Earendil's announcement describes Pi Durable as "a framework for building any agentic application, coding agents included." It does not replace the Pi coding agent. It shares code with it, such as the pi-ai model layer, and is meant for agents that run anywhere, are reached from several apps, hold very long conversations and survive failures. Several people can watch and steer the same conversation.
How Pi Durable works
Everything is a task with a checkpoint
In Earendil's words, "every step of a run is a task that stores a checkpoint before it moves on." A model call is a task. A tool call is a task. Compaction, the step that summarises a long conversation, is a task that runs in the background. Each change is an atomic commit: either all of it is stored, or none of it.
According to the package README, nothing is shown to the user before its commit is stored. After a restart you call resume() and the scheduler continues any unfinished work.
Interrupted model calls are retried
If the process dies while a model is streaming an answer, Pi keeps the partial answer marked as aborted and counts the interruption as a failed attempt. It retries after a backoff. When no retries are left, the run ends unanswered with the reason "interrupted".
Submissions are not duplicated
Each input you send can carry a requestId. If a client sends the same request twice, for example after a network error, Pi returns the existing submission instead of starting a second one.
Crash loops are stopped
A task that crashes the process every time would otherwise restart forever. Pi counts restarts and ends the task after a limit, which defaults to five.
Tool replay declarations
This is the most important idea in Pi Durable. Before a tool runs, Pi commits its intent. If the process dies during the call, Pi has to decide whether to run it again. It does not guess. Each tool says it upfront.
- A tool marked replay: "safe" is run again after a crash. Use this for reads and for actions that are already idempotent.
- A tool without that mark is never run again automatically. The model gets an "interrupted" result with any output committed so far, and decides what to do next.
Earendil's example is a deploy: "a deploy interrupted by a crash is reported to the model, never repeated." Here is a simplified sketch based on the README:
const lookupOrder = defineTool({
name: "lookup_order",
description: "Read an order from the shop database",
parameters: obj({ orderId: str() }),
replay: "safe", // reading twice is harmless, so rerun after a crash
execute: async (args) => {
/* ... */
},
});
const refundOrder = defineTool({
name: "refund_order",
description: "Refund an order",
parameters: obj({ orderId: str() }),
// no replay declaration: after a crash the model is told
// the call was interrupted, and it is not run again
execute: async (args) => {
/* ... */
},
});Replay-safe is your promise, not Pi's
Checkpoint stores
Pi Durable separates the agent from where its state lives. The README lists these backends:
| Store | Where | Notes from the README |
|---|---|---|
| Memory | In the process | Nothing is persisted. Good for tests. |
| SQLite | One database file (Node) | WAL mode; commits survive process crashes, but the newest may be lost on power or host failure. |
| JSONL | Append-only files in a folder | Optional fsync before each commit. Keeps the whole history in memory, so the README recommends SQLite for long-running agents. |
| IndexedDB | Browser | One owner at a time; use a Web Lock. |
| Cloudflare Durable Object | SQLite storage of one Durable Object | Commits are the object's storage transactions. |
You can also write your own backend, for example on Postgres or a key-value store. Earendil ships a conformance test suite to check that a custom store behaves correctly.
Integrations: Cloudflare, Temporal and Rivet
Cloudflare Agents SDK
Cloudflare documents running Pi inside a Durable Object through PiHarness in the Agents SDK. Pi stores its transcripts and tasks in the object's SQLite database, in tables prefixed with "pi_". While Pi has work, an alarm fires every 30 seconds. If the object is evicted or crashes, the next alarm restarts it and the run continues.
Temporal (pi-temporal)
Temporal took a different route. In "The immortal life of Pi" (8 October 2026), Temporal describes pi-temporal, which runs the Pi coding agent on a fleet of Temporal workers. The authors wanted failover across machines and note that Pi Durable's local SQLite store survives process crashes but not host failure. So pi-temporal uses Temporal as the execution engine rather than Pi Durable's storage. It is described as an experiment built on a small fork of Pi.
Rivet
Rivet announced on 7 October 2026 that its pi() helper runs a Pi Durable harness inside a Rivet Actor. Each actor stores one harness in its own SQLite database, so runs continue through crashes and upgrades, and idle agents can sleep.
| Integration | Runs on | State lives in | Status |
|---|---|---|---|
| Cloudflare PiHarness | Durable Object via Agents SDK | Object's SQLite (pi_ tables) | Pi Durable is experimental; API can change in minor releases |
| Temporal pi-temporal | Temporal workers | Shared session files plus Temporal | Described as an experiment on a fork of Pi |
| Rivet pi() | Rivet Actor | Actor's SQLite | Rivet says to expect API changes |
Caveats before you use Pi Durable
- Experimental. Earendil says "the API might still change", and the README warns it can change without notice between releases.
- No built-in tool approval step. Cloudflare's docs state that Pi Durable has no approval or permission step for tool calls yet. You can block tools with a hook, as the README shows, but a full human approval flow is up to you.
- Local storage limits. SQLite on one machine survives process crashes, not host loss.
- Platform limits on Cloudflare. A single model request streaming longer than 15 minutes can be cut off, session deletion is not supported yet, and rolling back to an older Pi version can leave newer conversations unreadable, so Cloudflare advises rolling forward.
- TypeScript only, for now.
Getting started
- 1Install the package and run the README quick start with in-memory storage.
- 2Switch to SQLite storage, start a long task, kill the process and call resume().
- 3Go through every tool and decide: replay-safe or not. Add idempotency keys to external calls.
- 4Add a hook that blocks risky tools until you have a proper approval flow.
- 5Pick a host: your own server, Cloudflare, Rivet, or Temporal if you need cross-machine failover.
For the wider picture of durable execution, including Temporal, Restate, Inngest, DBOS and LangGraph, read our durable AI agents guide. For the Cloudflare side, see Cloudflare Project Think.
How Halmob helps
Halmob builds durable agents: long-running agents that keep their state, retry after failures and resume where they stopped, for work that spans hours or days. Through our agent platform consultancy we help businesses choose, set up and roll out Pi Durable, OpenClaw, Hermes Agent, Meta Muse, OpenAI Dots or Claude Duet, including the tool replay review and approval flow that Pi Durable leaves to you. Get in touch to discuss your project.