Skip to content

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:

  1. client.memory.remember() - Explicit save
  2. Automatic extraction during chatStream()
  3. 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

  1. Use descriptive keys

    • seat_preference not pref1
    • home_city not location
  2. Keep values concise

    • aisle not I prefer aisle seats when flying
    • Values are strings, not JSON
  3. Don't store sensitive data

    • No passwords, API keys, or financial data
    • Memories may be shared with AI
  4. Use the profile, don't rebuild it

    • Fetch once per session
    • Let chatStream handle updates
  5. Trust automatic extraction

    • chatStream extracts memories automatically
    • Only use remember() for explicit saves

AI Memory Infrastructure