Checkpoint Plugin
Overview
The @tokenring-ai/checkpoint plugin provides persistent state management for agents within the Token Ring Agent framework. It enables agents to save snapshots of their current state and restore them later, supporting workflow interruption, experimentation, and session recovery. The plugin includes interactive chat commands, auto-checkpointing hooks, and RPC endpoints for programmatic access to checkpoint operations.
Key Features
- State Snapshots: Save complete agent state including chat history, command history, hooks, events, and cost tracking
- Pluggable Storage: Custom storage backends for checkpoint persistence via
setCheckpointProvider - Interactive Browsing: Tree-based UI for exploring and restoring checkpoints
- Auto-Checkpointing: Automatic checkpoint creation after agent input processing
- Session History: Browse checkpoints grouped by agent session
- Named Checkpoints: Label checkpoints for easy identification
- RPC Endpoints: Programmatic access to checkpoint operations via JSON-RPC
- Agent Launching: Create new agents from saved checkpoints
- Configuration Validation: Zod schema for configuration validation
Core Components
AgentCheckpointService
The main service for checkpoint operations. Automatically installed when the plugin is registered with the Token Ring app.
Key Methods:
// Set the checkpoint storage provider
setCheckpointProvider(provider: AgentCheckpointProvider): void
// Save agent state to a checkpoint
saveAgentCheckpoint(name: string, agent: Agent): Promise<string>
// Restore agent from checkpoint
restoreAgentCheckpoint(id: string, agent: Agent): Promise<void>
// List all available checkpoints
listCheckpoints(): Promise<AgentCheckpointListItem[]>
Example Usage:
import { AgentCheckpointService } from '@tokenring-ai/checkpoint';
import { Agent } from '@tokenring-ai/agent';
// Create a memory provider
const memoryProvider = new MemoryProvider();
const checkpointService = agent.requireServiceByType(AgentCheckpointService);
checkpointService.setCheckpointProvider(memoryProvider);
// Save checkpoint
const checkpointId = await checkpointService.saveAgentCheckpoint('Before Feature Implementation', agent);
// Restore checkpoint
await checkpointService.restoreAgentCheckpoint(checkpointId, agent);
// List all checkpoints
const checkpoints = await checkpointService.listCheckpoints();
AgentCheckpointProvider Interface
The storage provider interface that users must implement for custom storage backends.
export interface AgentCheckpointProvider {
// Optional startup method
start?(): Promise<void>;
// Save checkpoint and return its ID
storeCheckpoint(data: NamedAgentCheckpoint): Promise<string>;
// Retrieve checkpoint by ID
retrieveCheckpoint(id: string): Promise<StoredAgentCheckpoint | null>;
// List all stored checkpoints (without state data)
listCheckpoints(): Promise<AgentCheckpointListItem[]>;
}
Data Structures:
// Checkpoint with name
export interface NamedAgentCheckpoint extends AgentCheckpointData {
name: string;
}
// Checkpoint with storage ID
export interface StoredAgentCheckpoint extends NamedAgentCheckpoint {
id: string;
}
// Checkpoint listing item (minimal info)
export type AgentCheckpointListItem = Omit<StoredAgentCheckpoint, "state" | "config">;
Checkpoint State Contains:
AgentEventState- Agent event state (busyWith, events, idle)CommandHistoryState- Command historyCostTrackingState- Cost tracking informationHooksState- Enabled hooks- Additional agent-specific state data
Configuration
The checkpoint plugin requires configuration for the checkpoint storage provider. The configuration is defined under the checkpoint key in your application's configuration file (e.g., .tokenring/coder-config.mjs).
Configuration Schema:
import { z } from "zod";
export const CheckpointConfigSchema = z.object({
provider: z.looseObject({
type: z.string()
})
});
Example Configuration:
export default {
checkpoint: {
provider: {
type: "memory",
// Additional provider-specific properties can be included here
}
}
};
Important Note:
The checkpoint plugin does not automatically create storage providers based on configuration. Users must implement their own storage providers by implementing the AgentCheckpointProvider interface and set it using the setCheckpointProvider method of the AgentCheckpointService.
Storage Provider Implementations
The checkpoint plugin defines the AgentCheckpointProvider interface, but does not include built-in storage providers. Users must implement their own storage providers.
Example Implementation: Memory Provider
import type { AgentCheckpointProvider, NamedAgentCheckpoint, StoredAgentCheckpoint, AgentCheckpointListItem } from '@tokenring-ai/checkpoint';
class MemoryProvider implements AgentCheckpointProvider {
private checkpoints = new Map<string, StoredAgentCheckpoint>();
async storeCheckpoint(data: NamedAgentCheckpoint): Promise<string> {
const id = crypto.randomUUID();
const checkpoint = {
...data,
id,
};
this.checkpoints.set(id, checkpoint);
return id;
}
async retrieveCheckpoint(id: string): Promise<StoredAgentCheckpoint | null> {
return this.checkpoints.get(id) || null;
}
async listCheckpoints(): Promise<AgentCheckpointListItem[]> {
return Array.from(this.checkpoints.values()).map(cp => ({
id: cp.id,
name: cp.name,
agentId: cp.agentId,
createdAt: cp.createdAt
}));
}
}
Database Provider Example (conceptual):
class DatabaseProvider implements AgentCheckpointProvider {
constructor(private connectionString: string) {}
async storeCheckpoint(data: NamedAgentCheckpoint): Promise<string> {
// Save to database and return ID
}
async retrieveCheckpoint(id: string): Promise<StoredAgentCheckpoint | null> {
// Retrieve from database
}
async listCheckpoints(): Promise<AgentCheckpointListItem[]> {
// Query database for checkpoint listings
}
}
Commands
/checkpoint
Manage agent checkpoints - create, restore, or browse with interactive tree selection.
Syntax:
/checkpoint [action] [args...]
Actions:
create [label]
Create a checkpoint of the current agent state with an optional label.
/checkpoint create
/checkpoint create "My Important Fix"
restore <id>
Restore agent state from a specific checkpoint by ID.
/checkpoint restore abc123def456
list (default)
Show interactive tree selection of all checkpoints, grouped by date. Select one to restore.
/checkpoint list
/checkpoint # Same as list
Examples:
/checkpoint create # Create with default label
/checkpoint create "Bug Fix" # Create with custom label
/checkpoint restore xyz789 # Restore by ID
/checkpoint list # Browse and restore interactively
Output:
- Shows checkpoint ID when created
- Displays grouped checkpoints by date with timestamps
- Indicates most recent checkpoints first
- Interactive tree selection for easy navigation
/history
Browse and view checkpoint history grouped by agent session.
Syntax:
/history
Shows an interactive tree selection where checkpoints are grouped by:
- Agent ID (session)
- Individual checkpoints within each agent (sorted by creation time, newest first)
Display Information:
For each selected checkpoint:
- Name and creation timestamp
- Agent ID
- Full checkpoint details including state data (when retrievable)
The /history command displays detailed checkpoint information, organized by agent sessions. It shows timestamps, checkpoint names, and allows viewing the full state of each checkpoint including agent-specific state data.
Hooks
autoCheckpoint
Automatically creates a checkpoint after each agent input is processed. Enabled by default when the plugin is installed.
Hook Points:
afterAgentInputComplete- Triggered after agent successfully processes inputbeforeChatCompletion- Triggered before chat response is generated
Behavior:
- Uses the input message as the checkpoint label
- Runs silently without interrupting workflow
- Can be disabled via agent hook management
Configuration:
// Disable auto-checkpointing
agent.hooks.disableItems("@tokenring-ai/checkpoint/autoCheckpoint");
// Re-enable auto-checkpointing
agent.hooks.enableItems("@tokenring-ai/checkpoint/autoCheckpoint");
RPC API
The plugin provides JSON-RPC endpoints for remote checkpoint operations.
Endpoint: /rpc/checkpoint
listCheckpoints
Query all available checkpoints without state data.
Request:
{
"method": "listCheckpoints",
"params": {}
}
Response:
{
"result": [
{
"id": "checkpoint-123",
"name": "Before Feature Implementation",
"agentId": "agent-456",
"createdAt": 1640995200000
}
]
}
getCheckpoint
Retrieve a specific checkpoint with full state data.
Request:
{
"method": "getCheckpoint",
"params": {
"id": "checkpoint-123"
}
}
Response:
{
"result": {
"id": "checkpoint-123",
"name": "Before Feature Implementation",
"agentId": "agent-456",
"createdAt": 1640995200000,
"state": {
"AgentEventState": {},
"CommandHistoryState": {},
"CostTrackingState": {},
"HooksState": {}
}
}
}
launchAgentFromCheckpoint
Create a new agent from a checkpoint.
Request:
{
"method": "launchAgentFromCheckpoint",
"params": {
"checkpointId": "checkpoint-123",
"headless": false
}
}
Response:
{
"result": {
"agentId": "agent-789",
"agentName": "Restored Agent",
"agentType": "default"
}
}
Usage Examples
Basic Checkpoint Workflow
import { AgentCheckpointService } from '@tokenring-ai/checkpoint';
import { Agent } from '@tokenring-ai/agent';
// Create a memory provider
const memoryProvider = new MemoryProvider();
const checkpointService = agent.requireServiceByType(AgentCheckpointService);
checkpointService.setCheckpointProvider(memoryProvider);
// Save checkpoint
const id1 = await checkpointService.saveAgentCheckpoint('Before Changes', agent);
// Make changes to agent state
// ... agent does work ...
// Save another checkpoint
const id2 = await checkpointService.saveAgentCheckpoint('After Changes', agent);
// List all checkpoints
const all = await checkpointService.listCheckpoints();
console.log(`Total checkpoints: ${all.length}`);
// Restore from earlier checkpoint
await checkpointService.restoreAgentCheckpoint(id1, agent);
Custom Storage Provider
import type { AgentCheckpointProvider, NamedAgentCheckpoint, StoredAgentCheckpoint, AgentCheckpointListItem } from '@tokenring-ai/checkpoint';
class CustomProvider implements AgentCheckpointProvider {
private checkpoints = new Map<string, StoredAgentCheckpoint>();
async storeCheckpoint(data: NamedAgentCheckpoint): Promise<string> {
const id = crypto.randomUUID();
this.checkpoints.set(id, {
...data,
id,
});
return id;
}
async retrieveCheckpoint(id: string): Promise<StoredAgentCheckpoint | null> {
return this.checkpoints.get(id) || null;
}
async listCheckpoints(): Promise<AgentCheckpointListItem[]> {
return Array.from(this.checkpoints.values()).map(cp => ({
id: cp.id,
name: cp.name,
agentId: cp.agentId,
createdAt: cp.createdAt
}));
}
}
// Register provider
const checkpointService = agent.requireServiceByType(AgentCheckpointService);
checkpointService.setCheckpointProvider(new CustomProvider());
Conditional Checkpointing
// Disable auto-checkpointing for certain operations
agent.hooks.disableItems("@tokenring-ai/checkpoint/autoCheckpoint");
// Do work without automatic checkpoints
// ...
// Re-enable auto-checkpointing
agent.hooks.enableItems("@tokenring-ai/checkpoint/autoCheckpoint");
// Save a specific checkpoint manually
const id = await service.saveAgentCheckpoint('Critical State', agent);
RPC Usage
// Using the RPC endpoint directly
const response = await fetch('/rpc/checkpoint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
method: 'listCheckpoints',
params: {}
})
});
const checkpoints = await response.json();
Package Integration
Installation with TokenRingApp
The checkpoint plugin is installed by adding it to your Token Ring application:
import checkpointPackage from '@tokenring-ai/checkpoint';
const app = new TokenRingApp();
app.registerPackages([checkpointPackage]);
After installation, configure the storage provider:
const checkpointService = app.requireService(AgentCheckpointService);
checkpointService.setCheckpointProvider(new MemoryProvider());
Automatically Provides:
- Chat commands (
/checkpoint,/history) - Auto-checkpoint hook
AgentCheckpointServiceservice instance- RPC endpoints for remote operations
- Configuration schema validation
Plugin Architecture
The plugin uses a modular architecture for automatic integration:
import {AgentCommandService, AgentLifecycleService} from "@tokenring-ai/agent";
import {TokenRingPlugin} from "@tokenring-ai/app";
import {RpcService} from "@tokenring-ai/rpc";
import {WebHostService} from "@tokenring-ai/web-host";
import JsonRpcResource from "@tokenring-ai/web-host/JsonRpcResource";
import {z} from "zod";
import AgentCheckpointService from "./AgentCheckpointService.ts";
import chatCommands from "./chatCommands.ts";
import hooks from "./hooks.ts";
import {CheckpointConfigSchema} from "./schema.ts";
import packageJSON from "./package.json" with {type: "json"};
import checkpointRPC from "./rpc/checkpoint.ts";
const packageConfigSchema = z.object({
checkpoint: CheckpointConfigSchema
});
export default {
name: packageJSON.name,
version: packageJSON.version,
description: packageJSON.description,
install(app, config) {
const checkpointService = new AgentCheckpointService(config.checkpoint);
app.addServices(checkpointService);
app.waitForService(AgentCommandService, agentCommandService =>
agentCommandService.addAgentCommands(chatCommands)
);
app.waitForService(AgentLifecycleService, lifecycleService =>
lifecycleService.addHooks(packageJSON.name, hooks)
);
app.waitForService(RpcService, rpcService => {
rpcService.registerEndpoint(checkpointRPC);
});
},
config: packageConfigSchema
} satisfies TokenRingPlugin<typeof packageConfigSchema>;
Best Practices
- Regular Checkpoints: Use auto-checkpointing for frequent automatic saves
- Named Checkpoints: Create named checkpoints at logical decision points
- Storage Selection: Implement appropriate provider for your use case:
- Memory for testing/experimentation
- Database for production deployments
- Cleanup: Periodically list and remove old checkpoints to manage storage
- Error Handling: Always catch restore errors for graceful degradation
- RPC Usage: Use RPC endpoints for remote checkpoint management and agent spawning
Error Handling
try {
await checkpointService.restoreAgentCheckpoint(id, agent);
agent.infoMessage(`Checkpoint ${id} restored`);
} catch (error) {
agent.errorMessage(`Failed to restore checkpoint: ${error}`);
// Agent state remains unchanged
}
Testing
vitest run # Run tests
bun run test:watch # Watch mode
bun run test:coverage # Coverage report
Package Details
- Name: @tokenring-ai/checkpoint
- Version: 0.2.0
- License: MIT
- Dependencies: @tokenring-ai/app, @tokenring-ai/chat, @tokenring-ai/agent, @tokenring-ai/utility, @tokenring-ai/rpc, @tokenring-ai/web-host
- Dev Dependencies: typescript, vitest
License
MIT License - see LICENSE file for details.
Implementation Note
The checkpoint plugin does not include built-in storage providers. Users must implement their own storage providers by implementing the AgentCheckpointProvider interface and set it using the setCheckpointProvider method of the AgentCheckpointService.