Files
cleveragents-core/docs/reference/checkpointing.md
T
freemo 1f64a274e3
ci.yml / docs: document ACMS real retrieval logic and automatic checkpoint triggers (push) Failing after 0s
ci.yml / docs: document ACMS real retrieval logic and automatic checkpoint triggers (pull_request) Failing after 0s
docs: document ACMS real retrieval logic and automatic checkpoint triggers
- docs/reference/context_strategies.md: update Built-in Strategies table
  to document real retrieval logic for all 6 strategies (SimpleKeyword,
  SemanticEmbedding, BreadthDepthNavigator, ARCE, TemporalArchaeology,
  PlanDecisionContext); add note about v1 character-frequency embedding
  approximation; note SpecStrategyAdapter registration (#3500)
- docs/reference/checkpointing.md: add Automatic Checkpoint Triggers
  section documenting the 4 triggers (on_tool_write, on_tool_write_complete,
  on_subplan_spawn, on_error), configuration via core.checkpoints.auto_create_on,
  and wiring into ToolRunner/SubplanExecutionService/PlanExecutor (#3439)
2026-04-05 21:31:44 +00:00

7.2 KiB
Raw Blame History

Checkpointing and Rollback

Overview

CleverAgents supports checkpointing and rollback to allow operators to snapshot sandbox state during plan execution and restore it later. This is useful for recovering from mistakes, reverting tool side-effects, and supporting the decision-correction revert flow.

Concepts

Checkpoint

A Checkpoint is an immutable record of sandbox state at a point in time. Each checkpoint stores:

  • checkpoint_id — Unique ULID identifier
  • plan_id — The plan that owns this checkpoint
  • sandbox_ref — A reference to the sandbox state (e.g. git commit hash)
  • decision_id — Optional decision ULID this checkpoint is aligned to
  • checkpoint_type — One of pre_write, post_step, or manual
  • resource_id — Optional resource ULID association
  • filesystem_path — Relative path within the checkpoint directory
  • size_bytes — Size of the checkpoint data in bytes
  • created_at — Timestamp of creation (UTC)
  • metadata — Audit metadata including reason, source tool, and phase

Retention Policy

A CheckpointRetentionPolicy governs how many checkpoints a plan may keep. When auto_prune is enabled and the number of checkpoints exceeds max_checkpoints, the oldest interior checkpoints are automatically removed when a new one is created. The first (earliest) and most recent checkpoints are always preserved during pruning.

Defaults:

Field Default Range
max_checkpoints 50 1100
auto_prune true

Rollback

A rollback restores sandbox state to a previously captured checkpoint. The RollbackResult describes what changed:

  • restored_files_count — Number of files restored
  • changed_paths — Paths that were modified during rollback
  • from_checkpoint_id — The checkpoint that was restored

Guards

The rollback operation enforces two guards:

  1. Plan is applied — Once a plan reaches the applied terminal state, rollback is rejected with a BusinessRuleViolation.
  2. Sandbox is missing — If the sandbox has been cleaned up, rollback is rejected because there is nothing to restore.

Automatic Checkpoint Triggers (v3.8.0+)

The execution engine now supports four automatic checkpoint triggers, all configurable via core.checkpoints.auto_create_on (default: all enabled):

Trigger When Component
on_tool_write Before each write-tool execution ToolRunner
on_tool_write_complete After each write-tool execution ToolRunner
on_subplan_spawn Before first subplan execution attempt SubplanExecutionService
on_error When the Execute phase fails PlanExecutor

Configuration

[core.checkpoints]
auto_create_on = ["on_tool_write", "on_tool_write_complete", "on_subplan_spawn", "on_error"]

To disable a specific trigger, remove it from the list. To disable all automatic checkpoints:

[core.checkpoints]
auto_create_on = []

Wiring

The CheckpointService is injected as an optional parameter into:

  • ToolRunnercheckpoint_service and auto_checkpoint_triggers parameters
  • SubplanExecutionServicecheckpoint_service, auto_checkpoint_triggers, and parent_plan_id parameters
  • PlanExecutor — uses _is_auto_trigger_active() helper to check trigger config

When checkpoint_service is None, all automatic checkpointing is skipped (backward-compatible no-op).

CLI Usage

Create a checkpoint (programmatic)

Checkpoints are created automatically by the execution engine via the four triggers above, or manually via CheckpointService.create_checkpoint(). The CheckpointScope on each tool's capability declaration controls which tools trigger on_tool_write / on_tool_write_complete checkpoints.

Rollback to a checkpoint

agents plan rollback [--yes|-y] <plan_id> <checkpoint_id>

The --yes / -y flag skips the interactive confirmation prompt.

JSON output envelope (when using --format json):

{
  "rollback_summary": {
    "plan_id": "...",
    "from_checkpoint_id": "...",
    "restored_files_count": 3
  },
  "changes_reverted": ["path/to/file1.py", "path/to/file2.py"],
  "impact": {
    "files_affected": 3
  },
  "post_rollback_state": {
    "active_checkpoint": "...",
    "plan_id": "..."
  },
  "timing": {
    "elapsed_seconds": 0.042
  },
  "messages": ["Rollback completed successfully."]
}

Error Cases

Error Cause
Rollback blocked: plan is already applied Plan has reached terminal applied state
Rollback blocked: sandbox is missing Sandbox was cleaned up before rollback
Not found: checkpoint Checkpoint ID does not exist
Validation Error Checkpoint does not belong to the specified plan

Correction Service Integration

The CorrectionService accepts an optional checkpoint_service parameter (typed as CheckpointService | None). This is an integration point for a future milestone: once wired, the correction revert flow will delegate sandbox restoration to the checkpoint rollback mechanism, enabling reuse of the same rollback logic for both explicit CLI rollback and decision-correction reverts. The delegation is not yet active in the current implementation; execute_revert() performs BFS impact analysis and marks decisions as reverted but does not invoke checkpoint_service.rollback_to_checkpoint().

Database Schema

The checkpoint_metadata table stores checkpoint metadata:

Column Type Description
checkpoint_id STRING(26) PK ULID primary key
plan_id STRING(26) FK References v3_plans.plan_id
decision_id STRING(26) Optional decision alignment
checkpoint_type TEXT pre_write, post_step, manual
resource_id STRING(26) Optional resource association
sandbox_ref TEXT Git commit hash or patch reference
filesystem_path TEXT Relative path within checkpoint dir
size_bytes INTEGER Size of checkpoint data in bytes
created_at STRING(30) ISO-8601 timestamp
metadata_json TEXT JSON: reason, source_tool, phase

Indexes: idx_checkpoints_plan, ix_checkpoint_metadata_created_at.

Dependency Injection

The CheckpointService is registered in the DI container (container.py) and backed by a CheckpointRepository that uses the session-factory pattern (ADR-007). The CLI rollback command obtains the service from the container via get_container().checkpoint_service().

The UnitOfWorkContext also exposes a checkpoints property for cross-repository atomicity within a single transaction.

Metadata for Auditability

Each checkpoint stores structured metadata to support audit trails:

  • reason — Why the checkpoint was created (e.g. "pre-execution")
  • source_tool — Which tool triggered the checkpoint (e.g. "lint-check")
  • phase — Which plan phase was active (e.g. "execute")
  • extra — Arbitrary key-value pairs for extension