Persistent User Memory

Persistent User Memory enables EDDI agents to remember facts, preferences, and context about individual users across conversations. Unlike conversation-scoped properties that are lost when a conversation ends, persistent memories survive indefinitely and are automatically loaded into every new conversation with the same user.

Overview

Feature
Description

Scope

Per-user, per-agent (or globally shared)

Storage

MongoDB (usermemories collection) or PostgreSQL (usermemories table)

LLM Integration

4 built-in tools for autonomous memory management

Visibility

self, group, global scoping

Guardrails

Configurable key/value limits, write-rate limits, capacity caps

GDPR

Full right-to-erasure support via REST API and MCP tools

Maintenance

Background "Dream" consolidation (stale pruning, contradiction detection)

Architecture

┌─────────────────────────────────────────────────────┐
│                   Conversation Pipeline              │
│                                                      │
│  LLM ──→ UserMemoryTool ──→ IUserMemoryStore        │
│            ↑                       ↑                 │
│            │                       │                 │
│      AgentOrchestrator     MongoUserMemoryStore      │
│      (per-invocation)      PostgresUserMemoryStore   │
│                                                      │
│  REST API ───────────────────→ IUserMemoryStore      │
│  MCP Tools ──────────────────→ IUserMemoryStore      │
│  DreamService (background) ─→ IUserMemoryStore      │
└─────────────────────────────────────────────────────┘

Agent Configuration

Enable advanced memory features (LLM tools, Dream consolidation, guardrails, recall settings) in your agent's configuration:

Note: Basic longTerm property persistence (via PropertySetterTask) works for all agents regardless of enableMemoryTools. The flag only gates advanced features: LLM UserMemoryTool, Dream consolidation, write guardrails, and custom recall settings.

Configuration Reference

Field
Type
Default
Description

maxEntriesPerUser

int

500

Maximum memory entries per user

maxRecallEntries

int

50

Maximum entries returned by recall

recallOrder

String

"most_recent"

"most_recent" (by updatedAt) or "most_accessed" (by accessCount)

onCapReached

String

"evict_oldest"

"reject" (block new writes) or "evict_oldest" (push out of recall window)

Guardrails

Field
Type
Default
Description

maxKeyLength

int

100

Maximum characters for memory keys

maxValueLength

int

1000

Maximum characters for memory values

maxWritesPerTurn

int

10

Write-rate limit per conversation turn

allowedCategories

List<String>

["preference","fact","context"]

Allowed memory categories

Dream Configuration

Field
Type
Default
Description

enabled

boolean

false

Enable background consolidation

pruneStaleAfterDays

int

90

Remove entries not accessed in N days. Set to 0 to disable.

detectContradictions

boolean

true

Flag entries with same key but different values

summarizeInteractions

boolean

false

V2 feature: LLM-driven fact compression

maxCostPerRun

double

0.50

Maximum dollar cost per dream cycle

LLM Tools

When usermemory is in the agent's builtInToolsWhitelist, the LLM gets access to four tools:

rememberFact

Store a fact about the user.

recallMemories

Retrieve all memories visible to this agent for the current user.

searchMemory

Search for memories by keyword across keys and values.

forgetFact

Delete a specific memory by key.

Visibility Scopes

Scope
Description
Upsert Key

self

Only the agent that stored it can see it

(userId, key, sourceAgentId)

group

All agents in the same group conversation can see it

(userId, key, sourceAgentId)

global

All agents for this user can see it

(userId, key)

Group Memory

When agents participate in a Group Conversation, the groupId is automatically injected into the conversation context. Memories stored with group visibility are visible to all agents in that group.

REST API

Base path: /usermemorystore/memories

Method
Path
Description

GET

/{userId}

Get all memories for a user

GET

/{userId}/visible?agentId=&groupId=&order=&limit=

Get memories visible to a specific agent

GET

/{userId}/search?q=

Search memories by keyword

GET

/{userId}/category/{category}

Get memories filtered by category

GET

/{userId}/key/{key}

Get a specific memory by key

PUT

/

Upsert a memory entry (JSON body)

DELETE

/entry/{entryId}

Delete a specific memory

DELETE

/{userId}

Delete ALL memories for a user (GDPR)

GET

/{userId}/count

Count memory entries

Example: Upsert a memory

Example: Get visible memories

MCP Tools

8 MCP tools are available for external integration and administration:

Tool
Role
Description

list_user_memories

eddi-viewer

List all entries for a user

get_visible_memories

eddi-viewer

Get entries visible to a specific agent

search_user_memories

eddi-viewer

Search by keyword

get_memory_by_key

eddi-viewer

Look up by key name

count_user_memories

eddi-viewer

Count entries

upsert_user_memory

eddi-admin

Insert or update an entry

delete_user_memory

eddi-admin

Delete a specific entry

delete_all_user_memories

eddi-admin

GDPR delete-all (requires CONFIRM)

GDPR Compliance

The delete_all_user_memories MCP tool and DELETE /{userId} REST endpoint permanently remove all memory entries and legacy properties for a user. The MCP tool requires an explicit confirmation="CONFIRM" parameter as a safety gate.

Dream Consolidation

The Dream service performs background maintenance on user memories:

  1. Stale Pruning — Removes entries not accessed in pruneStaleAfterDays days. This is a deterministic operation with zero LLM cost.

  2. Contradiction Detection — Identifies entries with the same key but different values (e.g., language=English from Agent A vs language=German from Agent B). V1 uses key-based matching; future versions will use LLM-driven semantic analysis.

  3. Interaction Summarization — (V2, not yet active) Compresses multiple related facts into consolidated summaries using the LLM.

Metrics

The Dream service exposes Micrometer metrics:

Metric
Type
Description

dream.users.processed

Counter

Users processed across all dream cycles

dream.entries.pruned

Counter

Total entries pruned

dream.contradictions.found

Counter

Contradictions detected

dream.duration

Timer

Duration of dream cycles

Migration from Legacy Properties

In v6, the legacy IPropertiesStore interface and the properties collection have been removed. All user-scoped persistent data now lives in the unified usermemories collection.

Aspect
Legacy Properties (v5)
User Memory (v6)

Storage

properties collection (flat map)

usermemories collection (structured entries)

Interface

IPropertiesStore (deleted in v6)

IUserMemoryStore

Scoping

Per-user only

Per-user, per-agent, per-group

LLM access

Via template variables only

Direct LLM tool access

Querying

Key lookup only

Key, category, search, visibility filtering

Administration

No REST API

Full CRUD REST API + MCP tools

Backward Compatibility

Legacy flat property operations (readProperties, mergeProperties, deleteProperties) continue to work through IUserMemoryStore — they operate on global visibility entries in the usermemories collection. The REST endpoint at /propertiesstore/properties/{userId} is preserved.

Startup Migration (MongoDB only)

On first startup, PropertiesMigrationService automatically migrates existing properties documents into usermemories as global entries with category=legacy. The old collection is renamed to properties_migrated_v6 as a safety backup. This migration is idempotent and skipped if no legacy collection exists.

Note: PostgreSQL deployments do not need migration — the properties table only existed in MongoDB (v5).

Data Model

Each memory entry contains:

Last updated

Was this helpful?