---
title: Checkpointing
description: Automatically save execution state so crews, flows, and agents can resume after failures.
icon: floppy-disk
mode: "wide"
---
Checkpointing saves a snapshot of execution state during a run so a crew, flow, or agent can resume after a failure or be forked into an alternate branch.
How checkpointing works: events, storage, and inheritance.
A 5-minute walkthrough: run, interrupt, resume.
Task-focused recipes for common workflows.
`CheckpointConfig`, events, providers, and CLI.
## Explanation
### What a checkpoint is
A checkpoint is a serialized snapshot of `RuntimeState` written at a point in execution. It records which tasks have completed, their outputs, the current inputs, and a lineage ID that identifies the run.
When you restore from a checkpoint, CrewAI rebuilds that state, skips already-completed work, and continues. When you fork from one, CrewAI restores the state under a new lineage so the new branch and the original run do not overwrite each other.
### When checkpoints are written
Checkpointing is event-driven. The runtime subscribes to events you select via `on_events` and writes a checkpoint each time one fires. The default `task_completed` produces one checkpoint per finished task — a sensible tradeoff between granularity and disk use. Higher-frequency events like `llm_call_completed` are available for fine-grained recovery but write far more files.
### Storage
Two providers ship with CrewAI:
- `JsonProvider` writes one file per checkpoint. Human-readable and easy to inspect.
- `SqliteProvider` writes to a single SQLite database. Better for high-frequency checkpointing.
Both prune oldest checkpoints when `max_checkpoints` is set.
Checkpoint writes are best-effort. A failed checkpoint is logged but does not interrupt the run.
### Inheritance model
`Crew`, `Flow`, and `Agent` all accept a `checkpoint` argument. Children inherit from their parent unless they set their own value or pass `False` to opt out. Enable checkpointing once on the crew and every agent participates, or selectively exclude one agent.
## Tutorial: Resume a failing crew
This walkthrough takes ~5 minutes. You will run a two-task crew, kill it midway, and resume from the saved checkpoint.
```python
from crewai import Agent, Crew, Task
researcher = Agent(role="Researcher", goal="Research", backstory="Expert")
writer = Agent(role="Writer", goal="Write", backstory="Expert")
crew = Crew(
agents=[researcher, writer],
tasks=[
Task(description="Research AI trends", agent=researcher, expected_output="bullets"),
Task(description="Write a summary", agent=writer, expected_output="paragraph"),
],
checkpoint=True,
)
```
```python
result = crew.kickoff()
```
Press `Ctrl+C` after the first task finishes. Look in `./.checkpoints/` — a file named `_.json` is the checkpoint.
```python
from crewai import CheckpointConfig
result = crew.kickoff(
from_checkpoint=CheckpointConfig(
restore_from="./.checkpoints/_.json",
),
)
```
The research task is skipped, the writer runs against the saved research output, and the crew finishes.
## How-to guides
```python
crew = Crew(agents=[...], tasks=[...], checkpoint=True)
```
Writes to `./.checkpoints/` on every `task_completed`.
```python
from crewai import Crew, CheckpointConfig
crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
location="./my_checkpoints",
on_events=["task_completed", "crew_kickoff_completed"],
max_checkpoints=5,
),
)
```
```python JsonProvider
from crewai import Crew, CheckpointConfig
from crewai.state import JsonProvider
crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
location="./my_checkpoints",
provider=JsonProvider(),
max_checkpoints=5,
),
)
```
```python SqliteProvider
from crewai import Crew, CheckpointConfig
from crewai.state import SqliteProvider
crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
location="./.checkpoints.db",
provider=SqliteProvider(),
max_checkpoints=50,
),
)
```
SQLite enables WAL journal mode for concurrent reads. Prefer it for high-frequency checkpointing.
```python
crew = Crew(
agents=[
Agent(role="Researcher", ...),
Agent(role="Writer", ..., checkpoint=False),
],
tasks=[...],
checkpoint=True,
)
```
```python
config = CheckpointConfig(restore_from="./my_checkpoints/.json")
crew = Crew.from_checkpoint(config)
result = crew.kickoff()
```
`fork()` restores a checkpoint under a fresh lineage so the new run does not collide with the original.
```python
config = CheckpointConfig(restore_from="./my_checkpoints/.json")
crew = Crew.fork(config, branch="experiment-a")
result = crew.kickoff(inputs={"strategy": "aggressive"})
```
The `branch` label is optional; one is generated if omitted.
```python
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, review_task],
checkpoint=CheckpointConfig(location="./crew_cp"),
)
```
Default trigger: `task_completed`.
```python
from crewai.flow.flow import Flow, start, listen
from crewai import CheckpointConfig
class MyFlow(Flow):
@start()
def step_one(self):
return "data"
@listen(step_one)
def step_two(self, data):
return process(data)
flow = MyFlow(
checkpoint=CheckpointConfig(
location="./flow_cp",
on_events=["method_execution_finished"],
),
)
result = flow.kickoff()
config = CheckpointConfig(restore_from="./flow_cp/.json")
flow = MyFlow.from_checkpoint(config)
result = flow.kickoff()
```
```python
agent = Agent(
role="Researcher",
goal="Research topics",
backstory="Expert researcher",
checkpoint=CheckpointConfig(
location="./agent_cp",
on_events=["lite_agent_execution_completed"],
),
)
result = agent.kickoff(messages=[{"role": "user", "content": "Research AI trends"}])
```
Register a handler on any event and call `state.checkpoint()`.
```python Sync
from crewai.events.event_bus import crewai_event_bus
from crewai.events.types.llm_events import LLMCallCompletedEvent
@crewai_event_bus.on(LLMCallCompletedEvent)
def on_llm_done(source, event, state):
path = state.checkpoint("./my_checkpoints")
print(f"Saved checkpoint: {path}")
```
```python Async
from crewai.events.event_bus import crewai_event_bus
from crewai.events.types.llm_events import LLMCallCompletedEvent
@crewai_event_bus.on(LLMCallCompletedEvent)
async def on_llm_done_async(source, event, state):
path = await state.acheckpoint("./my_checkpoints")
print(f"Saved checkpoint: {path}")
```
A `state` argument is supplied automatically when the handler takes three parameters. See [Event Listeners](/en/concepts/event-listener) for the full event catalog.
```bash
crewai checkpoint # auto-detects .checkpoints/ or .checkpoints.db
crewai checkpoint --location ./my_checkpoints
crewai checkpoint --location ./.checkpoints.db
```
The left panel groups checkpoints by branch; forks nest under their parent. Selecting a checkpoint shows its metadata, entity state, and task progress. **Resume** continues the run; **Fork** starts a new branch.
The detail panel exposes two editable areas:
- **Inputs** — original kickoff inputs, pre-filled and editable.
- **Task outputs** — outputs of completed tasks. Editing an output and hitting **Fork** invalidates downstream tasks so they re-run against the modified context.
Useful for "what if" exploration: fork, tweak, observe.
```bash
crewai checkpoint list ./my_checkpoints
crewai checkpoint info ./my_checkpoints/.json
crewai checkpoint info ./.checkpoints.db
```
## Reference
### `CheckpointConfig`
Storage destination. A directory for `JsonProvider`, a database file path for `SqliteProvider`.
Event types that trigger a checkpoint. See [event types](#event-types).
Storage backend. Either `JsonProvider` or `SqliteProvider`.
Maximum checkpoints to retain. Oldest are pruned after each write.
Checkpoint to restore from when passed via `from_checkpoint`.
### `checkpoint` field values
Accepted by `Crew`, `Flow`, and `Agent`.
Inherit from parent.
Enable with defaults.
Explicit opt-out. Stops inheritance.
Custom configuration.
### Event types
Common values for `on_events`:
| Use case | Events |
|:---------|:-------|
| After each task | `["task_completed"]` |
| After each flow method | `["method_execution_finished"]` |
| After agent execution | `["agent_execution_completed"]`, `["lite_agent_execution_completed"]` |
| On crew completion only | `["crew_kickoff_completed"]` |
| After every LLM call | `["llm_call_completed"]` |
| Everything | `["*"]` |
`["*"]` and high-frequency events like `llm_call_completed` write many checkpoints and can degrade performance. Pair them with `max_checkpoints`.
### Storage providers
One file per checkpoint, named `_.json` inside `location`.
Single database file at `location` with WAL journaling.
### CLI
| Command | Purpose |
|:--------|:--------|
| `crewai checkpoint` | Launch the TUI; auto-detect storage. |
| `crewai checkpoint --location ` | Launch the TUI against a specific location. |
| `crewai checkpoint list ` | List checkpoints. |
| `crewai checkpoint info ` | Inspect a checkpoint file or the latest entry in a SQLite database. |