ai-sdk-deepagent

Long-term Memory

Learn how to extend Deep Agent with persistent memory across conversations

Deep agents come with a local filesystem to offload memory. By default, this filesystem is stored in agent state and is transient to a single thread - files are lost when the conversation ends.

You can extend Deep Agent with long-term memory by using a CompositeBackend that routes specific paths to persistent storage. This enables hybrid storage where some files persist across threads while others remain ephemeral.

Think of long-term memory as the agent's "knowledge base" - information it learns in one conversation that it can access in future conversations.

Overview

Two Filesystem Types

By default, Deep Agent maintains two separate filesystems:

1. Short-term (Transient) Filesystem

  • Stored in the agent's state (via StateBackend)
  • Persists only within a single thread
  • Files are lost when the thread ends
  • Accessed through standard paths: /notes.txt, /workspace/draft.md

2. Long-term (Persistent) Filesystem

  • Stored in a persistent backend (via PersistentBackend)
  • Persists across all threads and conversations
  • Survives agent restarts
  • Accessed through paths prefixed with /memories/: /memories/preferences.txt

Why Long-term Memory?

Use CaseShort-termLong-term
Temporary calculations
Session notes
User preferences
Project knowledge
Learned conventions
Research findings

Setup

Configure Long-term Memory

Use a CompositeBackend that routes the /memories/ path to a PersistentBackend:

import { createDeepAgent } from 'ai-sdk-deep-agent';
import { anthropic } from '@ai-sdk/anthropic';
import { CompositeBackend, StateBackend, PersistentBackend } from 'ai-sdk-deep-agent';
import { InMemoryStore } from 'ai-sdk-deep-agent';

const store = new InMemoryStore();

const backend = new CompositeBackend(
  new StateBackend(), // Default: ephemeral
  {
    '/memories/': new PersistentBackend({ store }),
  }
);

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend,
  systemPrompt: `You have long-term memory at /memories/.

  - Read /memories/instructions.txt at the start of conversations
  - Save important information to /memories/ for future reference
  - Check /memories/ before asking users about their preferences`,
});

How It Works

Path Routing

The CompositeBackend routes file operations based on path prefixes:

// Example: Hybrid storage setup
const backend = new CompositeBackend(
  new StateBackend(), // Ephemeral
  {
    '/memories/': new PersistentBackend({ store }),
  }
);

// File operations route to correct backend:
await backend.write('/draft.txt', '...');            // → StateBackend (ephemeral)
await backend.write('/memories/prefs.txt', '...');   // → PersistentBackend (persistent)

Cross-thread Persistence

Files in /memories/ can be accessed from any thread:

import { v4 as uuidv4 } from 'uuid';

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: compositeBackend,
  systemPrompt: `Save user preferences to /memories/user_preferences.txt
  and read them at the start of each conversation.`,
});

// Thread 1: Teach preferences
const config1 = { configurable: { thread_id: uuidv4() } };

await agent.generate({
  prompt: 'Save my preference: I prefer TypeScript over JavaScript',
}, config1);

// Thread 2: Different conversation, same preferences
const config2 = { configurable: { thread_id: uuidv4() } };

const result = await agent.generate({
  prompt: 'What are my language preferences?',
}, config2);

// Agent reads from /memories/user_preferences.txt and responds:
// "You prefer TypeScript over JavaScript"

Common Patterns

Pattern 1: User Preferences

Store user preferences that persist across sessions:

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: compositeBackend,
  systemPrompt: `User Preferences

  You have a file at /memories/user_preferences.txt with user settings.

  At the start of each conversation:
  1. Read /memories/user_preferences.txt
  2. Apply those preferences to your responses

  When users tell you their preferences:
  1. Update /memories/user_preferences.txt using edit_file

  Common preferences to remember:
  - Programming languages (TypeScript vs JavaScript)
  - Code style (tabs vs spaces, semicolons)
  - Framework choices (React vs Vue)
  - Communication style (concise vs detailed)`,
});

Pattern 2: Self-Improving Instructions

