Memory Operations
Learn how to read, write, and manage user memories with Configure Memory.
Overview
Configure Memory stores data in a Memory Profile - a centralized context store for each user. The profile contains:
- User Profile: Name, email, phone, location, etc.
- Connected Tools: Gmail, Calendar, Drive, Notion status
- App Memories: Per-app preferences and facts
- Global Preferences: Cross-app user preferences
Reading the Memory Profile
Get Full Profile
typescript
const profile = await client.memory.getProfile(token, userId);
console.log(profile);
// {
// user: { name: 'Sarah', email: 'sarah@example.com', ... },
// connected_tools: ['gmail', 'calendar'],
// apps: ['travelbot', 'myapp'],
// apps_data: {
// myapp: {
// prefs_delta: { favorite_color: 'blue', timezone: 'PST' },
// user_summary: 'Frequent traveler who prefers window seats'
// }
// },
// prefs: { ... }
// }python
profile = client.memory.get_profile(token, user_id)
print(profile)
# {
# 'user': { 'name': 'Sarah', 'email': 'sarah@example.com', ... },
# 'connected_tools': ['gmail', 'calendar'],
# 'apps': ['travelbot', 'myapp'],
# 'apps_data': { ... },
# 'prefs': { ... }
# }Get Specific Path
Use dot-notation to fetch specific parts:
typescript
// Get just user info
const user = await client.memory.getProfile(token, userId, { path: 'user' });
// { data: { name: 'Sarah', email: 'sarah@example.com', ... } }
// Get app-specific data
const appData = await client.memory.getProfile(token, userId, { path: 'apps.myapp' });
// { data: { prefs_delta: {...}, user_summary: '...' } }
// Get tools status
const tools = await client.memory.getProfile(token, userId, { path: 'tools' });Get App-Scoped Data
Filter to data relevant for your app:
typescript
const scoped = await client.memory.getProfile(token, userId, { appScope: 'myapp' });
// {
// user: { name: 'Sarah', ... },
// connected_tools: ['gmail'],
// app_data: { prefs_delta: {...} },
// global_prefs: {}
// }Writing Memories
Simple Remember
Save individual key-value memories:
typescript
await client.memory.remember(token, userId, 'favorite_color', 'blue');
await client.memory.remember(token, userId, 'dietary_restrictions', 'vegetarian');
await client.memory.remember(token, userId, 'preferred_language', 'English');
// Response
// { saved: true, app: 'myapp', key: 'favorite_color', value: 'blue' }python
client.memory.remember(token, user_id, "favorite_color", "blue")
client.memory.remember(token, user_id, "dietary_restrictions", "vegetarian")
client.memory.remember(token, user_id, "preferred_language", "English")Memories are namespaced to your app - other apps can't read them.
Best Practices for Memory Keys
typescript
// Good: Descriptive, snake_case
await client.memory.remember(token, userId, 'seat_preference', 'aisle');
await client.memory.remember(token, userId, 'home_airport', 'SFO');
await client.memory.remember(token, userId, 'notification_time', '9am');
// Bad: Generic, ambiguous
await client.memory.remember(token, userId, 'pref1', 'value');
await client.memory.remember(token, userId, 'data', 'something');Automatic Memory Extraction
During streaming chat, Memory automatically detects and saves relevant facts:
typescript
await client.streaming.chatStream(
token,
userId,
'I always prefer window seats when I fly',
history,
{ appName: 'TravelBot', appDescription: 'Travel assistant' },
{
onToken: (t) => process.stdout.write(t),
onMemoryUpdated: (memories) => {
// Called when memories are saved
console.log('Saved:', memories);
// [{ key: 'seat_preference', value: 'window' }]
},
onDone: () => {}
}
);Memory Ingestion
Evaluate messages for memory extraction without streaming:
typescript
const result = await client.memory.ingest(
token,
userId,
{ role: 'user', content: 'I live in San Francisco and prefer morning meetings' },
'Location preferences, scheduling preferences, travel preferences'
);
if (result.relevant) {
console.log('Memories extracted:', result.memoriesWritten);
// [{ key: 'location', value: 'San Francisco' },
// { key: 'meeting_preference', value: 'morning' }]
}python
from configure_memory import ConversationMessage
result = client.memory.ingest(
token,
user_id,
ConversationMessage(role="user", content="I live in San Francisco and prefer morning meetings"),
"Location preferences, scheduling preferences, travel preferences"
)
if result.relevant:
print(f"Memories extracted: {result.memories_written}")Memory Profile Structure
The complete profile structure:
typescript
interface MemoryProfile {
// User profile (shared across all apps)
user: {
name?: string;
email?: string;
phone?: string;
location?: string;
timezone?: string;
occupation?: string;
interests?: string[];
summary?: string;
birthday?: string;
};
// Connected tool IDs
connected_tools: ('gmail' | 'calendar' | 'drive' | 'notion')[];
// List of apps that have stored data
apps: string[];
// Per-app data
apps_data: {
[appSlug: string]: {
// App-specific memories (key-value)
prefs_delta: Record<string, string>;
// AI-generated user summary for this app
user_summary?: string;
// Tool context (extracted data relevant to app)
tool_context?: {
gmail?: { items: any[] };
calendar?: { items: any[] };
};
};
};
// Global preferences (cross-app)
prefs: Record<string, any>;
// Tool connection status and data
tools: {
[tool: string]: {
connected: boolean;
connectedAt?: number;
lastSync?: number;
data?: any;
};
};
}Syncing Tool Data
Force a refresh of connected tool data:
typescript
// Sync specific tools
const result = await client.memory.syncTools(token, userId, ['gmail', 'calendar']);
// { userId: '...', synced: { gmail: { synced: true }, calendar: { synced: true } } }
// Sync all connected tools
const result = await client.memory.syncTools(token, userId);Using Memory Context in Prompts
The profile data is designed to be injected into your LLM prompts:
typescript
const profile = await client.memory.getProfile(token, userId);
// Build context string
const context = [];
if (profile.user?.name) {
context.push(`User's name: ${profile.user.name}`);
}
if (profile.connected_tools?.length) {
context.push(`Connected tools: ${profile.connected_tools.join(', ')}`);
}
const appMemories = profile.apps_data?.myapp?.prefs_delta;
if (appMemories && Object.keys(appMemories).length > 0) {
context.push(`Preferences: ${JSON.stringify(appMemories)}`);
}
// Use in your prompt
const systemPrompt = `You are a helpful assistant.
USER CONTEXT:
${context.join('\n')}
Use this context to personalize your responses.`;Memory Lifecycle
Creation
Memories are created via:
client.memory.remember()- Explicit save- Automatic extraction during
chatStream() client.memory.ingest()- Batch evaluation
Updates
Memories are updated by saving with the same key:
typescript
// Initial
await client.memory.remember(token, userId, 'favorite_color', 'blue');
// Update (overwrites)
await client.memory.remember(token, userId, 'favorite_color', 'green');Deletion
Currently, individual memories cannot be deleted. To clear all memories:
typescript
// Disconnect all tools and reset profile
await client.tools.disconnectAll(token);Error Handling
typescript
try {
await client.memory.remember(token, userId, 'key', 'value');
} catch (error) {
if (error.message.includes('unauthorized')) {
// Token expired
// Re-authenticate user
} else if (error.message.includes('missing_fields')) {
// Invalid request
console.error('Missing required fields');
} else {
console.error('Failed to save memory:', error.message);
}
}Best Practices
Use descriptive keys
seat_preferencenotpref1home_citynotlocation
Keep values concise
aislenotI prefer aisle seats when flying- Values are strings, not JSON
Don't store sensitive data
- No passwords, API keys, or financial data
- Memories may be shared with AI
Use the profile, don't rebuild it
- Fetch once per session
- Let
chatStreamhandle updates
Trust automatic extraction
chatStreamextracts memories automatically- Only use
remember()for explicit saves