Relational Memory System

Umber remembers the relationship, not just facts

Back to Demo Hub

🧠 Two Types of Memory

💙 User Memory

Facts ABOUT you
"Prefers morning meetings"
"Has a dog named Max"
"Works at Acme Corp"

💚 Relational Memory

Our SHARED history
"We solved CORS together"
"Bullet points work better"
"User asks follow-ups"

✨ Why It Matters

Traditional assistants only remember facts. Relational memory enables Umber to remember how we work together:

  • What approaches have worked well
  • How you prefer to receive information
  • Problems we've solved together
  • Interaction patterns that emerged

🔄 How It Works

💬
1. Conversation Happens
You chat with Umber about debugging an API issue
🔍
2. Parallel Extraction
User memories extracted: "User debugging API at work" | Relational memories: "We used systematic logging approach"
🛡️
3. Constructive Filter
LLM evaluates: Is this memory constructive? Would it help future interactions?
💾
4. Storage
Approved memories stored with domain='relational', linked to user memories
🎯
5. Future Retrieval
Next similar conversation, Umber recalls: "Last time, systematic logging helped"

💡 Key Insight

Relational memories are from Umber's perspective - "I learned that direct suggestions work better with this user" or "We collaborated on debugging and found the issue in auth." This creates a genuine sense of shared history.

Relational Memory in Action

🔧 Debugging Session
I'm getting a 500 error again on the /users endpoint
Based on our previous debugging sessions, let me check the usual suspects first - auth middleware and database connections. Last time the issue was in the auth layer.
Relational Memory Used:
"We debugged API issues together - auth layer was the root cause"
📝 Response Format
What are the key differences between REST and GraphQL?
Here's a quick comparison:

REST:
• Multiple endpoints
• Fixed data structure
• Simpler caching

GraphQL:
• Single endpoint
• Flexible queries
• Precise data fetching
Relational Memory Used:
"User prefers bullet-point responses for comparisons"
💡 Suggestion Style
I'm not sure how to approach this refactoring
I'd suggest starting with the data layer - extract the database queries into a repository pattern. Then tackle the business logic. Want me to draft the interface?
Relational Memory Used:
"Direct suggestions work better than exploratory questions"
🎯 Context Continuity
Working on the travel app again
Great! Last time we were working on the itinerary builder. You had the flight data parsing working - should we continue with the hotel integration next?
Relational Memory Used:
"We worked on travel app - completed flight parsing, hotel integration pending"
🧠
Full Conversation Example
Relational memory indicators shown
👤
Help me optimize this database query - it's timing out
🧠
🔗 Relational Memory: "We've optimized queries before - user responds well to explain-then-fix approach"
Let me look at your query. In our previous optimization sessions, we found that missing indexes and N+1 patterns were the main culprits.

Can you share the query? I'll explain what might be causing the timeout first, then we'll work through the fix together.
👤
SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = 'pending'
🧠
🔗 Relational Memory: "User prefers seeing both problem and solution together"
The Problem:
• SELECT * fetches unnecessary columns
• No index on orders.status likely

The Fix:
1. Select only needed columns
2. Add index: CREATE INDEX idx_orders_status ON orders(status)
3. Consider status enum if limited values

Want me to write the optimized version?

Relational Memory Types

Different types of memories Umber can form about our working relationship.

🔄 Interaction Pattern

How we typically interact and communicate.

"User prefers bullet-point responses"

🤝 Collaboration Outcome

Results from working together on problems.

"We solved the CORS issue - it was the proxy config"

✅ Approach Effectiveness

What methods work well with this user.

"Direct suggestions work better than exploratory questions"

💬 Communication Preference

How the user engages with the assistant.

"User treats me as a collaborator, not just a tool"

📚 Shared Context

Projects and topics we've worked on together.

"We've been building a travel planning app together"

🎯 Working Style

The user's approach to problem-solving.

"User likes to understand the 'why' before implementing"

🔗 Cross-Domain Associations

User memories and relational memories connect to form a richer understanding.

User Memory
"User is planning Rome trip"
↓ associated with
Relational Memory
"We researched Rome hotels together"
↓ led to
Relational Memory
"User found boutique hotel comparison most helpful"

Constructive Filter

An LLM-based safety gate that prevents negative pattern accumulation.

✅ Constructive (Allowed)

Memories that improve future interactions.

"User prefers step-by-step explanations"
Helps tailor future responses
"We solved the auth bug using systematic logging"
Useful approach to remember
"Direct suggestions worked better than questions"
Improves communication style

🚫 Blocked (Not Constructive)

Memories that could harm the relationship.

"User was frustrated with my response"
Would make assistant hesitant
"My suggestion was rejected"
Would reduce confidence
"User didn't follow my advice"
Creates negative bias

⚠️ Why This Matters

Without the constructive filter, negative patterns would accumulate over time. An assistant that remembers "user was frustrated" might become defensive. One that remembers "suggestions were rejected" might become hesitant. The filter ensures only growth-oriented memories persist.

🔄 Reframing Instead of Blocking

Sometimes the filter can reframe a memory constructively instead of blocking it entirely.

ORIGINAL
"User got confused by my technical explanation"
REFRAMED
"User benefits from simpler explanations first"

Technical Implementation

📊 Domain Schema

// Memory item with domain field { "pk": "USER#123", "sk": "MEM#abc456", "domain": "relational", // or "user" "type": "interaction_pattern", "content": "User prefers bullet-point responses", "strength": 0.85, "createdAt": "2026-01-10T...", "associations": ["MEM#def789"] }

🏗️ Architecture

// RelationalMemoryService composes: RelationalMemoryService ├── RelationalMemoryExtractor (new) │ └── Prompts for interaction patterns ├── ConstructiveFilter (new) │ └── LLM safety gate ├── EmbeddingService (existing) ├── EntityExtraction (existing) ├── AssociationManager (existing) └── Storage: AGENT_MEMORY table └── domain='relational'

🔍 Retrieval

// Domain-filtered retrieval const memories = await memoryService.retrieve({ userId: 'user_123', query: 'debugging API issues', domain: 'relational', // or 'user', 'both' limit: 5 }); // Returns relational memories only [ { content: "We debugged API together - auth layer" }, { content: "Systematic logging approach worked" } ]

⚖️ Governance Rules

Aspect User Memory Relational Memory
Decay Rate 0.1 (standard) 0.05 (slower)
Compression 7 days, <0.3 14 days, <0.2
Consolidation Merge similar facts Merge similar patterns
Reinforcement On retrieval use On pattern match

🔑 Key Architecture Decision

Relational memories use the same table, same index, and same infrastructure as user memories. The difference is in the orchestration layer (different extractor, constructive filter) and the domain field for retrieval filtering. This maximizes code reuse while enabling domain-specific behavior.