
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
ai-memory-sdk
Advanced tools
TypeScript SDK for using Letta subagents for pluggable memory management
A TypeScript SDK for using Letta subagents for pluggable memory management. This SDK allows you to easily integrate persistent conversational memory into your applications. This is the TypeScript equivalent of the Python implementation.
npm install @letta-ai/letta-client
# or
yarn add @letta-ai/letta-client
export LETTA_API_KEY="your-letta-api-key"
export OPENAI_API_KEY="your-openai-api-key" # Required for examples
npm run build
import { Memory } from './src/memory';
// Initialize the memory client
const client = new Memory({
lettaApiKey: process.env.LETTA_API_KEY
});
// Or connect to a local server
const client = new Memory({
baseUrl: "http://localhost:8283"
});
// Initialize user memory
await client.initializeUserMemory('user_123');
// Add messages to user's memory
const runId = await client.addMessages('user_123', [
{
role: 'user',
content: 'Hi my name is Bob'
},
{
role: 'assistant',
content: 'Hi Bob, how can I help you today?'
}
]);
// Wait for processing to complete
await client.waitForRun(runId);
// Retrieve user memory
const memory = await client.getUserMemory('user_123');
console.log('User memory:', memory);
// Search user's message history
const searchResults = await client.search('user_123', 'Bob');
console.log('Search results:', searchResults);
new Memory(config?: MemoryConfig)Creates a new Memory instance.
interface MemoryConfig {
lettaApiKey?: string; // Letta API key (or use LETTA_API_KEY env var)
baseUrl?: string; // Base URL for local Letta server
}
Examples:
// Using API key
const client = new Memory({
lettaApiKey: "your-api-key"
});
// Using local server
const client = new Memory({
baseUrl: "http://localhost:8283"
});
// Using environment variable
const client = new Memory(); // Uses LETTA_API_KEY env var
initializeUserMemory(userId: string, options?: InitOptions): Promise<string>Initialize memory for a new user.
interface InitOptions {
userContextBlockPrompt?: string; // Default: "Details about the human user you are speaking to."
userContextBlockCharLimit?: number; // Default: 10000
userContextBlockValue?: string; // Default: ""
summaryBlockPrompt?: string; // Default: "A short (1-2 sentences) running summary of the conversation."
summaryBlockCharLimit?: number; // Default: 1000
reset?: boolean; // Default: false - whether to reset existing memory
}
Returns: Agent ID for the user's memory
Example:
const agentId = await client.initializeUserMemory('user_123', {
userContextBlockValue: 'User is a software engineer who likes TypeScript',
reset: true
});
addMessages(userId: string, messages: Message[], skipVectorStorage?: boolean): Promise<string>Add messages to a user's memory.
interface Message {
role: string; // 'user' or 'assistant'
content: string; // Message content
name?: string; // Optional name
metadata?: Record<string, any>; // Optional metadata
}
Parameters:
userId: User identifiermessages: Array of messages to addskipVectorStorage: Whether to skip adding messages to vector search (default: true)Returns: Run ID for the processing task
Example:
const runId = await client.addMessages('user_123', [
{
role: 'user',
content: 'I love programming in TypeScript'
},
{
role: 'assistant',
content: 'TypeScript is a great language! What do you like most about it?'
}
], false); // Don't skip vector storage for searchability
getUserMemory(userId: string, promptFormatted?: boolean): Promise<string | null>Retrieve a user's memory.
Parameters:
userId: User identifierpromptFormatted: Whether to return memory in XML format for prompts (default: false)Returns: User memory string or null if user doesn't exist
Example:
// Get raw memory
const memory = await client.getUserMemory('user_123');
// Get formatted memory for use in prompts
const formattedMemory = await client.getUserMemory('user_123', true);
// Returns: <human description="Details about the human user...">User details here</human>
getSummary(userId: string, promptFormatted?: boolean): Promise<string | null>Retrieve a user's conversation summary.
Parameters:
userId: User identifierpromptFormatted: Whether to return summary in XML format (default: false)Returns: Summary string or null if user doesn't exist
Example:
// Get raw summary
const summary = await client.getSummary('user_123');
// Get formatted summary
const formattedSummary = await client.getSummary('user_123', true);
// Returns: <conversation_summary>User discussed TypeScript programming...</conversation_summary>
search(userId: string, query: string): Promise<string[]>Search a user's message history.
Parameters:
userId: User identifierquery: Search queryReturns: Array of matching message contents
Example:
const results = await client.search('user_123', 'programming');
console.log('Found messages:', results);
getMemoryAgentId(userId: string): Promise<string | null>Get the Letta agent ID associated with a user.
Parameters:
userId: User identifierReturns: Agent ID or null if user doesn't exist
waitForRun(runId: string): Promise<void>Wait for a background processing run to complete.
Parameters:
runId: Run ID returned from addMessagesdeleteUser(userId: string): Promise<void>Delete a user and all associated data.
Parameters:
userId: User identifierExample:
await client.deleteUser('user_123');
console.log('User deleted');
addFiles(files: any[]): Promise<never>Add files to memory. Currently not implemented.
Throws: "Not implemented" error
import { Memory } from './src/memory';
const client = new Memory();
const userId = 'user_123';
// Initialize user
await client.initializeUserMemory(userId);
// Simulate a conversation
const messages = [
{ role: 'user', content: 'Hi, I\'m working on a React project' },
{ role: 'assistant', content: 'That\'s great! React is a popular framework. What are you building?' },
{ role: 'user', content: 'A todo app with TypeScript' },
{ role: 'assistant', content: 'Excellent choice! TypeScript adds great type safety to React projects.' }
];
// Add messages with vector storage for searchability
const runId = await client.addMessages(userId, messages, false);
await client.waitForRun(runId);
// Check what the system learned about the user
const memory = await client.getUserMemory(userId);
console.log('User context:', memory);
// Search for specific topics
const reactResults = await client.search(userId, 'React');
const typescriptResults = await client.search(userId, 'TypeScript');
console.log('React mentions:', reactResults);
console.log('TypeScript mentions:', typescriptResults);
Run the interactive chat example:
npm run build
node dist/examples/chat.js
const client = new Memory();
const users = ['alice', 'bob', 'charlie'];
// Initialize memory for multiple users
for (const userId of users) {
await client.initializeUserMemory(userId, {
userContextBlockValue: `User ${userId} preferences and context`
});
}
// Add different messages for each user
await client.addMessages('alice', [
{ role: 'user', content: 'I prefer Python for data science' }
]);
await client.addMessages('bob', [
{ role: 'user', content: 'I love JavaScript and web development' }
]);
await client.addMessages('charlie', [
{ role: 'user', content: 'I work with Go for backend services' }
]);
// Retrieve each user's memory
for (const userId of users) {
const memory = await client.getUserMemory(userId);
console.log(`${userId}'s memory:`, memory);
}
The SDK includes comprehensive tests that match the Python SDK functionality:
# Run all tests (includes build + traditional tests + Jest messages test)
npm test
# Run all test suites separately
npm run test:all
# Run Jest tests specifically
npm run test:jest
# Run the messages test suite (equivalent to Python test_messages.py)
npm run test:messages
# Run specific test suites
npm run test:memory
npm run test:formatter
# Watch mode for development
npm run test:watch
npm run dev
npm run clean
npm run build
interface MessageCreate {
content: string;
role: string;
name?: string;
metadata?: Record<string, any>;
}
interface Message {
id: number;
agent_id: string;
content: string;
processed: boolean;
role?: string;
name?: string;
registered_at?: Date;
processed_at?: Date;
metadata?: Record<string, any>;
}
interface File {
id: number;
agent_id: string;
file_path: string;
file_hash: string;
size: number;
last_modified: Date;
processed: boolean;
label: string;
description: string;
registered_at?: Date;
processed_at?: Date;
}
Set up your environment:
# For Letta Cloud
export LETTA_API_KEY="your-api-key-here"
# For local development
# No API key needed, just connect to local server at http://localhost:8283
The SDK throws errors for:
reset: trueaddFilesAlways wrap SDK calls in try-catch blocks for production use:
try {
const runId = await client.addMessages(userId, messages);
await client.waitForRun(runId);
const memory = await client.getUserMemory(userId);
} catch (error) {
console.error('Memory operation failed:', error.message);
// Handle error appropriately
}
MIT License - see LICENSE file for details.
FAQs
TypeScript SDK for using Letta subagents for pluggable memory management
We found that ai-memory-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.