Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

File Persistence

Synaptic provides file-system backed persistence through FileStore (the Store trait) and StoreCheckpointer (the Checkpointer trait backed by any Store).

FileStore

FileStore implements the Store trait with a directory-based layout. Each item is stored as a JSON file.

Feature flag: store-filesystem

Layout

{root}/{namespace...}/{key}.json

For example, store.put(&["users", "prefs"], "theme", json!("dark")) writes to {root}/users/prefs/theme.json.

Basic Usage

use synaptic::store::FileStore;

let store = FileStore::new("/tmp/my-store");

// Write
store.put(&["app", "settings"], "theme", json!("dark")).await?;

// Read
let item = store.get(&["app", "settings"], "theme").await?;

// Search (substring matching on key and value)
let results = store.search(&["app"], Some("theme"), 10).await?;

// Delete
store.delete(&["app", "settings"], "theme").await?;

// List namespaces
let namespaces = store.list_namespaces(&["app"]).await?;

With Embeddings

FileStore supports optional embeddings for semantic search, just like InMemoryStore.

use synaptic::store::FileStore;
use synaptic::openai::OpenAiEmbeddings;

let embeddings = Arc::new(OpenAiEmbeddings::new("text-embedding-3-small"));
let store = FileStore::new("/tmp/my-store").with_embeddings(embeddings);

StoreCheckpointer

StoreCheckpointer implements the Checkpointer trait backed by any Store. This replaces the old FileSaver with a unified, backend-agnostic approach -- the same checkpointer works with InMemoryStore, FileStore, RedisStore, or any other Store implementation.

Feature flag: store-filesystem (when using FileStore as the backing store)

How It Works

Checkpoints are stored at namespace ["checkpoints", "{thread_id}"], with the checkpoint ID as the key. Checkpoint IDs are timestamp-hex based, so alphabetical order corresponds to chronological order.

When backed by FileStore, the on-disk layout is:

{root}/checkpoints/{thread_id}/{checkpoint_id}.json

Usage

use std::sync::Arc;
use synaptic::graph::{StoreCheckpointer, CheckpointConfig};
use synaptic::store::FileStore;

let store = Arc::new(FileStore::new("/tmp/my-data"));
let checkpointer = StoreCheckpointer::new(store);

// Use with a compiled graph
let graph = builder.compile_with_checkpointer(Arc::new(checkpointer))?;

let config = CheckpointConfig::new("thread-1");
let result = graph.invoke_with_config(state, config).await?;

Manual Checkpoint Operations

use synaptic::graph::{Checkpointer, CheckpointConfig};

let config = CheckpointConfig::new("thread-1");

// Get the latest checkpoint
let latest = checkpointer.get(&config).await?;

// List all checkpoints for a thread
let all = checkpointer.list(&config).await?;

Unified Namespace

Because StoreCheckpointer is backed by a regular Store, the same FileStore instance can handle memory, checkpoints, and sessions simultaneously. Each subsystem uses a distinct namespace prefix:

use std::sync::Arc;
use synaptic::store::FileStore;
use synaptic::graph::StoreCheckpointer;

let store = Arc::new(FileStore::new("/tmp/my-data"));

// Checkpoints go to {root}/checkpoints/{thread_id}/{id}.json
let checkpointer = StoreCheckpointer::new(store.clone());

// Application data goes to {root}/app/settings/{key}.json
store.put(&["app", "settings"], "theme", json!("dark")).await?;

This single-store approach eliminates the need for separate directory configurations and keeps all persistent state in one place.

Cargo.toml

[dependencies]
synaptic = { version = "0.4", features = ["store-filesystem", "graph"] }

Migrating from FileSaver

If you previously used FileSaver from the graph-filesystem feature, switch to StoreCheckpointer backed by FileStore:

BeforeAfter
use synaptic::graph::FileSaveruse synaptic::graph::StoreCheckpointer
FileSaver::new("/tmp/checkpoints")StoreCheckpointer::new(Arc::new(FileStore::new("/tmp/data")))
Feature: graph-filesystemFeature: store-filesystem + graph

The checkpoint data format is the same, so existing checkpoint files remain compatible.

FileStore and StoreCheckpointer are suitable for single-process deployments. For distributed systems, use database-backed Store implementations such as RedisStore.