Documentation Index Fetch the complete documentation index at: https://docs.usesatori.sh/llms.txt
Use this file to discover all available pages before exploring further.
Overview
While the memoryTools() helper is great for Vercel AI SDK integration, you can also use the MemoryClient directly for more control over memory operations. This is useful for:
Custom AI frameworks
Background jobs that manage memories
Admin interfaces for viewing/managing memories
Non-LLM use cases
Installation
npm install @usesatori/tools
Basic Usage
Creating a Client
import { MemoryClient } from '@usesatori/tools' ;
const client = new MemoryClient ({
apiKey: process . env . SATORI_API_KEY ! ,
baseUrl: process . env . SATORI_URL ! ,
userId: 'user-123' ,
});
Adding Memories
const memory = await client . addMemory (
'User prefers TypeScript over JavaScript'
);
console . log ( 'Saved memory:' , memory . id );
With metadata:
const memory = await client . addMemory (
'User prefers dark mode in all applications' ,
{
metadata: {
category: 'preference' ,
tags: [ 'ui' , 'theme' ],
importance: 'high' ,
},
}
);
Searching Memories
const memories = await client . searchMemories ( 'programming languages' );
memories . forEach (( memory ) => {
console . log ( ` ${ memory . content } (similarity: ${ memory . similarity } )` );
});
With options:
const memories = await client . searchMemories ( 'preferences' , {
limit: 5 ,
threshold: 0.8 , // Only very similar memories
});
Getting All Memories
const allMemories = await client . getAllMemories ();
console . log ( `Total memories: ${ allMemories . length } ` );
With limit:
const recentMemories = await client . getAllMemories ({ limit: 10 });
Deleting Memories
await client . deleteMemory ( 'memory-uuid' );
console . log ( 'Memory deleted' );
Complete API Reference
Constructor
Satori server URL (e.g., https://api.usesatori.sh)
User identifier for memory isolation
Methods
addMemory(content, options?)
Saves a new memory.
Optional metadata for organization {
category : 'preference' ,
tags : [ 'important' ],
customField : 'value'
}
Returns: Promise<Memory>
{
id : 'uuid' ,
content : 'User prefers TypeScript' ,
userId : 'user-123' ,
metadata : { category : 'preference' },
createdAt : '2024-01-15T10:30:00Z' ,
updatedAt : '2024-01-15T10:30:00Z'
}
searchMemories(query, options?)
Searches for semantically similar memories.
Natural language search query
Maximum number of results (1-100)
Minimum similarity score (0-1)
Returns: Promise<MemoryWithSimilarity[]>
[
{
id: 'uuid' ,
content: 'User prefers TypeScript' ,
similarity: 0.92 ,
userId: 'user-123' ,
metadata: {},
createdAt: '2024-01-15T10:30:00Z' ,
updatedAt: '2024-01-15T10:30:00Z'
}
]
getAllMemories(options?)
Retrieves all memories for the user.
Maximum number of memories to return
Returns: Promise<Memory[]>
deleteMemory(id)
Deletes a specific memory.
UUID of the memory to delete
Returns: Promise<void>
Advanced Use Cases
Building an Admin Dashboard
import { MemoryClient } from '@usesatori/tools' ;
export async function GET ( req : Request ) {
const { searchParams } = new URL ( req . url );
const userId = searchParams . get ( 'userId' );
if ( ! userId ) {
return new Response ( 'Missing userId' , { status: 400 });
}
const client = new MemoryClient ({
apiKey: process . env . SATORI_API_KEY ! ,
baseUrl: process . env . SATORI_URL ! ,
userId ,
});
const memories = await client . getAllMemories ();
return Response . json ({
userId ,
totalMemories: memories . length ,
memories: memories . map (( m ) => ({
id: m . id ,
content: m . content ,
createdAt: m . createdAt ,
metadata: m . metadata ,
})),
});
}
Background Memory Processing
// Cron job to clean up old memories
import { MemoryClient } from '@usesatori/tools' ;
async function cleanupOldMemories ( userId : string ) {
const client = new MemoryClient ({
apiKey: process . env . SATORI_API_KEY ! ,
baseUrl: process . env . SATORI_URL ! ,
userId ,
});
const memories = await client . getAllMemories ();
const sixMonthsAgo = Date . now () - 6 * 30 * 24 * 60 * 60 * 1000 ;
for ( const memory of memories ) {
const createdAt = new Date ( memory . createdAt ). getTime ();
if ( createdAt < sixMonthsAgo ) {
await client . deleteMemory ( memory . id );
console . log ( `Deleted old memory: ${ memory . id } ` );
}
}
}
Memory Export
// Export user data for GDPR compliance
async function exportUserMemories ( userId : string ) {
const client = new MemoryClient ({
apiKey: process . env . SATORI_API_KEY ! ,
baseUrl: process . env . SATORI_URL ! ,
userId ,
});
const memories = await client . getAllMemories ();
const exportData = {
userId ,
exportDate: new Date (). toISOString (),
totalMemories: memories . length ,
memories: memories . map (( m ) => ({
content: m . content ,
createdAt: m . createdAt ,
metadata: m . metadata ,
})),
};
return JSON . stringify ( exportData , null , 2 );
}
Custom AI Framework Integration
import { MemoryClient } from '@usesatori/tools' ;
import Anthropic from '@anthropic-ai/sdk' ;
const anthropic = new Anthropic ({
apiKey: process . env . ANTHROPIC_API_KEY ! ,
});
const memoryClient = new MemoryClient ({
apiKey: process . env . SATORI_API_KEY ! ,
baseUrl: process . env . SATORI_URL ! ,
userId: 'user-123' ,
});
async function chatWithMemory ( userMessage : string ) {
// Search for relevant context
const relevantMemories = await memoryClient . searchMemories ( userMessage , {
limit: 5 ,
});
const context = relevantMemories
. map (( m ) => m . content )
. join ( ' \n ' );
// Call Claude with context
const response = await anthropic . messages . create ({
model: 'claude-3-5-sonnet-20241022' ,
max_tokens: 1024 ,
messages: [
{
role: 'user' ,
content: `Context about the user: \n ${ context } \n\n User message: ${ userMessage } ` ,
},
],
});
// Extract and save any important information
const responseText = response . content [ 0 ]. text ;
// Simple heuristic: if user said "remember" or "I am/like/prefer"
if ( /remember | I am | I like | I prefer/ i . test ( userMessage )) {
await memoryClient . addMemory ( userMessage );
}
return responseText ;
}
Error Handling
Handle errors appropriately:
try {
const memories = await client . searchMemories ( 'query' );
} catch ( error ) {
if ( error instanceof Error ) {
if ( error . message . includes ( 'Unauthorized' )) {
console . error ( 'Invalid API key' );
} else if ( error . message . includes ( 'rate limit' )) {
console . error ( 'Rate limit exceeded' );
// Implement exponential backoff
} else if ( error . message . includes ( 'Not Found' )) {
console . error ( 'Memory not found' );
} else {
console . error ( 'Unknown error:' , error . message );
}
}
throw error ;
}
TypeScript Types
The client exports TypeScript types for all operations:
import type {
Memory ,
MemoryWithSimilarity ,
AddMemoryOptions ,
SearchOptions
} from '@usesatori/tools' ;
const memory : Memory = {
id: 'uuid' ,
content: 'User prefers TypeScript' ,
userId: 'user-123' ,
clerkUserId: 'user_372Icb...' ,
metadata: {},
createdAt: '2024-01-15T10:30:00Z' ,
updatedAt: '2024-01-15T10:30:00Z' ,
};
const searchResult : MemoryWithSimilarity = {
... memory ,
similarity: 0.92 ,
};
Testing
Mock the client for testing:
import { MemoryClient } from '@usesatori/tools' ;
// Mock the client
jest . mock ( '@usesatori/tools' , () => ({
MemoryClient: jest . fn (). mockImplementation (() => ({
addMemory: jest . fn (). mockResolvedValue ({
id: 'test-uuid' ,
content: 'Test memory' ,
userId: 'test-user' ,
metadata: {},
createdAt: new Date (). toISOString (),
updatedAt: new Date (). toISOString (),
}),
searchMemories: jest . fn (). mockResolvedValue ([]),
getAllMemories: jest . fn (). mockResolvedValue ([]),
deleteMemory: jest . fn (). mockResolvedValue ( undefined ),
})),
}));
describe ( 'Memory operations' , () => {
it ( 'saves a memory' , async () => {
const client = new MemoryClient ({
apiKey: 'test-key' ,
baseUrl: 'http://localhost:3001' ,
userId: 'test-user' ,
});
const memory = await client . addMemory ( 'Test content' );
expect ( memory . content ). toBe ( 'Test memory' );
});
});
Best Practices
Create one client per user and reuse it: // ✅ Good: Reuse client
const client = new MemoryClient ( config );
await client . addMemory ( 'Memory 1' );
await client . addMemory ( 'Memory 2' );
// ❌ Bad: Create new client each time
await new MemoryClient ( config ). addMemory ( 'Memory 1' );
await new MemoryClient ( config ). addMemory ( 'Memory 2' );
Use descriptive memory content
Store complete, self-contained information: // ✅ Good
await client . addMemory ( 'User prefers dark mode in all applications' );
// ❌ Bad
await client . addMemory ( 'dark mode' ); // Too vague
Add metadata for organization
Always wrap operations in try-catch blocks: try {
await client . addMemory ( content );
} catch ( error ) {
console . error ( 'Failed to save memory:' , error );
// Fallback behavior
}
Next Steps
Vercel AI SDK Learn about the AI SDK integration
API Reference Explore the complete API documentation
Examples See complete implementations
Troubleshooting Fix common issues