Skip to Content
SdkMemory Systems

Memory Systems

The platform uses a 3-tier memory architecture to give agents access to user context at different time scales. This enables personalization that improves over time while maintaining responsive, context-aware interactions within a single session.

Architecture Overview

TierScopeLifetimePurpose
Profile MemoryUserPermanentLong-term preferences and attributes
Pattern MemoryUserLong-livedLearned behavioral patterns over time
Session MemorySessionEphemeralShort-term context for current interaction

Each tier serves a distinct role. Together, they give agents a complete picture of who the user is, how they have behaved historically, and what they are doing right now.

┌─────────────────────────────────────────────────┐ │ Agent Execution │ │ │ │ input_data = { │ │ "request": { ... }, ← User input │ │ "profile_memory": { ... }, ← Tier 1 │ │ "pattern_memory": { ... }, ← Tier 2 │ │ "session_memory": { ... }, ← Tier 3 │ │ } │ └─────────────────────────────────────────────────┘

Profile Memory

Profile Memory stores long-term, relatively stable user preferences and attributes. It represents what the system knows about the user as a person, typically populated through onboarding flows, explicit preference settings, and inferred attributes that have been confirmed over time.

Contents

  • Account attributes — user preferences, saved configurations, notification settings
  • Domain preferences — preferred models, output formats, quality thresholds
  • Budget range — spending comfort zone
  • Provider affinities — preferred and disliked providers
  • Constraints — rate limits, compliance requirements, cost caps

Access Pattern

from src.services.user_memory.service import UserMemoryService memory_service = UserMemoryService() # Load profile memory for a user profile = await memory_service.get_profile_memory(user_id="user_456") # Profile data structure # { # "default_model": "gpt-4o", # "preferred_formats": ["json", "markdown"], # "budget_range": {"min": 50, "max": 200}, # "provider_preferences": {"liked": ["openai", "anthropic"], "disliked": ["deprecated-v1"]}, # "quality_thresholds": {"accuracy": "high", "latency": "medium", "cost": "low"} # }

Updates

Profile memory is updated through explicit user actions (updating preferences in settings) or through confirmed inferences from pattern analysis:

await memory_service.update_profile_memory( user_id="user_456", updates={"preferred_formats": ["json", "markdown", "csv"]} )

Pattern Memory

Pattern Memory captures behavioral patterns learned from the user’s interactions over time. Unlike Profile Memory (which stores explicit preferences), Pattern Memory represents inferred tendencies that emerge from repeated behavior.

Contents

  • Interaction patterns — time of day preferences, session frequency, engagement depth
  • Decision patterns — what the user tends to accept or reject from results
  • Preference evolution — how preferences shift over time
  • Category affinity scores — weighted preferences across task categories

Access Pattern

# Load pattern memory for a user patterns = await memory_service.get_pattern_memory(user_id="user_456") # Pattern data structure # { # "avg_session_duration_min": 12, # "peak_activity_hours": [10, 14, 20], # "acceptance_rate_by_category": { # "extraction": 0.72, # "analysis": 0.58, # "reporting": 0.41 # }, # "preference_drift": { # "from": "verbose", # "toward": "concise", # "confidence": 0.68 # }, # "cost_sensitivity": 0.65 # }

Learning

Pattern memory is updated automatically after each significant interaction. The system analyzes user behavior and updates pattern scores:

await memory_service.record_interaction( user_id="user_456", interaction_type="result_accepted", context={"category": "extraction", "cost": 0.0045, "format": "json"} ) # Pattern memory is recalculated in the background

Session Memory

Session Memory holds short-term context for the current interaction. It is created when a session starts and discarded when the session ends. This gives agents awareness of what has already happened in the current conversation without permanent storage overhead.

Contents

  • Conversation history — messages exchanged in the current session
  • Items viewed — results or content the user has seen in this session
  • Current intent — what the user appears to be looking for right now
  • Temporary preferences — session-specific overrides (e.g., “use only gpt-4o for this session”)
  • Agent outputs — results from agents already executed in this session

Access Pattern

# Load session memory session = await memory_service.get_session_memory(session_id="sess_789") # Session data structure # { # "started_at": "2026-02-08T14:00:00Z", # "messages": [ # {"role": "user", "content": "Analyze this dataset"}, # {"role": "assistant", "content": "Here are the results..."} # ], # "items_viewed": ["run_001", "run_002"], # "current_intent": "data_analysis", # "session_overrides": {"model_filter": "gpt-4o"}, # "agent_results": { # "extractor": {"entities": [...]}, # "analyzer": {"results": [...]} # } # }

Lifecycle

# Create a new session session_id = await memory_service.create_session(user_id="user_456") # Update session context during interaction await memory_service.update_session_memory( session_id=session_id, updates={"current_intent": "data_analysis", "items_viewed": ["run_001"]} ) # Session is automatically cleaned up after expiration (default: 30 minutes of inactivity)

Integrating Memory with Agents

Memory is injected into agents through the input_data dictionary. The orchestrator loads all three memory tiers before pipeline execution and includes them alongside the user’s request:

class PersonalizedAgent(BaseAgent): async def execute(self, input_data: Dict) -> AsyncIterator[AgentEvent]: yield AgentEvent(type="agent_start", agent=self.name) # Access all three memory tiers profile = input_data.get("profile_memory", {}) patterns = input_data.get("pattern_memory", {}) session = input_data.get("session_memory", {}) # Use memory to personalize the prompt user_context = f""" User preferences: {profile.get('preferred_formats', [])} Budget: {profile.get('budget_range', {})} Recent behavior: acceptance rate for extraction is {patterns.get('acceptance_rate_by_category', {}).get('extraction', 'unknown')} Current session intent: {session.get('current_intent', 'general analysis')} """ result = await self.llm.generate( prompt=f"{user_context}\n\nAnalyze: {input_data['request']}", model=self.model ) yield AgentEvent(type="agent_complete", agent=self.name, result=result)

Memory Persistence

TierStorageRetention
Profile MemoryMongoDB (user document)Permanent, user-deletable
Pattern MemoryMongoDB (analytics collection)Long-lived, decays over time
Session MemoryRedis30-minute inactivity timeout

Profile and pattern memory are stored in MongoDB for durability and queryability. Session memory uses Redis for low-latency access and automatic expiration.