Astreus - Docs

Memory Storage

Memory

Memory Storage in Astreus is a hierarchical memory system that provides powerful conversation history management with adaptive context management. The enhanced system features intelligent AI-powered summarization, automatic context layer management, and smart frequency tracking across immediate, summarized, and persistent memory layers with intelligent token budgeting.

Hierarchical Memory Architecture

The Memory Storage system uses a three-layer architecture for optimal context management:

  • Immediate Layer: Recent messages (40% of token budget)
  • Summarized Layer: AI-powered conversation summaries (35% of token budget)
  • Persistent Layer: Long-term important facts (25% of token budget)
  • Intelligent Summarization: AI-powered summarization with simple fallback when provider unavailable
  • Automatic Context Loading: Smart loading of context layers from database storage
  • Adaptive Context: Automatic context window management with intelligent compression
  • Session-Based Organization: Conversations organized by session ID
  • Automatic Message Storage: Messages saved during agent.chat() and agent.chat({ stream: true })
  • Direct Memory Access: Full memory operations through agent.getMemory()
  • Semantic Search: Optional vector embeddings for content search
  • Priority-Based Retention: Important content stays longer based on multiple factors

Memory Through Agents

Access memory operations directly through your agent:

import { createAgent, createProvider, createMemory, createDatabase } from '@astreus-ai/astreus';

async function setupAgentWithMemory() {
  const db = await createDatabase();
  
  // Create memory with advanced features including adaptive context
  const memory = await createMemory({
    database: db,
    tableName: "conversations",
    maxEntries: 200,
    enableEmbeddings: true,      // Enable semantic search
    enableAdaptiveContext: true, // Enable adaptive context management
    tokenBudget: {              // Custom token budget allocation
      total: 4000,
      immediate: 1600,    // 40% for recent messages
      summarized: 1400,   // 35% for summaries
      persistent: 1000    // 25% for persistent data
    }
  });

  const provider = createProvider({ 
    type: 'openai', 
    model: 'gpt-4o-mini' 
  });

  // Create agent with memory
  const agent = await createAgent({
    name: 'MemoryAgent',
    provider: provider,
    memory: memory,
    systemPrompt: "You are a helpful assistant with perfect memory."
  });

  return agent;
}

// Use agent memory operations
const agent = await setupAgentWithMemory();

// Automatic memory storage during chat
await agent.chat({
  message: "Remember that I like coffee",
  sessionId: "preferences",
  metadata: { category: 'personal_preferences' },
  stream: true,
  onChunk: (chunk) => console.log(chunk)
});

// Direct memory access
const history = await agent.getHistory("preferences");
console.log(`Found ${history.length} messages`);

Session Management

Agents provide built-in session management for organizing conversations:

Session Operations

// List all sessions with metadata
const sessions = await agent.listSessions(20);
sessions.forEach(session => {
  console.log(`Session: ${session.sessionId}`);
  console.log(`Messages: ${session.messageCount}`);
  console.log(`Last message: ${session.lastMessage}`);
  console.log(`Last activity: ${session.lastActivity}`);
  console.log(`Metadata:`, session.metadata);
});

// Get specific session history
const history = await agent.getHistory("session-123", 50);
history.forEach(msg => {
  console.log(`${msg.role}: ${msg.content}`);
  console.log(`Metadata:`, msg.metadata);
});

// Clear a session
await agent.clearHistory("old-session");

Manual Memory Management

Add custom entries to memory for context or system messages:

// Add system context
await agent.addToMemory({
  sessionId: "user-preferences",
  role: 'system',
  content: "User prefers detailed technical explanations",
  metadata: { 
    type: 'preference',
    category: 'communication_style',
    timestamp: new Date()
  }
});

// Add user context
await agent.addToMemory({
  sessionId: "project-discussion",
  role: 'user',
  content: "Working on a React application with TypeScript",
  metadata: { 
    project: 'web_app',
    technologies: ['react', 'typescript'],
    context: 'project_setup'
  }
});

// Add assistant notes
await agent.addToMemory({
  sessionId: "troubleshooting",
  role: 'assistant',
  content: "Issue resolved by updating dependencies",
  metadata: { 
    resolution: 'dependency_update',
    issue_type: 'build_error',
    resolved: true
  }
});

Direct Memory Access

For advanced operations, access the memory instance directly:

// Get memory instance from agent
const memory = agent.getMemory();

// Advanced memory operations
const agentMemories = await memory.getByAgent(agent.id, 100);
console.log(`Agent has ${agentMemories.length} total memories`);

// Search by text content
const searchResults = await memory.searchByText("machine learning", 5);
searchResults.forEach(result => {
  console.log(`Found: ${result.content}`);
  console.log(`Session: ${result.sessionId}`);
});

// Search by embedding (if enabled)
if (memory.config.enableEmbeddings) {
  const embedding = [0.1, 0.2, 0.3, 0.4, 0.5]; // 1536-dimensional vector for OpenAI
  const similarResults = await memory.searchByEmbedding(embedding, 5, 0.8);
  
  similarResults.forEach(result => {
    console.log(`Similarity: ${result.similarity}`);
    console.log(`Content: ${result.content}`);
  });
}

