Skip to main content

Advanced Memory System

The advanced memory system provides sophisticated memory management with short-term, long-term, entity, and user-specific storage, enhanced by quality scoring and optional graph database support.

Key Features

Separate short-term and long-term memory systems
4-metric quality assessment for stored memories
User, agent, and run-specific memory scoping
Automatic entity extraction and storage
Optional Neo4j/Memgraph for relationships
Quality-based filtering and relevance ranking

Quick Start

Memory Tiers

Short-term Memory (STM)

Short-term memory is cleared between sessions and used for immediate context.
memory.reset_short_term() / .reset_long_term() now work on the default rag / chroma provider, not just sqlite / in_memory and dakera. On sqlite / in_memory providers, reset_* / delete_* delegate to the active adapter (mirroring search_short_term), so they operate on the adapter-created short_term_memory / long_term_memory tables.
On the default rag provider, resetting short-term also clears long-term — Chroma stores both tiers in one collection. Use DakeraMemoryAdapter if you need tier isolation.
Adapters that don’t implement reset_short_term / reset_long_term now log a warning stating the tier was NOT cleared, instead of silently succeeding — check logs after upgrade.
Since PraisonAI PR #4020, Chroma-backed memory (the default) supports reset. On earlier releases, Memory().reset_short_term() / .reset_long_term() was a documented, callable, exception-free API that quietly did nothing.

Long-term Memory (LTM)

Long-term memory persists across sessions and stores important information.

Entity Memory

Entity memory stores information about specific people, places, or things.

User Memory

User memory stores personalised information and preferences.

Configuration Options

RAG Configuration (Default)

Mem0 Configuration

Dakera Configuration

Requires: pip install "praisonaiagents[dakera]"
See Dakera Memory for the full guide.

Graph Memory Configuration

Quality Scoring System

Quality Metrics

Completeness

Measures how complete and comprehensive the information is

Relevance

Measures how relevant the information is to the context

Clarity

Measures how clear and understandable the information is

Accuracy

Measures the factual accuracy of the information

Quality Calculation

Local LLM for quality scoring

Memory quality scoring uses litellm when available and falls back to the OpenAI client. Point it at any OpenAI-compatible local server by either: Via memory config (recommended when the rest of your memory layer is config-driven):
Via environment (works with any call site, not just memory):
Before PR #4812, the OpenAI-client fallback in calculate_quality_metrics silently ignored base_url supplied through config — it worked only if you also exported OPENAI_BASE_URL. If you were seeing memory reads/writes go to your local server but quality scoring still hit api.openai.com, that was the bug; it is now fixed.

Advanced Features

Scoped search with user_id and metadata_filter

search_short_term and search_long_term accept user_id and metadata_filter as first-class kwargs to scope results per tenant.
user_id is now enforced twice on every search — once at the Memory layer (existing) and again inside SearchMixin.search_short_term / SearchMixin.search_long_term as of PraisonAI PR #4819. The lower layer auto-derives the same user_id metadata filter, so adapters that accept user_id but ignore it in their own query (Chroma/RAG, SQLite, in-memory) still isolate per-tenant results. If a caller passes both an explicit user_id and a conflicting metadata_filter["user_id"], the explicit user_id always wins — a caller cannot widen scope to another tenant’s data.
user_id takes precedence over any metadata_filter["user_id"], so a route can never widen scope to another tenant. Applied across every backend — Mem0, MongoDB (with and without vector search), ChromaDB, memory-adapter, and the SQLite fallback. When a metadata_filter is present, each backend over-fetches by 10× so results ranked beyond limit still survive the post-filter, then truncates back to limit.
Direct SearchMixin use (subclassing or embedding in a custom store) previously depended on the adapter to filter by user_id. If you have such code, no change is required — the filter is applied automatically now — but you may safely remove any duplicate post-filtering you added as a workaround.
Before PR #3855, user_id and metadata_filter were silently absorbed into **kwargs and never applied — per-user scoping was broken on the class-body path. Pass them explicitly, not inside a memory={...} dict.

Context Building

Build comprehensive context for tasks:

Task Output Finalisation

Store task results with quality assessment:

Memory Citations

Automatically cite memory sources:

Memory Reranking

Enhance search results with intelligent reranking based on relevance scores:

Reranking Features

  1. Semantic Reranking: Re-scores results based on semantic similarity
  2. Context-Aware Ranking: Considers current context when ranking
  3. Quality-Weighted Ranking: Combines relevance with quality scores

Custom Reranking Logic

Implement custom reranking strategies:

Reranking Performance

Optimize reranking for large result sets:

Performance Optimisation

Complete Example

Best Practices

  • Set minimum quality for critical information (0.8+)
  • Use lower thresholds for exploratory searches
  • Regular quality audits
  • Periodically review and clean old memories
  • Update quality scores as information ages
  • Deduplicate similar memories
  • Use user_id for personalisation
  • Use agent_id for agent-specific knowledge
  • Use run_id for session isolation
  • Enable embeddings for semantic search
  • Use quality filters to reduce search space
  • Implement caching for frequent queries

Next Steps

Knowledge

Integrate with document knowledge bases

Sessions

Learn about stateful sessions