An agent can update its own instructions based on feedback:

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: compositeBackend,
  systemPrompt: `You have a file at /memories/instructions.txt with additional
  instructions and user feedback.

  Process:
  1. Read /memories/instructions.txt at the start of conversations
  2. Follow those instructions in your responses

  When users provide feedback like "please always do X" or "I prefer Y":
  1. Update /memories/instructions.txt using edit_file
  2. Include the date and context of the feedback

  Over time, build up a comprehensive set of customized instructions.`,
});

Pattern 3: Knowledge Base

Build up knowledge over multiple conversations:

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: compositeBackend,
  systemPrompt: `You are building a knowledge base about the project.

  Structure:
  /memories/project/architecture.md - System architecture
  /memories/project/api-endpoints.md - API documentation
  /memories/project/conventions.md - Coding conventions
  /memories/project/team-preferences.md - Team choices

  When you learn new information:
  1. Save it to the appropriate file in /memories/project/
  2. Use edit_file to update existing files

  When answering questions:
  1. Check /memories/project/ for relevant information
  2. Use that knowledge in your responses`,
});

Pattern 4: Research Projects

Maintain research state across sessions:

const researchAgent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: compositeBackend,
  systemPrompt: `You are a research assistant working on long-term projects.

  Research storage structure:
  /memories/research/sources.txt - List of sources found
  /memories/research/notes.txt - Key findings and notes
  /memories/research/report.md - Final report draft
  /memories/research/citations.bib - Bibliography

  Process:
  1. When given a research topic, save it to /memories/research/topic.txt
  2. As you conduct research, update the files above
  3. Each conversation continues where the previous one left off
  4. Read existing research files before starting new research`,
});

// Session 1: Start research
await researchAgent.generate({
  prompt: 'Research quantum computing applications in drug discovery',
});

// Session 2 (days later): Continue research
await researchAgent.generate({
  prompt: 'Continue the research and add more findings',
});
// Agent has all previous research context

Store Implementations

InMemoryStore (Development)

Good for testing and development, but data is lost on restart:

import { InMemoryStore, PersistentBackend } from 'ai-sdk-deep-agent';

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: new CompositeBackend(
    new StateBackend(),
    {
      '/memories/': new PersistentBackend({ store }),
    }
  ),
});

Custom RedisStore (Production)

For production, use a persistent store:

import { Redis } from 'ioredis';
import { PersistentBackend } from 'ai-sdk-deep-agent';

class RedisStore {
  constructor(private redis: Redis) {}

  async get(namespace: string[], key: string) {
    const redisKey = [...namespace, key].join(':');
    const data = await this.redis.get(redisKey);
    return data ? JSON.parse(data) : undefined;
  }

  async put(namespace: string[], key: string, value: any) {
    const redisKey = [...namespace, key].join(':');
    await this.redis.set(redisKey, JSON.stringify(value));
  }

  async delete(namespace: string[], key: string) {
    const redisKey = [...namespace, key].join(':');
    await this.redis.del(redisKey);
  }

  async list(namespace: string[]) {
    const pattern = namespace.join(':') + ':*';
    const keys = await this.redis.keys(pattern);

    const values = await Promise.all(
      keys.map(async (key) => {
        const value = await this.redis.get(key);
        return {
          key: key.split(':').pop()!,
          value: JSON.parse(value!),
        };
      })
    );

    return values;
  }
}

// Usage
const redis = new Redis({
  host: 'localhost',
  port: 6379,
});

const redisStore = new RedisStore(redis);

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: new CompositeBackend(
    new StateBackend(),
    {
      '/memories/': new PersistentBackend({ store: redisStore }),
    }
  ),
});

Best Practices

1. Use Descriptive Paths

Organize persistent files with clear paths:

// ✅ Good: Organized structure
/memories/user_preferences.txt
/memories/research/topic_a/sources.txt
/memories/research/topic_a/notes.txt
/memories/project/requirements.md
/memories/project/api-conventions.md

// ❌ Bad: Flat namespace
/memories/prefs1.txt
/memories/data.txt
/memories/stuff.txt

2. Document the Memory Structure

Tell the agent what's stored where:

