Fork, time travel, and snapshot AI agent runs
To rewind an agent run to an earlier point — or branch a new run from it — Tidebase models every state update as a version in a stream. A snapshot is just a labeled version, so time travel, forking, and restore all fall out of one small model:
current state = latest version in a stream
snapshot = labeled state version
time travel = read an older version
fork = create new app/run context from an older version
restore = append a new version based on an older version
Tidebase is an open-source checkpoint layer for AI agents: wrap your steps, and failed runs resume from the last safe point — in your own Postgres, without moving execution into a new runtime.
Writing versions
run.state.set() and run.state.patch() update the live run state and append to the version history:
await run.state.patch({ status: 'writing', progress: 0.7 })
Label the current state when it becomes a meaningful review or restore point:
await run.state.save('before-approval', {
reason: 'the user is about to approve sending'
})
Snapshots of app-level targets
Snapshots are a convenience API over labeled versions for external targets — reports, artifacts, workspaces, documents, app state:
await run.snapshots.create('draft-v1', {
target: { type: 'report', id: reportId },
state: draft,
reason: 'first complete draft'
})
Reading history
GET /runs/:runId/state/versions — all versions, all streams
GET /runs/:runId/state/versions?labeled=true — labeled versions (snapshots) only
GET /runs/:runId/state/versions?stream=NAME — one stream
What fork/restore means is yours to define
Tidebase stores and exposes the versions; your app decides what restoring a report or forking a workspace means for its own state targets. A forked run is a new run whose initial context comes from an older version — completed steps in the parent replay from checkpoints, so a fork doesn’t re-pay for work already done.
See also: Fan out to subagents · Checkpointing in Postgres