Skip to content
Back to skills

2956 Checkpointing A0ad9f8e

ASecurity

pydantic-deep supports conversation checkpointing — saving snapshots of conversation state at key points so the agent (or user) can **rewind** to any checkpoint or **fork** from a checkpoint into a new session.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmentpythonbackend

Works with

  • claude code

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2956-checkpointing_a0ad9f8e --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2956 Checkpointing A0ad9f8e?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2956 Checkpointing A0ad9f8e
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2956-checkpointing-a0ad9f8e/badge)](https://www.skillsdirectory.com/skills/tools-only-2956-checkpointing-a0ad9f8e)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Checkpointing

pydantic-deep supports conversation checkpointing — saving snapshots of conversation state at key points so the agent (or user) can **rewind** to any checkpoint or **fork** from a checkpoint into a new session.

## Quick Start

```python
from pydantic_deep import create_deep_agent, InMemoryCheckpointStore

store = InMemoryCheckpointStore()
agent = create_deep_agent(
    include_checkpoints=True,
    checkpoint_store=store,
    checkpoint_frequency="every_tool",  # auto-save after each tool call
)
```

The agent now has three tools:

| Tool | Description |
|------|-------------|
| `save_checkpoint` | Label the most recent auto-checkpoint with a custom name |
| `list_checkpoints` | Show all saved checkpoints with labels and metadata |
| `rewind_to` | Rewind conversation to a checkpoint (raises `RewindRequested`) |

## Configuration

### `create_deep_agent()` Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `include_checkpoints` | `bool` | `False` | Enable checkpointing |
| `checkpoint_frequency` | `str` | `"every_tool"` | When to auto-save: `"every_tool"`, `"every_turn"`, or `"manual_only"` |
| `max_checkpoints` | `int` | `20` | Maximum checkpoints to keep (oldest pruned first) |
| `checkpoint_store` | `CheckpointStore` | `InMemoryCheckpointStore()` | Storage backend for checkpoints |

### Checkpoint Frequencies

=== "every_tool"
    Saves a checkpoint after each tool call. Provides the finest granularity for rewinding.

    ```python
    agent = create_deep_agent(
        include_checkpoints=True,
        checkpoint_frequency="every_tool",
    )
    ```

=== "every_turn"
    Saves a checkpoint before each model request (i.e. at the start of each turn).

    ```python
    agent = create_deep_agent(
        include_checkpoints=True,
        checkpoint_frequency="every_turn",
    )
    ```

=== "manual_only"
    No auto-checkpoints. The agent must explicitly call `save_checkpoint`.

    ```python
    agent = create_deep_agent(
        include_checkpoints=True,
        checkpoint_frequency="manual_only",
    )
    ```

## Checkpoint Stores

### InMemoryCheckpointStore

Default store. Checkpoints are kept in a Python dict — fast, but lost when the process exits.

```python
from pydantic_deep import InMemoryCheckpointStore

store = InMemoryCheckpointStore()
```

### FileCheckpointStore

Persists checkpoints as JSON files on disk. Each checkpoint is a separate file in the given directory.

```python
from pydantic_deep import FileCheckpointStore

store = FileCheckpointStore("/path/to/checkpoints")
```

Messages are serialized using pydantic-ai's `ModelMessagesTypeAdapter`, so all message types (text, tool calls, tool results) are preserved.

### Custom Store

Implement the [`CheckpointStore`][pydantic_deep.toolsets.checkpointing.CheckpointStore] protocol:

```python
from pydantic_deep.toolsets.checkpointing import Checkpoint, CheckpointStore

class RedisCheckpointStore:
    async def save(self, checkpoint: Checkpoint) -> None: ...
    async def get(self, checkpoint_id: str) -> Checkpoint | None: ...
    async def get_by_label(self, label: str) -> Checkpoint | None: ...
    async def list_all(self) -> list[Checkpoint]: ...
    async def remove(self, checkpoint_id: str) -> bool: ...
    async def remove_oldest(self) -> bool: ...
    async def count(self) -> int: ...
    async def clear(self) -> None: ...
```

## Rewinding

When the agent calls `rewind_to`, a [`RewindRequested`][pydantic_deep.toolsets.checkpointing.RewindRequested] exception propagates out of `agent.run()`. Your application loop catches it and restores the conversation:

```python
from pydantic_deep import create_deep_agent, DeepAgentDeps, RewindRequested
from pydantic_ai_backends import StateBackend

agent = create_deep_agent(include_checkpoints=True)
deps = DeepAgentDeps(backend=StateBackend())
message_history = []

while True:
    user_input = input("> ")
    try:
        result = await agent.run(
            user_input,
            deps=deps,
            message_history=message_history,
        )
        message_history = result.all_messages()
        print(result.output)
    except RewindRequested as e:
        print(f"Rewinding to '{e.label}'...")
        message_history = e.messages
```

## Session Forking

Fork creates a new session from a checkpoint — the original session stays unchanged.

```python
from pydantic_deep import fork_from_checkpoint, InMemoryCheckpointStore

store = InMemoryCheckpointStore()
# ... after some conversation with checkpoints saved ...

# Fork from a specific checkpoint
messages = await fork_from_checkpoint(store, checkpoint_id="abc123")

# Start a new session with the forked history
new_result = await agent.run(
    "Try a different approach",
    deps=new_deps,
    message_history=messages,
)
```

## Per-Session Stores

For multi-user applications, set `checkpoint_store` on deps at runtime:

```python
from pydantic_deep import DeepAgentDeps, FileCheckpointStore

# Each user gets their own checkpoint store
deps = DeepAgentDeps(
    backend=backend,
    checkpoint_store=FileCheckpointStore(f"/checkpoints/{user_id}"),
)
```

The middleware resolves the store from `deps.checkpoint_store` first, falling back to the store passed at agent creation time.

!!! warning "Multi-User Applications"
    Always create a fresh `CheckpointStore` per user session. A shared
    `InMemoryCheckpointStore` means all users see each other's checkpoints.
    See [Multi-User Guide](multi-user.md).

## Components

| Component | Description |
|-----------|-------------|
| [`Checkpoint`][pydantic_deep.toolsets.checkpointing.Checkpoint] | Immutable snapshot: id, label, turn, messages, metadata |
| [`CheckpointStore`][pydantic_deep.toolsets.checkpointing.CheckpointStore] | Protocol for storage backends |
| [`InMemoryCheckpointStore`][pydantic_deep.toolsets.checkpointing.InMemoryCheckpointStore] | Default in-memory store |
| [`FileCheckpointStore`][pydantic_deep.toolsets.checkpointing.FileCheckpointStore] | Persistent JSON file store |
| [`CheckpointMiddleware`][pydantic_deep.toolsets.checkpointing.CheckpointMiddleware] | Auto-save middleware |
| [`CheckpointToolset`][pydantic_deep.toolsets.checkpointing.CheckpointToolset] | Agent tools (save, list, rewind) |
| [`RewindRequested`][pydantic_deep.toolsets.checkpointing.RewindRequested] | Exception for app-level rewind |
| [`fork_from_checkpoint`][pydantic_deep.toolsets.checkpointing.fork_from_checkpoint] | Utility for session forking |

## Next Steps

- [Teams](teams.md) — Multi-agent collaboration with shared state
- [Hooks](hooks.md) — Claude Code-style lifecycle hooks
- [Human-in-the-Loop](human-in-the-loop.md) — Approval workflows

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.