const agent = createDeepAgent({
  systemPrompt: `Persistent memory structure:

  User Preferences:
  - /memories/user/preferences.txt - General user settings
  - /memories/user/code-style.txt - Coding preferences

  Project Knowledge:
  - /memories/project/architecture.md - System design
  - /memories/project/api.md - API documentation
  - /memories/project/conventions.md - Team conventions

  Research:
  - /memories/research/active.md - Current research topics
  - /memories/research/archive/ - Past research

  Always check these locations before asking the user.`,
});

3. Read Before Write

Encourage the agent to check existing memory before updating:

const agent = createDeepAgent({
  systemPrompt: `Before saving information to /memories/:

  1. Check if the file already exists (read_file)
  2. If it exists, use edit_file to update it
  3. If it doesn't exist, use write_file to create it

  This preserves accumulated knowledge over time.`,
});

4. Regular Summarization

Periodically summarize and consolidate memory:

await agent.generate({
  prompt: `Review all files in /memories/ and create a consolidated summary.

  1. Read all files in /memories/
  2. Identify key information
  3. Create /memories/summary.md with consolidated knowledge
  4. Keep individual files for detail, but use summary for quick reference`,
});

5. Namespace Isolation

For multi-tenant scenarios, use namespaced stores:

// Option 1: Separate stores per user
const userBackend = new CompositeBackend(
  new StateBackend(),
  {
    '/memories/': new PersistentBackend({
      store: new RedisStore(redis, `user:${userId}:`),
    }),
  }
);

// Option 2: Paths per user
const multiUserBackend = new CompositeBackend(
  new StateBackend(),
  {
    '/memories/user1/': new PersistentBackend({ store: sharedStore }),
    '/memories/user2/': new PersistentBackend({ store: sharedStore }),
  }
);

Examples

Example 1: Personal Assistant

import { createDeepAgent } from 'ai-sdk-deep-agent';
import { anthropic } from '@ai-sdk/anthropic';
import { CompositeBackend, StateBackend, PersistentBackend, InMemoryStore } from 'ai-sdk-deep-agent';

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: new CompositeBackend(
    new StateBackend(),
    {
      '/memories/': new PersistentBackend({ store }),
    }
  ),
  systemPrompt: `You are a personal assistant with long-term memory.

  Memory structure:
  - /memories/profile.txt - User's profile information
  - /memories/preferences.txt - User's likes and dislikes
  - /memories/tasks.txt - Ongoing tasks and projects
  - /memories/relationships.txt - Important people and connections

  Workflow:
  1. On conversation start, read all memory files
  2. Use this context in your responses
  3. When you learn new information, update memory files
  4. Keep memory files organized and up-to-date`,
});

// Teach the agent about yourself
await agent.generate({
  prompt: `My name is Alex. I'm a software engineer who loves TypeScript and hates meetings.
  Save this to my profile.`,
});

// Weeks later, the agent remembers
const result = await agent.generate({
  prompt: 'What do you know about me?',
});
// Agent reads from /memories/profile.txt and responds

Example 2: Project Documentation Agent

const docAgent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: new CompositeBackend(
    new StateBackend(),
    {
      '/memories/docs/': new PersistentBackend({ store: docStore }),
    }
  ),
  systemPrompt: `You maintain project documentation.

  Documentation structure:
  - /memories/docs/overview.md - Project overview
  - /memories/docs/api.md - API documentation
  - /memories/docs/guides/ - Tutorial guides
  - /memories/docs/changelog.md - Change log

  When you make changes:
  1. Always read existing documentation first
  2. Use edit_file to update existing docs
  3. Add entries to changelog.md with dates
  4. Keep documentation consistent and accurate`,
});

// Session 1: Initial documentation
await docAgent.generate({
  prompt: 'Create initial documentation for the project API',
});

// Session 2: Update documentation
await docAgent.generate({
  prompt: 'The API added a new endpoint /users/:id. Update the docs.',
});
// Agent reads existing /memories/docs/api.md and updates it

Example 3: Learning Agent