// Get specific memory entry
const entry = await memory.getById("memory-id-123");
if (entry) {
  console.log('Found entry:', entry.content);
}

// Delete specific entries
await memory.delete("memory-id-to-delete");

Memory Configuration

Configure memory when creating agents:

// Basic memory configuration
const basicMemory = await createMemory({
  database: db,
  tableName: "basic_conversations",
  maxEntries: 100
});

// Advanced memory with embeddings
const advancedMemory = await createMemory({
  database: db,
  tableName: "advanced_conversations",
  maxEntries: 500,
  enableEmbeddings: true
});

// Create agents with different memory configurations
const basicAgent = await createAgent({
  name: 'BasicAgent',
  provider: provider,
  memory: basicMemory
});

const advancedAgent = await createAgent({
  name: 'AdvancedAgent',
  provider: provider,
  memory: advancedMemory
});

Memory Configuration Options

OptionTypeDescriptionDefault
databaseDatabaseInstanceDatabase for persistenceRequired
tableNamestringTable name for memory storage"memories"
maxEntriesnumberMax entries per session100
enableEmbeddingsbooleanEnable semantic searchfalse
enableAdaptiveContextbooleanEnable adaptive context management with AI analysisfalse
tokenBudgetTokenBudgetConfigToken allocation across layersDefault budget
priorityWeightsPriorityWeightsPriority weights for content retentionDefault weights
defaultCompressionStrategyCompressionStrategyDefault compression strategySUMMARIZE

Adaptive Context Management

When enableAdaptiveContext is true, the memory system automatically manages context across three hierarchical layers:

// Enable adaptive context with custom configuration
const adaptiveMemory = await createMemory({
  database: db,
  tableName: "adaptive_conversations",
  maxEntries: 300,
  enableAdaptiveContext: true,
  tokenBudget: {
    total: 6000,
    immediate: 3000,    // 50% for recent messages
    summarized: 2000,   // 33% for summaries
    persistent: 1000    // 17% for persistent data
  },
  priorityWeights: {
    recency: 0.4,       // Prioritize recent messages
    frequency: 0.1,     // Less weight to frequency
    importance: 0.4,    // High importance weight
    userInteraction: 0.1,
    sentiment: 0.0      // Ignore sentiment
  }
});

const agent = await createAgent({
  name: 'AdaptiveAgent',
  provider: provider,
  memory: adaptiveMemory,
  systemPrompt: "You are an intelligent assistant with advanced memory management."
});

// Context is automatically managed during conversations
const response = await agent.chat({
  message: "Remember that I prefer concise answers",
  sessionId: "preferences",
  stream: true,
  onChunk: (chunk) => console.log(chunk)
});

// Later conversations will remember preferences even with long context
const response2 = await agent.chat({
  message: "What did I tell you about my communication preferences?",
  sessionId: "preferences",
  stream: true,
  onChunk: (chunk) => console.log(chunk)
});

Adaptive Context Methods

Access adaptive context features directly:

// Get adaptive context layers for a session
const contextLayers = await memory.getAdaptiveContext("session-1", 4000);
console.log("Immediate messages:", contextLayers.immediate.messages.length);
console.log("Summary:", contextLayers.summarized.summary);
console.log("Important facts:", contextLayers.persistent.importantFacts.length);

// Update context with new information
await memory.updateContextLayers("session-1", {
  role: "user",
  content: "Important: I'm a software engineer",
  timestamp: new Date()
});

// Compress context when needed
const compressionResult = await memory.compressContext("session-1", "SUMMARIZE");
console.log("Compression result:", compressionResult);

// Get formatted context for display (includes AI-generated summaries)
const formattedContext = await memory.getFormattedContext("session-1", 4000);
console.log("Formatted context:", formattedContext);

// Generate intelligent summary for session
const sessionSummary = await memory.generateSummary("session-1");
console.log("AI-powered session summary:", sessionSummary);

Semantic Search with Embeddings

When embeddings are enabled, perform semantic searches across conversations:

// Enable embeddings in memory
const vectorMemory = await createMemory({
  database: db,
  tableName: "vector_conversations",
  maxEntries: 300,
  enableEmbeddings: true
});

const agent = await createAgent({
  name: 'VectorAgent',
  provider: provider,
  memory: vectorMemory
});

// Chat with automatic embedding storage
await agent.chat({
  message: "I'm interested in machine learning algorithms",
  sessionId: "ml-discussion",
  stream: true,
  onChunk: (chunk) => console.log(chunk)
});

await agent.chat({
  message: "Tell me about neural networks",
  sessionId: "ml-discussion",
  stream: true,
  onChunk: (chunk) => console.log(chunk)
});

// Search for semantically similar content
const memory = agent.config.memory;
const mlResults = await memory.searchByText("artificial intelligence", 5);

mlResults.forEach(result => {
  console.log(`Related content: ${result.content}`);
  console.log(`From session: ${result.sessionId}`);
});

