Redis checkpoint and store implementation for LangGraph.
This package provides Redis-based implementations for:
npm install @langchain/langgraph-checkpoint-redis
This library requires Redis with the following modules:
If you're using Redis 8.0 or higher, both RedisJSON and RediSearch modules are included by default.
For Redis versions lower than 8.0, you'll need to:
import { RedisSaver } from "@langchain/langgraph-checkpoint-redis";
const checkpointer = await RedisSaver.fromUrl(
"redis://localhost:6379",
{
defaultTTL: 60, // TTL in minutes
refreshOnRead: true
}
);
// Indices are automatically created by fromUrl()
// Use with your graph
const config = {configurable: {thread_id: "1"}};
// Metadata must include required fields
const metadata = {
source: "update", // "update" | "input" | "loop" | "fork"
step: 0,
parents: {}
};
await checkpointer.put(config, checkpoint, metadata, {});
const loaded = await checkpointer.get(config);
The ShallowRedisSaver
is a memory-optimized variant that only keeps the latest checkpoint per thread:
import { ShallowRedisSaver } from "@langchain/langgraph-checkpoint-redis/shallow";
// Create a shallow saver that only keeps the latest checkpoint
const shallowSaver = await ShallowRedisSaver.fromUrl("redis://localhost:6379");
// Use it the same way as RedisSaver
const config = {
configurable: {
thread_id: "my-thread",
checkpoint_ns: "my-namespace"
}
};
const metadata = {
source: "update",
step: 0,
parents: {}
};
await shallowSaver.put(config, checkpoint, metadata, versions);
// Only the latest checkpoint is kept - older ones are automatically cleaned up
const latest = await shallowSaver.getTuple(config);
Key differences from RedisSaver:
The RedisStore
provides a key-value store with optional vector search capabilities:
import { RedisStore } from "@langchain/langgraph-checkpoint-redis/store";
// Basic key-value store
const store = await RedisStore.fromConnString("redis://localhost:6379");
// Store with vector search
const vectorStore = await RedisStore.fromConnString("redis://localhost:6379", {
index: {
dims: 1536, // Embedding dimensions
embed: embeddings, // Your embeddings instance
distanceType: "cosine", // or "l2", "ip"
fields: ["text"], // Fields to embed
},
ttl: {
defaultTTL: 60, // TTL in minutes
refreshOnRead: true,
}
});
// Put and get items
await store.put(["namespace", "nested"], "key1", {text: "Hello world"});
const item = await store.get(["namespace", "nested"], "key1");
// Search with namespace filtering
const results = await store.search(["namespace"], {
filter: {category: "docs"},
limit: 10,
});
// Vector search
const semanticResults = await vectorStore.search(["namespace"], {
query: "semantic search query",
filter: {type: "article"},
limit: 5,
});
// Batch operations
const ops = [
{type: "get", namespace: ["ns"], key: "key1"},
{type: "put", namespace: ["ns"], key: "key2", value: {data: "value"}},
{type: "search", namespacePrefix: ["ns"], limit: 10},
{type: "list_namespaces", matchConditions: [{matchType: "prefix", path: ["ns"]}], limit: 10},
];
const results = await store.batch(ops);
Both checkpoint savers and stores support Time-To-Live (TTL) functionality:
const ttlConfig = {
defaultTTL: 60, // Default TTL in minutes
refreshOnRead: true, // Refresh TTL when items are read
};
const checkpointer = await RedisSaver.fromUrl("redis://localhost:6379", ttlConfig);
# Run tests (uses TestContainers)
yarn test
# Run tests in watch mode
yarn test:watch
# Run integration tests
yarn test:int
MIT