const learningAgent = createDeepAgent({
  model: anthropic('claude-sonnet-4-5-20250929'),
  backend: new CompositeBackend(
    new StateBackend(),
    {
      '/memories/learned/': new PersistentBackend({ store: learningStore }),
    }
  ),
  systemPrompt: `You are a learning agent that builds knowledge over time.

  Process:
  1. Before answering, check /memories/learned/ for relevant information
  2. After learning something new, save it to /memories/learned/
  3. Organize knowledge by topic

  Knowledge structure:
  - /memories/learned/concepts/ - Concepts and definitions
  - /memories/learned/patterns/ - Design patterns
  - /memories/learned/best-practices/ - Best practices
  - /memories/learned/troubleshooting/ - Solutions to problems

  When you learn something:
  1. Determine which category it belongs to
  2. Save it to the appropriate file
  3. Include context and examples`,
});

// Teach the agent over multiple sessions
await learningAgent.generate({
  prompt: 'Teach me about React hooks, especially useEffect and useState',
});

// Agent learns and saves to /memories/learned/concepts/react-hooks.md

// Later, the agent uses what it learned
const result = await learningAgent.generate({
  prompt: 'What are common React hooks patterns?',
});
// Agent reads from /memories/learned/patterns/react-hooks.md

Troubleshooting

Memory Not Persisting

Problem: Files saved to /memories/ are lost between conversations.

Solutions:

  1. Check backend configuration:
// ❌ Wrong: No persistent backend
const backend = new StateBackend();

// ✅ Correct: Composite backend with persistent storage
const backend = new CompositeBackend(
  new StateBackend(),
  {
    '/memories/': new PersistentBackend({ store: myStore }),
  }
);
  1. Verify store is working:
// Test the store directly
await store.put(['test'], 'key', { data: 'test' });
const result = await store.get(['test'], 'key');
console.log(result); // Should return { data: 'test' }

Agent Not Reading Memory

Problem: Agent doesn't access files in /memories/.

Solution: Explicitly instruct the agent to read memory:

const agent = createDeepAgent({
  systemPrompt: `IMPORTANT: At the start of EVERY conversation:

  1. Read /memories/instructions.txt
  2. Read /memories/context.txt
  3. Use this information in your responses

  Do not wait for the user to remind you.`,
});

Memory Getting Cluttered

Problem: /memories/ becomes disorganized over time.

Solution: Implement periodic cleanup:

await agent.generate({
  prompt: `Clean up and reorganize /memories/:

  1. Read all files in /memories/
  2. Identify outdated or duplicate information
  3. Consolidate related information
  4. Create a clear organizational structure
  5. Delete unnecessary files

  Propose a new structure before making changes.`,
});

Advanced Patterns

Pattern: Hierarchical Memory

const agent = createDeepAgent({
  backend: new CompositeBackend(
    new StateBackend(),
    {
      // Short-term session memory (1 day)
      '/memories/session/': new PersistentBackend({
        store: sessionStore,
        ttl: 86400, // 24 hours
      }),

      // Medium-term project memory (1 week)
      '/memories/project/': new PersistentBackend({
        store: projectStore,
        ttl: 604800, // 7 days
      }),

      // Long-term knowledge (permanent)
      '/memories/knowledge/': new PersistentBackend({
        store: knowledgeStore,
        ttl: null, // Never expires
      }),
    }
  ),
  systemPrompt: `Memory hierarchy:

  - /memories/session/ - Current conversation context (cleared daily)
  - /memories/project/ - Project-specific information (cleared weekly)
  - /memories/knowledge/ - Permanent knowledge (never cleared)

  Save information to the appropriate level based on its longevity.`,
});

Pattern: Memory Versioning

await agent.generate({
  prompt: `When updating /memories/important.txt:

  1. Read the current content
  2. Save a backup to /memories/archive/important_YYYYMMDD_HHMMSS.txt
  3. Update the main file
  4. Add a changelog entry to /memories/changelog.md

  This provides version history for important memory files.`,
});

Summary

Long-term memory provides:

FeatureBenefit
Cross-session persistenceInformation survives conversation restarts
Knowledge accumulationAgent learns and improves over time
PersonalizationRemembers user preferences and context
Hybrid storageEphemeral workspace + persistent knowledge
Flexible backendsChoose storage based on your needs
Path-based routingEasy to organize different types of memory
Key Insight: Long-term memory transforms agents from stateless tools into persistent assistants that learn and adapt over time.

Next Steps

On this page