Documentation Index
Fetch the complete documentation index at: https://mintlify.com/vercel/chat/llms.txt
Use this file to discover all available pages before exploring further.
The StateAdapter interface defines the contract for managing persistent state in Chat SDK. State adapters handle thread subscriptions, distributed locking, and caching.
Built-in Implementations
Chat SDK provides three state adapter implementations:
Interface
interface StateAdapter {
connect(): Promise<void>;
disconnect(): Promise<void>;
// Subscriptions
subscribe(threadId: string): Promise<void>;
unsubscribe(threadId: string): Promise<void>;
isSubscribed(threadId: string): Promise<boolean>;
// Locking
acquireLock(threadId: string, ttlMs: number): Promise<Lock | null>;
releaseLock(lock: Lock): Promise<void>;
extendLock(lock: Lock, ttlMs: number): Promise<boolean>;
// Caching
get<T = unknown>(key: string): Promise<T | null>;
set<T = unknown>(key: string, value: T, ttlMs?: number): Promise<void>;
delete(key: string): Promise<void>;
}
interface Lock {
threadId: string;
token: string;
expiresAt: number;
}
Methods
connect()
Establish connection to the state backend.
Called automatically by Chat SDK during initialization.
disconnect()
Close connection to the state backend.
await state.disconnect();
Called automatically by Chat SDK during shutdown.
subscribe()
Subscribe to a thread to receive all future messages.
The thread ID to subscribe to
await state.subscribe("slack:C123ABC:1234567890.123456");
Subscriptions persist across restarts and are stored indefinitely until explicitly unsubscribed.
unsubscribe()
Unsubscribe from a thread.
The thread ID to unsubscribe from
await state.unsubscribe("slack:C123ABC:1234567890.123456");
isSubscribed()
Check if currently subscribed to a thread.
Whether the thread is subscribed
const subscribed = await state.isSubscribed("slack:C123ABC:1234567890.123456");
acquireLock()
Acquire a distributed lock on a thread with a TTL.
Time-to-live in milliseconds
Lock object if acquired, null if already locked
const lock = await state.acquireLock(threadId, 5000); // 5 second lock
if (lock) {
try {
// Process message with exclusive access
} finally {
await state.releaseLock(lock);
}
}
Locks prevent concurrent processing of messages in the same thread across multiple instances.
releaseLock()
Release a previously acquired lock.
The lock object to release
await state.releaseLock(lock);
extendLock()
Extend the TTL of an existing lock.
The lock object to extend
New time-to-live in milliseconds
Whether the lock was successfully extended
const extended = await state.extendLock(lock, 5000);
if (!extended) {
// Lock expired or was released
}
get()
Retrieve a cached value by key.
Cached value or null if not found
const data = await state.get<{ userId: string }>("user:123");
set()
Store a value in cache with optional TTL.
Optional time-to-live in milliseconds
await state.set("user:123", { userId: "U123", name: "Alice" }, 3600000); // 1 hour
delete()
Delete a cached value by key.
await state.delete("user:123");
Implementing a Custom Adapter
To create a custom state adapter:
import type { StateAdapter, Lock } from "chat";
export class MyStateAdapter implements StateAdapter {
async connect(): Promise<void> {
// Connect to your backend
}
async disconnect(): Promise<void> {
// Close connections
}
async subscribe(threadId: string): Promise<void> {
// Store subscription
}
async unsubscribe(threadId: string): Promise<void> {
// Remove subscription
}
async isSubscribed(threadId: string): Promise<boolean> {
// Check if subscribed
return false;
}
async acquireLock(threadId: string, ttlMs: number): Promise<Lock | null> {
// Implement distributed locking
return null;
}
async releaseLock(lock: Lock): Promise<void> {
// Release the lock
}
async extendLock(lock: Lock, ttlMs: number): Promise<boolean> {
// Extend lock TTL
return false;
}
async get<T>(key: string): Promise<T | null> {
// Retrieve cached value
return null;
}
async set<T>(key: string, value: T, ttlMs?: number): Promise<void> {
// Store cached value
}
async delete(key: string): Promise<void> {
// Delete cached value
}
}
See Also