Context-Aware Conversations

Use memory to build context-aware responses:

class ContextualAgent {
  private agent: AgentInstance;

  constructor(agent: AgentInstance) {
    this.agent = agent;
  }

  async contextualChat(message: string, sessionId: string) {
    // Get recent conversation context
    const recentHistory = await this.agent.getHistory(sessionId, 5);
    
    // Search for relevant past conversations
    const memory = this.agent.getMemory();
    const relevantMemories = await memory.searchByText(message, 3);
    
    // Build context-aware system prompt
    const context = [
      ...recentHistory.map(h => `${h.role}: ${h.content}`),
      ...relevantMemories.map(m => `Related: ${m.content}`)
    ].join('\n');

    const contextPrompt = `Previous context:\n${context}\n\nCurrent message: ${message}`;

    return await this.agent.chat({
      message: contextPrompt,
      sessionId,
      systemPrompt: `You are a helpful assistant. Use the provided context to give more relevant and personalized responses.`,
      stream: true,
      onChunk: (chunk) => console.log(chunk)
    });
  }

  async addUserPreference(sessionId: string, preference: string, category: string) {
    await this.agent.addToMemory({
      sessionId,
      role: 'system',
      content: `User preference: ${preference}`,
      metadata: { 
        type: 'preference',
        category,
        timestamp: new Date()
      }
    });
  }

  async getUserPreferences(sessionId: string) {
    const memory = this.agent.getMemory();
    const preferences = await memory.searchByText("User preference", 10);
    
    return preferences
      .filter(p => p.sessionId === sessionId)
      .map(p => ({
        preference: p.content.replace('User preference: ', ''),
        category: p.metadata?.category,
        timestamp: p.metadata?.timestamp
      }));
  }
}

Multi-Session Memory Management

Manage memory across multiple sessions:

class MultiSessionMemoryManager {
  private agent: AgentInstance;

  constructor(agent: AgentInstance) {
    this.agent = agent;
  }

  async getSessionSummary() {
    const sessions = await this.agent.listSessions();
    
    return sessions.map(session => ({
      sessionId: session.sessionId,
      messageCount: session.messageCount,
      lastActivity: session.lastActivity,
      lastMessage: session.lastMessage?.substring(0, 100) + '...',
      metadata: session.metadata
    }));
  }

  async findSessionsByTopic(topic: string) {
    const memory = this.agent.getMemory();
    const topicResults = await memory.searchByText(topic, 20);
    
    // Group by session
    const sessionMap = new Map();
    topicResults.forEach(result => {
      if (!sessionMap.has(result.sessionId)) {
        sessionMap.set(result.sessionId, []);
      }
      sessionMap.get(result.sessionId).push(result);
    });

    return Array.from(sessionMap.entries()).map(([sessionId, messages]) => ({
      sessionId,
      relevantMessages: messages.length,
      preview: messages[0]?.content.substring(0, 100) + '...'
    }));
  }

  async cleanupOldSessions(daysOld: number = 30) {
    const sessions = await this.agent.listSessions();
    const cutoffDate = new Date(Date.now() - (daysOld * 24 * 60 * 60 * 1000));
    
    const oldSessions = sessions.filter(s => s.lastActivity < cutoffDate);
    
    for (const session of oldSessions) {
      await this.agent.clearHistory(session.sessionId);
      console.log(`Cleaned up session: ${session.sessionId}`);
    }
    
    return oldSessions.length;
  }

  async exportSessionData(sessionId: string) {
    const history = await this.agent.getHistory(sessionId);
    const sessions = await this.agent.listSessions();
    const sessionInfo = sessions.find(s => s.sessionId === sessionId);
    
    return {
      sessionInfo,
      messages: history,
      exportDate: new Date(),
      messageCount: history.length
    };
  }
}

Database Integration

Memory integrates seamlessly with the database system:

// Access database directly through agent
const database = agent.getDatabase();

// Custom queries on memory data
const customQuery = await database.knex('memories')
  .where('agentId', agent.id)
  .andWhere('role', 'user')
  .andWhere('timestamp', '>', new Date(Date.now() - 7 * 24 * 60 * 60 * 1000))
  .orderBy('timestamp', 'desc');

console.log(`User messages in last 7 days: ${customQuery.length}`);

// Memory statistics
const stats = await database.knex('memories')
  .where('agentId', agent.id)
  .groupBy('sessionId')
  .select('sessionId')
  .count('* as messageCount');

console.log('Session statistics:', stats);

Best Practices

  1. Session Organization: Use meaningful session IDs for better organization
  2. Metadata Usage: Store relevant metadata for filtering and search
  3. Memory Cleanup: Regularly clean old sessions to manage storage
  4. Context Building: Use memory search to build relevant context
  5. Embedding Strategy: Enable embeddings for semantic search capabilities
  6. Error Handling: Handle memory operations with proper error handling
  7. Performance: Limit history retrieval for better performance

The agent-centric memory system provides a more intuitive and powerful way to manage conversation history with built-in session management and advanced search capabilities.

How is this guide?