Persistent storage implementations for key-value data.
interface BaseStore<K, V> {
mget(keys: K[]): Promise<(V | undefined)[]>;
mset(keyValuePairs: [K, V][]): Promise<void>;
mdelete(keys: K[]): Promise<void>;
yieldKeys(prefix?: string): AsyncGenerator<K>;
}In-memory key-value store (re-exported from @langchain/core/stores).
class InMemoryStore<T = any> implements BaseStore<string, T> {
constructor();
mget(keys: string[]): Promise<(T | undefined)[]>;
mset(keyValuePairs: [string, T][]): Promise<void>;
mdelete(keys: string[]): Promise<void>;
yieldKeys(prefix?: string): AsyncGenerator<string>;
}Examples:
import { InMemoryStore } from "langchain";
const store = new InMemoryStore<any>();
// Store values
await store.mset([
["user:1", { name: "Alice", age: 30 }],
["user:2", { name: "Bob", age: 25 }],
["config:theme", "dark"],
]);
// Retrieve
const [user1, theme] = await store.mget(["user:1", "config:theme"]);
// List keys
for await (const key of store.yieldKeys("user:")) {
console.log(key);
}
// Delete
await store.mdelete(["user:1"]);
// Use with agent
import { createAgent } from "langchain";
const sessionStore = new InMemoryStore();
const agent = createAgent({
model: "openai:gpt-4o",
tools: [searchTool],
store: sessionStore,
});File system implementation (Node.js only). Available via langchain/storage/file_system.
class LocalFileStore implements BaseStore<string, Uint8Array> {
constructor(config: { rootPath: string });
mget(keys: string[]): Promise<(Uint8Array | undefined)[]>;
mset(keyValuePairs: [string, Uint8Array][]): Promise<void>;
mdelete(keys: string[]): Promise<void>;
yieldKeys(prefix?: string): AsyncGenerator<string>;
}Examples:
import { LocalFileStore } from "langchain/storage/file_system";
const store = new LocalFileStore({ rootPath: "./my-data" });
// Store text
const textEncoder = new TextEncoder();
await store.mset([
["greeting", textEncoder.encode("Hello!")],
]);
// Retrieve text
const textDecoder = new TextDecoder();
const [greeting] = await store.mget(["greeting"]);
if (greeting) {
console.log(textDecoder.decode(greeting));
}
// Store binary
const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
await store.mset([["binary-key", binaryData]]);
// List keys
for await (const key of store.yieldKeys()) {
console.log(key);
}
// Use with agent
const memoryStore = new LocalFileStore({ rootPath: "./agent-memory" });
const agent = createAgent({
model: "openai:gpt-4o",
tools: [searchTool],
store: memoryStore,
});Store with encoding/decoding abstraction. Available via langchain/storage/encoder_backed.
class EncoderBackedStore<K, V, SerializedType = any> implements BaseStore<K, V> {
constructor(config: {
store: BaseStore<K, SerializedType>;
keyEncoder: (key: K) => string;
valueSerializer: (value: V) => SerializedType;
valueDeserializer: (value: SerializedType) => V;
});
mget(keys: K[]): Promise<(V | undefined)[]>;
mset(keyValuePairs: [K, V][]): Promise<void>;
mdelete(keys: K[]): Promise<void>;
yieldKeys(prefix?: string): AsyncGenerator<K>;
}Examples:
import { EncoderBackedStore } from "langchain/storage/encoder_backed";
import { LocalFileStore } from "langchain/storage/file_system";
const fileStore = new LocalFileStore({ rootPath: "./data" });
// JSON encoding
const jsonStore = new EncoderBackedStore({
store: fileStore,
keyEncoder: (key) => key,
valueSerializer: (value) => new TextEncoder().encode(JSON.stringify(value)),
valueDeserializer: (value) => JSON.parse(new TextDecoder().decode(value)),
});
await jsonStore.mset([
["user:1", { name: "Alice", age: 30 }],
]);
const [user1] = await jsonStore.mget(["user:1"]);
console.log(user1);
// Compressed storage
import { gzip, gunzip } from "zlib";
import { promisify } from "util";
const gzipAsync = promisify(gzip);
const gunzipAsync = promisify(gunzip);
const compressedStore = new EncoderBackedStore({
store: fileStore,
keyEncoder: (key) => key,
valueSerializer: async (value) => {
const json = JSON.stringify(value);
return await gzipAsync(Buffer.from(json));
},
valueDeserializer: async (value) => {
const decompressed = await gunzipAsync(value);
return JSON.parse(decompressed.toString());
},
});Helper to create document store from byte store.
function createDocumentStoreFromByteStore(
store: BaseStore<string, Uint8Array>
): EncoderBackedStore<string, Document, Uint8Array>;Example:
import { createDocumentStoreFromByteStore } from "langchain/storage/encoder_backed";
import { LocalFileStore } from "langchain/storage/file_system";
import { Document } from "langchain";
const fileStore = new LocalFileStore({ rootPath: "./documents" });
const docStore = createDocumentStoreFromByteStore(fileStore);
const doc = new Document({
pageContent: "This is document 1",
metadata: { source: "file1.txt", timestamp: Date.now() },
});
await docStore.mset([["doc:1", doc]]);
const [retrieved] = await docStore.mget(["doc:1"]);
console.log(retrieved.pageContent);
console.log(retrieved.metadata);Namespacing:
const store = new InMemoryStore();
// Use prefixes
await store.mset([
["user:123:profile", userData],
["user:123:settings", userSettings],
["session:abc:data", sessionData],
]);
// Retrieve by namespace
for await (const key of store.yieldKeys("user:123:")) {
const [value] = await store.mget([key]);
console.log(key, value);
}Hot/Cold Storage:
class CompositeStore {
constructor(
private hot: InMemoryStore,
private cold: LocalFileStore
) {}
async mget(keys: string[]) {
const hotResults = await this.hot.mget(keys);
const missingKeys = keys.filter((_, i) => !hotResults[i]);
if (missingKeys.length > 0) {
const coldResults = await this.cold.mget(missingKeys);
const toCache = missingKeys
.map((key, i) => [key, coldResults[i]] as [string, any])
.filter(([, value]) => value !== undefined);
await this.hot.mset(toCache);
}
return hotResults.map((value, i) =>
value ?? (await this.cold.mget([keys[i]]))[0]
);
}
async mset(pairs: [string, any][]) {
await Promise.all([
this.hot.mset(pairs),
this.cold.mset(pairs),
]);
}
}Cache Pattern:
const cache = new InMemoryStore<string>();
async function getCachedData(key: string): Promise<string> {
const [cached] = await cache.mget([key]);
if (cached) return cached;
const data = await fetchExpensiveData(key);
await cache.mset([[key, data]]);
return data;
}