Mandol: An Agglomerative Agent Memory System for Long-Term Conversations
Important
The main branch now contains the current public Mandol Python
implementation. The pre-migration implementation previously hosted on
main is preserved in
legacy/original
for historical reference.
The results reported in the paper were produced with the frozen
paper-repro
artifact. Use paper-repro when exact reproduction of the reported
experiments is required.
Show/Hide
Mandol is a native in-memory hierarchical memory system for LLM agents such as long-term conversational agents. Its core components are:
- Hierarchical Memory Model β Organizes memory into a basic layer and a high-level abstract layer, both uniformly represented as a structured semantic graph with traceable relationships between all memory elements.
- In-Memory Semantic Data Structures β Combines SemanticMap and SemanticGraph to natively fuse key-value, vector, and graph stores into a unified hybrid retrieval interface, eliminating cross-database I/O overhead.
- Smart Quantitative Retrieval β A query-adaptive routing mechanism with two-stage denoising, conflict resolution, and token-constrained context generation β all operating without invoking LLMs during retrieval.
On the LoCoMo and LongMemEval long-term conversation benchmarks, Mandol achieves state-of-the-art accuracy of 92.21% and 88.40%, respectively. Under the server comparison setting, Mandol delivers a 5.4Γ retrieval speedup and a 4.8Γ insertion speedup over the strongest non-Mandol baseline by mean latency, with Search and Add both measured at 10 QPS. These results validate the system's effectiveness, efficiency, and stability in complex long-conversation scenarios.
System-level comparison of agent memory systems:
| System | Memory Organization | Storage | Retrieval | Search Latency |
|---|---|---|---|---|
| Mem0 | Text vectors + metadata | VectorDB + metadata store | Vector semantic retrieval + metadata filtering | Medium |
| Zep | Text vectors + temporal knowledge graph | GraphDB + vector/full-text indexes | Multi-step graph traversal + reranking | High |
| MemOS | Text vectors + graph/tree summaries | VectorDB + GraphDB | Vector retrieval + graph node matching | High |
| EverMemOS | Text vectors + memory summaries | Multi-DB stack | Multi-turn retrieval + query rewriting | Very high |
| Mandol | Basic + high-level memories represented as a structured semantic graph | SemanticMap/Graph with RocksDB-backed tiered payload paging | Hybrid recall + smart quantitative retrieval | Low |
LoCoMo accuracy (%) comparison among different memory systems:
| Backbone | System | Avg. Tok. | Single | Multi | Temp. | Open | Overall |
|---|---|---|---|---|---|---|---|
| GPT-4o-mini | Mem0 | 1.0k | 66.71 | 58.16 | 55.45 | 40.62 | 61.00 |
| MemU | 4.0k | 72.77 | 62.41 | 33.96 | 46.88 | 61.15 | |
| MemOS | 2.5k | 81.45 | 69.15 | 72.27 | 60.42 | 75.87 | |
| Zep | 1.4k | 88.11 | 71.99 | 74.45 | 66.67 | 81.06 | |
| EverMemOSβ | 2.5k | 91.68 | 82.74 | 79.34 | 70.14 | 86.13 | |
| Mandol (Ours) | 2.0k | 93.82 | 85.11 | 89.10 | 65.63 | 89.48 | |
| GPT-4.1-mini | Mem0 | 1.0k | 68.97 | 61.70 | 58.26 | 50.00 | 64.20 |
| MemU | 4.0k | 74.91 | 72.34 | 43.61 | 54.17 | 66.67 | |
| MemOS | 2.5k | 85.37 | 79.43 | 75.08 | 64.58 | 80.76 | |
| Zep | 1.4k | 90.84 | 81.91 | 77.26 | 75.00 | 85.22 | |
| EverMemOSβ | 2.3k | 95.32 | 89.01 | 90.13 | 77.43 | 91.97 | |
| Mandol (Ours) | 1.9k | 95.36 | 92.20 | 87.85 | 79.17 | 92.21 |
β Reproduced using the official implementation from EverMemOS.
Mandol achieves the highest Overall accuracy on LoCoMo under both backbone settings.
LongMemEval accuracy (%) comparison among different memory systems:
| Backbone | System | Avg. Tok. | SS-Pref | SS-Asst | Temporal | Multi-S | Know. Upd. | SS-User | Overall |
|---|---|---|---|---|---|---|---|---|---|
| GPT-4o-mini | MemU | 0.5k | 76.70 | 19.60 | 17.30 | 42.10 | 41.00 | 67.10 | 38.40 |
| Mem0 | 1.1k | 90.00 | 26.78 | 72.18 | 63.15 | 66.67 | 82.86 | 66.40 | |
| Zep | 1.6k | 53.30 | 75.00 | 54.10 | 47.40 | 74.40 | 92.90 | 63.80 | |
| MemOS | 1.4k | 96.67 | 67.86 | 77.44 | 70.67 | 74.26 | 95.71 | 77.80 | |
| Mandol (Ours) | 2.1k | 96.67 | 98.21 | 78.95 | 74.44 | 88.46 | 97.14 | 85.00 | |
| GPT-4.1-mini | EverMemOS | 2.8k | 93.33 | 85.71 | 77.44 | 73.68 | 89.74 | 97.14 | 83.00 |
| Mandol (Ours) | 2.3k | 96.67 | 98.21 | 87.22 | 77.44 | 89.74 | 98.57 | 88.40 |
Mandol achieves the highest Overall accuracy on LongMemEval under both backbone settings.
All latency values are reported in milliseconds. The server comparison was measured on an NVIDIA H800 80GB at 10 QPS for both Search and Add.
| System | Search P99 (ms) | Search P90 (ms) | Search Mean (ms) | Add P99 (ms) | Add P90 (ms) | Add Mean (ms) |
|---|---|---|---|---|---|---|
| MemU | 63000.7 | 60539.5 | 47554.5 | 12070.6 | 7273.1 | 5077.9 |
| EverMemOSβ | 37192.4 | 35220.4 | 20092.1 | 790.2 | 555.5 | 317.7 |
| Mem0 | 4637.0 | 1397.0 | 1089.0 | 2841.0 | 1650.0 | 888.0 |
| Zep | 5348.7 | 614.8 | 571.7 | 375.1 | 254.5 | 239.0 |
| MemOS | 777.1 | 528.4 | 440.5 | 376.4 | 211.6 | 191.9 |
| Mandol (Ours) | 94.8 | 88.5 | 82.2 | 67.3 | 46.9 | 39.7 |
By mean latency in this server comparison, Mandol delivers a 5.4Γ retrieval speedup (440.5 / 82.2) and a 4.8Γ insertion speedup (191.9 / 39.7) over the strongest non-Mandol baseline.
Local deployment. On an NVIDIA RTX 5090 Laptop 24GB, Mandol reaches 166.5 ms mean search latency at 5 QPS and 37.4 ms mean insertion latency at 10 QPS.
| System | Search P99 (ms) | Search P90 (ms) | Search Mean (ms) | Add P99 (ms) | Add P90 (ms) | Add Mean (ms) |
|---|---|---|---|---|---|---|
| Mandol (Ours) | 211.6 | 186.8 | 166.5 | 51.6 | 42.1 | 37.4 |
The local result is reported separately because its hardware and search load differ from the server comparison. β EverMemOS was reproduced using its official implementation. These results correspond to the frozen paper-repro artifact.
Evaluation methodology. Retrieval quality is measured via QA accuracy on the two benchmarks, defined as the percentage of questions whose generated answers are judged correct or semantically consistent with the ground-truth answers. Following the evaluation protocol of prior memory-system studies, GPT-4o-mini and GPT-4.1-mini serve as the answer-generation backbones, and we adopt the released LLM-based answer correctness evaluation script from EverMemOS.
Notably, rather than using large-parameter models such as Qwen3-Embedding-4B and Qwen3-Reranker-4B, we employ lightweight alternatives β Qwen3-Embedding-0.6B for embedding and bge-reranker-v2-m3 for reranking.
Memory is organized into a basic memory layer and a high-level abstract memory layer, both uniformly represented as a structured semantic graph.
The basic layer represents raw memory through memory units, spaces, and explicit/implicit relationships.
The abstract layer models episodic memory (event chains), semantic memory
(entity graphs), and emotional memory (user preferences), with traceable links
that support evidence grounding and abstract reasoning. In the current public
implementation, mandol.auto_builder exposes explicit workflows for
hierarchical summaries, episodic facts, and entity-relation structures.
SemanticMap and SemanticGraph form a unified in-process data structure that combines memory-unit access, vector and sparse indexes, MemorySpace membership, and graph topology. Hybrid retrieval operators combine vector matching and graph traversal through one API surface. For larger memory collections, RocksDB-backed tiered paging can move cold MemoryUnit payloads out of the resident cache while keeping retrieval indexes and graph state in memory.
The RAG-style recall-then-rank paradigm is replaced with a proactive pipeline of Query-Adaptive Routing, two-stage denoising and conflict resolution, and token-constrained context generation. Query-Adaptive Routing dynamically selects and queries the most relevant memory sources based on query intent. Two-stage quantitative denoising and conflict resolution then remove noise and contradictory information across sources. Finally, a compact high-quality context is assembled under token constraints by jointly optimizing relevance and diversity β all without LLM involvement in retrieval.
The maintained package is organized around core data structures,
retrieval and triple_retrieval pipelines, auto_builder high-level memory
construction, memory_router and quantification policies, and the storage
tiered-paging layer.
Core APIs exposed by Mandol:
| Scope | API |
|---|---|
| Memory units | SemanticGraph.add_unit() / batch_add_units() / delete_unit() |
| Explicit relationships | SemanticGraph.add_relationship() / delete_relationship() |
| Dense graph search | SemanticGraph.search_similarity_in_graph() |
| Multi-method retrieval | MultiRetriever.smart_search() |
| Three-tower retrieval | TripleTowerRetriever.search() / smart_search() |
| Retrieval sufficiency | SemanticQuantifier |
| Persistence | SemanticGraph.save_graph() / load_graph() / connect_to_l2() |
| High-level construction | MemoryOrchestrator / build_high_level_memory() |
SemanticGraph.add_unit() and batch_add_units() insert base MemoryUnit objects and update the configured dense and sparse indexes. High-level construction is an explicit workflow provided by mandol.auto_builder; its orchestrator and builders can derive hierarchical summaries, episodic facts, and entity-relation structures while retaining links to the base memories.
Applications can use SemanticGraph.search_similarity_in_graph() for direct dense retrieval, MultiRetriever.smart_search() for fused BM25/SPLADE/cosine retrieval, or TripleTowerRetriever for the paper's hierarchical, graph, and episodic retrieval paths. Router and quantification components compose these paths for the benchmark workflows; they are separate from base unit insertion and indexing.
By default, payloads remain resident in SemanticMap, and SemanticGraph.save_graph() / load_graph() provide complete local snapshots. RocksDB is the only supported persistent payload backend in the current implementation. Calling connect_to_l2() enables automatic tiered paging: dense, BM25, and SPLADE indexes, UID mappings, MemorySpace membership, and graph topology remain resident, while cold payloads are evicted asynchronously after the high watermark is reached and paged back into the resident cache when a retrieval result requires them.
The LoCoMo and LongMemEval results reported in the paper were produced with the
frozen paper-repro
artifact. For faithful reproduction, clone that branch directly:
git clone --branch paper-repro --single-branch https://github.com/AgentCombo/Mandol.git
cd MandolUse the benchmark-specific instructions in the paper-repro branch:
The main branch contains the maintained public implementation. Its
benchmark_self_host/ workflows support current
self-host integration and development, but they are not the frozen entry point
used to produce the paper tables. The
legacy/original
branch is historical and is neither the current API nor a recommended
reproduction path. Obtain datasets, configurations, and intermediate artifacts
according to the corresponding documentation in paper-repro.
Mandol 0.1.0 requires Python >=3.12,<3.13.
Install the current release from the stable PyPI project page. Pin the version when a reproducible package environment is required:
python -m pip install mandol
python -m pip install "mandol==0.1.0"This is an early public research release. APIs may continue to evolve during
the 0.x series, and the package is not intended to be a production service.
For exact paper reproduction, use the paper-repro source checkout and its
benchmark-specific instructions rather than relying on the package alone.
Create the base source environment with:
uv syncFor daily development and documentation work:
uv sync --extra dev --extra docs --group spacy-modelFor the full paper reproduction and performance environment, run the following
inside a paper-repro checkout:
uv sync --extra dev --extra cuda --group spacy-modelIf CUDA or flash-attention is not available on your platform, omit --extra cuda:
uv sync --extra dev --group spacy-modelThe cuda extra is pinned to a Linux x86_64 / Python 3.12 / Torch 2.8 /
CUDA 12 flash-attention wheel for the paper artifact. If this wheel does not
match your platform, omit --extra cuda or install a compatible
flash-attn build manually.
Verify the local package version and build distribution archives with:
uv run python -c "import mandol; print(mandol.__version__)"
uv buildFor exact paper reproduction, use the
paper-reprobranch. Complete installation guides, configuration details, and advanced usage are available in the online documentation.
Copy the environment variable template and fill in only the provider keys used by your workflow:
cp env.template .envenv.template lists the supported OpenAI-compatible provider keys, base URLs,
embedding/reranking endpoints, and optional runtime settings. CLOSEAI_* is
an OpenAI-compatible provider alias used by the paper artifact configuration;
users of another gateway can configure OPENAI_API_KEY or map model aliases to
their own provider. Model and index choices are passed through the current
component constructors and benchmark configuration objects; there is no
repository-wide YAML facade for constructing the full system.
from mandol import MemoryUnit, SemanticGraph, SemanticMap
semantic_map = SemanticMap(
embedding_model_name="all-MiniLM-L6-v2",
use_flash_attention=False,
)
graph = SemanticGraph(semantic_map_instance=semantic_map)
graph.add_unit(
MemoryUnit(
uid="msg_001",
raw_data={"text_content": "Zhang San travelled to Beijing today."},
metadata={"timestamp": "2026-06-21T09:00:00"},
),
space_names=["demo"],
generate_sparse_embedding=False,
)
results = graph.search_similarity_in_graph(
query_text="Where did Zhang San go?",
top_k=3,
ms_names=["demo"],
return_score=True,
)
for unit, score in results:
print(score, unit.uid, unit.text_cached)
graph.save_graph("./memory_snapshot", build_sparse_vectors=False)
restored = SemanticGraph.load_graph(
"./memory_snapshot",
embedding_model_name="all-MiniLM-L6-v2",
use_flash_attention=False,
)Creating SemanticMap loads the selected embedding model and may download it
on first use. High-level memory construction is available separately through
mandol.auto_builder.
To enable RocksDB-backed automatic payload paging for larger collections:
graph.connect_to_l2(
"./l2_database",
max_capacity=100_000,
high_watermark=0.85,
low_watermark=0.70,
)If connect_to_l2() is not called, payloads remain resident in memory. When it
is enabled, eviction scheduling occurs in the add path, RocksDB writes and
resident-cache removal may complete asynchronously, and cold-result
materialization occurs inside the search call that requires the payload.
The maintained API reference, architecture notes, and usage guides are built with Sphinx:
π Online documentation: https://agentcombo.github.io/Mandol/docs
Build the documentation locally:
make docsWe welcome community contributions! Please read CONTRIBUTING.md before submitting a PR to learn about development environment setup, code standards (Ruff, 100-char line length), testing requirements, and the PR process.
- Issues: GitHub Issues β Report bugs or request new features
- Discussions: GitHub Discussions β Usage questions, best practice discussions
- Community: Scan the QR code below to join our WeChat user group
If this work is helpful to your research, please cite our paper:
@misc{zhang2026mandol,
title={Mandol: An Agglomerative Agent Memory System for Long-Term Conversations},
author={Yuhan Zhang and Zhiyuan Guo and Ziheng Zeng and Wei Wang and Wentao Wu and Lijie Xu},
year={2026},
eprint={2606.29778},
archivePrefix={arXiv},
primaryClass={cs.DB},
doi={10.48550/arXiv.2606.29778},
url={https://arxiv.org/abs/2606.29778}
}Apache License 2.0 β See LICENSE

