Storage โ
createStorage() gives you a typed, JSON-serializing key-value store on top of a pluggable StorageAdapter. Use it for durable run state, cached results, generated outputs, or any application data that should survive beyond a single agent run.
ts
import { createStorage } from 'confused-ai';Quick start โ
ts
import { createStorage } from 'confused-ai';
// In-memory (dev / testing)
const store = createStorage();
await store.set('user:alice', { name: 'Alice', plan: 'pro' });
const user = await store.get<{ name: string; plan: string }>('user:alice');
console.log(user?.plan); // 'pro'
await store.has('user:alice'); // true
await store.list('user:'); // ['user:alice']
await store.delete('user:alice');Drivers โ
In-memory (default) โ
Data lives only for the process lifetime. No config needed โ ideal for development and testing.
ts
const store = createStorage();
// equivalent to:
const store2 = createStorage({ driver: 'memory' });File system โ
Persists JSON files under a base directory. Suitable for local single-node deployments.
ts
const store = createStorage({
driver: 'file',
basePath: './data', // directory created automatically
});
await store.set('config', { theme: 'dark' });
// writes to ./data/config.jsonCustom adapter (S3, Redis, R2, etc.) โ
Implement the StorageAdapter interface to use any backend:
ts
import type { StorageAdapter } from 'confused-ai';
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
class S3StorageAdapter implements StorageAdapter {
private s3 = new S3Client({});
private bucket = process.env.S3_BUCKET!;
async get(key: string): Promise<string | undefined> {
try {
const res = await this.s3.send(new GetObjectCommand({ Bucket: this.bucket, Key: key }));
return res.Body?.transformToString();
} catch { return undefined; }
}
async set(key: string, value: string, ttl?: number): Promise<void> {
await this.s3.send(new PutObjectCommand({ Bucket: this.bucket, Key: key, Body: value }));
}
async delete(key: string): Promise<void> { /* ... */ }
async list(prefix?: string): Promise<string[]> { /* ... */ return []; }
async has(key: string): Promise<boolean> { /* ... */ return false; }
}
const store = createStorage({ adapter: new S3StorageAdapter() });Storage interface โ
ts
interface Storage {
get<T>(key: string): Promise<T | undefined>;
set<T>(key: string, value: T, ttl?: number): Promise<void>; // ttl in seconds
delete(key: string): Promise<void>;
list(prefix?: string): Promise<string[]>;
has(key: string): Promise<boolean>;
clear(): Promise<void>;
readonly adapter: StorageAdapter;
}Attach to agent โ
An agent can write its generated outputs to storage automatically:
ts
const agent = createAgent({
name: 'report-writer',
instructions: '...',
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY!,
storage: createStorage({ driver: 'file', basePath: './outputs' }),
});
const result = await agent.run('Write a quarterly summary.', { runId: 'q2-2026' });
console.log(result.storageKey); // key where the output was savedTTL (time-to-live) โ
ts
// Expire after 1 hour
await store.set('cache:result-123', expensiveResult, 3_600);Namespacing pattern โ
Use key prefixes to keep different concerns separate:
ts
// Separate namespaces using prefixes
await store.set('run:abc123:result', runResult);
await store.set('user:alice:prefs', prefs);
await store.set('cache:llm:sha256abc', cachedResponse);
const runKeys = await store.list('run:'); // all run keys
const userKeys = await store.list('user:'); // all user keys