---
name: Checkpointing
description: Explains Agency's ability to snapshot and restore execution state via `checkpoint`, `getCheckpoint`, and `restore`, which underpins interrupts, error recovery, forks, and the time-travel debugger.
---

# Checkpointing

## Creating checkpoints

Agency can pause and serialize its execution state at any point. The core API has three functions:
- `checkpoint()` — snapshot current state, returns a numeric ID
- `getCheckpoint(id)` — retrieve the full checkpoint object for a given ID (eg to save to disk)
- `restore(idOrCheckpoint, options)` — roll back to a checkpoint (accepts either a numeric ID or a Checkpoint object)

This lets you roll back to a previous point in execution. Here's a simple example:

```ts
node main() {
  const cp = checkpoint()
  const result:number = llm("Generate a random integer between 1 and 6")

  if (result < 3) {
    print("Bad roll, rolling back...")
    restore(cp)
  }
  print("Good roll:", result)
}
```

Note that this is not like a while loop that keeps retrying. This is actually restoring to a previous execution state. For example, suppose we want to count how many times we have rolled back. We try inserting a counter:

```ts
node main() {
  let counter = 1
  const cp = checkpoint()
  const result:number = llm("Generate a random integer between 1 and 6")

  if (result < 3) {
    print("Bad roll, rolling back...")
    counter++
    restore(cp)
  }
  print("Good roll:", result, "after", counter, "rolls")
}
```

This will not work. It will always print "...after one rolls", because if it's a bad roll, we increment the counter but then *immediately roll back*, which restores the counter back to one:

```ts
counter++
restore(cp)
```

You can take this one step further by getting the checkpoint and saving it to a file, which lets you restore back to that state at any point in the future, as long as the code hasn't changed.

```ts
const id = checkpoint()
const cp = getCheckpoint(id)
printJSON(cp)
```

Copy the printed JSON object into `checkpoint.json`. Do not redirect the whole
output of `agency run` into that file: the run banner and any other program
output would make it invalid JSON.

Resume it against the same source file:

```bash
agency resume checkpoint.json program.agency
```

You can change values in the current checkpoint frame while resuming:

```bash
agency resume checkpoint.json program.agency \
  --local-var mood='"happy"' \
  --arg input='{"retry":true}' \
  --global-var attempts=8
```

Values are parsed as JSON when possible and otherwise treated as strings. Use
repeated `--program-arg <value>` flags if the resumed program reads
`std::args`; process arguments are not stored in checkpoints.

This is kind of like saving your progress in a video game and coming back to it later.

## restore options

When you restore, you can optionally provide overrides for any of the variables in that checkpoint. This allows you to retry a section of code with different inputs.

You can override **function arguments**:

```ts
restore(result.checkpoint, { args: { input: "good" } })
```

**Global variables**:

```ts
restore(result.checkpoint, { globals: { attempts: 8 } })
```

Or **local variables**:

```ts
restore(result.checkpoint, { locals: { x: 8 } })
```

You can also limit the number of times you restore a checkpoint using `maxRestores`:


```ts
restore(result.checkpoint, { maxRestores: 3 })
```

## Inspecting checkpoints

You can inspect a checkpoint saved to disk using the debugger, like so:

```
agency debugger foo.agency --checkpoint <checkpoint-file>
```

Note that you have to additionally give the source file.
## Verifying checkpoint integrity

You can verify that a checkpoint has not been tampered with. If you set the AGENCY_CHECKPOINT_KEY environment variable, Agency will embed a checksum into every checkpoint.

```bash
export AGENCY_CHECKPOINT_KEY=$(openssl rand -hex 32)
```

 You can verify the checkpoint like this:
 
```ts
import { verifyCheckpointChecksum } from "agency-lang";

if (!verifyCheckpointChecksum(checkpoint)) {
  // oops! Someone has edited this checkpoint. Refuse to resume
}
```

Signing is opt-in. Hosts using the JavaScript API call
`verifyCheckpointChecksum` themselves. `agency resume` checks a signature when
one is present and refuses an invalid or unverifiable signature unless you pass
`--force`.
