Multi-Agent Memory Systems: HMARS and the Hierarchy Problem
AIAgentic AIKnowledge GraphsMulti-Agent Memory Systems: HMARS and the Hierarchy Problem
Why flat memory fails, and how hierarchical architectures are rewriting what agent systems can remember β and reason about
The Memory Bottleneck in Agentic AI
Ask any AI engineer working with agentic systems what the hardest technical challenge is today, and they'll likely say memory. Not retrieval speed, not model quality, not even cost β memory.
Why? Because agents face a fundamentally different memory profile than chatbots:
- Persistent state β Agents work across hours, days, or weeks, not single turns
- Context accumulation β Multiple subtasks create context that must be retained and reconciled
- Distributed knowledge β Different agents handle different domains, each with its own memory
- Selective recall β Not all memories are equally important, and agents must know when to remember
Traditional approaches β stuffing everything into the context window, or using a single flat vector store β collapse under these demands. The context window is finite. Flat stores lose temporal and logical structure. Neither supports the kind of deep reasoning that complex, multi-step agent workflows demand.
The Hierarchy Problem
The core insight behind recent work on agent memory is that human memory is hierarchical, and agent memory needs to be too.
Consider how you recall information:
- Your episodic memory holds specific events ("The server crashed last Tuesday at 3pm")
- Your semantic memory holds general facts ("PostgreSQL recovery requires WAL archival")
- Your working memory holds what you're processing right now ("I'm looking at the error log")
- Your procedural memory holds how to do things ("To restart, run systemctl restart postgresql")
Each layer is structured differently, persists differently, and is accessed differently. Flat memory collapses all of these into one undifferentiated blob β and that's why it fails.
HMARS: A Hierarchical Multi-Agent Memory System
HMARS (Hierarchical Multi-Agent Memory System) is a framework designed for long-context reasoning in multi-agent environments. It introduces a structured memory hierarchy where different tiers serve different purposes and different agents access different tiers.
The HMARS Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AGENT LAYER (Orchestration) β
β β
β βββββββββββ βββββββββββ βββββββββββ βββββββββββ β
β βAgent A β βAgent B β βAgent C β βAgent D β β
β β(Math) β β(Code) β β(Search) β β(Verify)β β
β ββββββ¬βββββ ββββββ¬βββββ ββββββ¬βββββ ββββββ¬βββββ β
β βββββββββββββββ΄ββββββββββββ΄ββββββββββββββ β
β β β
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββ
β MEMORY ACCESS LAYER (Shared bus) β
β - Conflict resolution - Memory arbitration β
β - Access control - Cross-agent sharing β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
β β β
βββββββββΌβββββββ ββββββββΌβββββββ ββββββββΌβββββββ
β Short-Term β β Working β β Long-Term β
β Memory β β Memory β β Memory β
β (Session) β β (Task) β β (Episodic) β
ββββββββββββββββ βββββββββββββββ βββββββββββββββ
βββββββββΌβββββββ ββββββββΌβββββββ ββββββββΌβββββββ
β Semantic β β Procedural β β Graph β
β Memory β β Memory β β Memory β
β (Facts) β β (Skills) β β (Relations) β
ββββββββββββββββ βββββββββββββββ βββββββββββββββ
Memory Tiers in Detail
1. Short-Term Memory (Session Persistence)
Purpose: Retain information across a single session context window. Characteristics: Fast access, volatile, bounded. Storage: In-memory embeddings with session-scoped keys. Access: All agents within a session.
2. Working Memory (Task Scope)
Purpose: Hold state needed for the current task. Characteristics: Task-scoped, actively maintained, cleared on completion. Storage: Structured task state with checkpoints. Access: Agent(s) assigned to the current task.
3. Long-Term / Episodic Memory
Purpose: Retain events, decisions, and outcomes across sessions. Characteristics: Persistent, time-stamped, retrievable by event type. Storage: Vector store with temporal metadata. Access: Read by all agents, written by designated recording agents.
4. Semantic Memory
Purpose: Store stable facts about the domain. Characteristics: Highly durable, verified, deduplicated. Storage: Knowledge graph or structured fact store. Access: All agents use semantic memory for grounding.
5. Procedural Memory
Purpose: Store skill knowledge β how tasks are performed. Characteristics: Reusable, versioned, validated. Storage: Recipe/prompt libraries with version histories. Access: Agents following established procedures.
6. Graph Memory
Purpose: Capture relationships and structural knowledge. Characteristics: Relationship-focused, supports path reasoning. Storage: Graph database (e.g., Neo4j, ArangoDB). Access: Retrieval agents, reasoning agents.
Cross-Memory Reasoning
The key innovation of HMARS isn't any single memory tier β it's how the tiers interact. HMARS supports cross-memory reasoning, where answering a question requires consulting multiple memory tiers and reconciling their contents.
Example: Diagnosing a Production Incident
Scenario: A user reports "The checkout service is failing intermittently."
Working Memory (Task):
β Session target: Diagnose checkout failures
β Open hypotheses: [DB connection pool, cache invalidation, API timeout]
Episodic Memory (Events):
β "2026-08-20: Similar checkout errors, caused by Redis eviction"
β "2026-08-22: Deploy v3.2.1 of checkout service, DB migration included"
Semantic Memory (Facts):
β "Checkout service depends on payments API (12% error budget)"
β "Redis is configured with maxmemory-policy=allkeys-lru"
Procedural Memory (Skills):
β "Incident playbook: 1) Check error rates 2) Inspect connection pool 3) Rollback last deploy"
Graph Memory (Relations):
β checkout β DEPENDS_ON β payments-api
β checkout β DEPLOYS_FROM β release-pipeline
β payments-api β CONNECTS_TO β redis
By cross-referencing these tiers, the agent can:
- Parallel hypothesis testing β Check current error rates (working) against historical pattern (episodic)
- Correlation discovery β Notice the deploy timeline (episodic) matches semantic dependencies
- Guided recovery β Apply the procedural playbook with knowledge from other tiers
- Explainability β Every diagnostic step links back to a specific memory
This is fundamentally different from cramming everything into one context window. Cross-memory reasoning gives agents the structure to know what to consult, not just what to retrieve.
Implementing Hierarchical Memory in Practice
Storage Choice Matters
| Memory Tier | Recommended Storage | Why |
|---|---|---|
| Short-term | Redis / in-process | Low latency, ephemeral |
| Working | Structured state (JSON) | Task-scoped, checkpointable |
| Episodic | Vector store (pgvector, Qdrant) | Similarity-based recall |
| Semantic | Knowledge graph (Neo4j) | Fact validation, dedup |
| Procedural | Recipe library + vector index | Versioned, searchable |
| Graph | Neo4j / ArangoDB | Relationship queries |
A Minimal HMARS Implementation
import json
from datetime import datetime
from typing import Any
class MemoryTier:
"""Base class for HMARS memory tiers."""
def __init__(self, name: str):
self.name = name
self.entries = []
def write(self, content: Any, metadata: dict | None = None):
entry = {
"content": content,
"timestamp": datetime.utcnow().isoformat(),
"metadata": metadata or {},
}
self.entries.append(entry)
return entry
def query(self, entity: str, limit: int = 5):
"""Stub β concrete tiers implement their own retrieval."""
raise NotImplementedError
class EpisodicMemory(MemoryTier):
"""Time-stamped event memory with vector similarity."""
def __init__(self, embedding_fn):
super().__init__("episodic")
self.embedding_fn = embedding_fn
self.index = [] # list of (embedding, entry)
def write(self, content: Any, metadata=None):
entry = super().write(content, metadata)
emb = self.embedding_fn(str(content))
self.index.append((emb, entry))
return entry
def query(self, entity: str, limit: int = 5):
# Cosine similarity search (simplified)
q_emb = self.embedding_fn(entity)
scored = [
(self._cosine(q_emb, emb), e)
for emb, e in self.index
]
scored.sort(key=lambda x: x[0], reverse=True)
return [e for _, e in scored[:limit]]
class SemanticMemory(MemoryTier):
"""Deduplicated fact store β facts verified before entry."""
def __init__(self, validator_fn):
super().__init__("semantic")
self.validator_fn = validator_fn
self.facts = {} # normalized fact -> entry
def write(self, content: Any, metadata=None):
normalized = self.validator_fn(content)
if normalized in self.facts:
# Deduplicate β update timestamp
self.facts[normalized]["timestamp"] = datetime.utcnow().isoformat()
return self.facts[normalized]
entry = super().write(content, metadata)
self.facts[normalized] = entry
return entry
class HMARS:
"""The orchestration layer coordinating memory tiers."""
def __init__(self, episodic: EpisodicMemory, semantic: SemanticMemory, graph):
self.episodic = episodic
self.semantic = semantic
self.graph = graph # graph DB client
self.working = MemoryTier("working")
self.session_id = None
def start_session(self):
self.session_id = datetime.utcnow().timestamp()
self.working = MemoryTier("working")
def record_event(self, event: dict):
"""Record an event across appropriate tiers."""
self.episodic.write(event["summary"], metadata={"type": event["type"]})
if event.get("new_fact"):
self.semantic.write(event["new_fact"])
if event.get("relations"):
self._update_graph(event["relations"])
def reason(self, query: str):
"""Cross-memory reasoning entry point."""
# 1. Check working memory
wm_results = self.working.query(query)
# 2. Check episodic memory (past events)
em_results = self.episodic.query(query)
# 3. Check semantic facts
sm_results = self.semantic.query(query)
# 4. Graph-based reasoning
graph_results = self._graph_reason(query)
return {
"working": wm_results,
"episodic": em_results,
"semantic": sm_results,
"graph": graph_results,
}
# Usage
def validate_fact(fact: str) -> str:
"""Normalize/validate a fact before storage."""
return fact.strip().lower()
agent_memory = HMARS(
episodic=EpisodicMemory(embedding_fn=lambda s: mock_embed(s)),
semantic=SemanticMemory(validator_fn=validate_fact),
graph=neo4j_client,
)
agent_memory.start_session()
agent_memory.record_event({
"summary": "Deploy v3.2.1 rolled back due to DB migration error",
"type": "incident",
"new_fact": "Checkout v3.2.1 has a breaking DB migration",
})
The Challenges of Hierarchical Memory
Consistency Across Tiers
The hardest problem: when memory in different tiers conflicts. What happens when episodic memory recalls an event, but semantic memory holds a fact that contradicts it?
HMARS uses a consensus protocol: facts promoted to semantic memory must be corroborated by episodic events or graph relationships. Unverified entries remain confined to episodic memory.
Memory Arbitration
In multi-agent systems, different agents write conflicting memories to the same tier. HMARS uses:
- Per-agent namespaces for private working memory
- Shared but versioned long-term memory
- Arbitration rules to resolve conflicts (newer wins, but only if verified)
Retrieval Strategy
Retrieval across tiers must be progressive β start cheap, escalate only when needed:
- Working memory (cheap, fast)
- Semantic facts (moderate)
- Episodic events (moderate)
- Graph reasoning (expensive)
This mirrors how humans actually work: check what you know, then research, then reason.
Cost Management
Multi-tier retrieval multiplies token usage. Practical mitigations:
- Cache semantic queries aggressively
- Summarize episodic events before storage (they rarely need verbatim retention)
- Only activate graph reasoning for high-complexity queries
- Time-box retrieval with a budget
The Future: Memory as a Service
As hierarchical memory systems mature, a clear architectural pattern is emerging β memory as a service. The memory layer becomes a first-class infrastructure component, orthogonal to any specific agent framework:
βββββββββββββββββββββββββββββββ
β MEMORY SERVICE β
β (centralized, shared) β
β β
β - Episodic store β
β - Semantic KG β
β - Procedural recipes β
β - Graph memory β
β - Arbitration layer β
ββββββββββββββ¬βββββββββββββββββ
β
ββββββββββββββββββββΌβββββββββββββββββββ
β β β
βββββββΌββββββ βββββββΌββββββ βββββββΌββββββ
β Agent β β Agent β β Agent β
β Framework β β Framework β β Framework β
β (LangGraph)β β (CrewAI) β β (AutoGen) β
βββββββββββββ βββββββββββββ βββββββββββββ
This decoupling means:
- Agents can be swapped without losing memory
- Multiple agent systems share institutional knowledge
- Memory survives agent crashes and restarts
- Auditing and compliance become tractable (single memory store to inspect)
Conclusion
HMARS and the broader move toward hierarchical memory represents a fundamental shift in agent architecture. Flat context windows and flat memory stores were always a compromise β a way to get agents working without solving the really hard problem of structured, persistent, distributed memory.
Hierarchical memory doesn't just make agents better at remembering. It makes them better at:
- Reasoning β by providing the right context at the right time
- Collaboration β through shared but structured memory
- Continuity β across sessions, tasks, and systems
- Explainability β every answer traces back to specific memory entries
The agents that will handle complex, long-running, knowledge-intensive work aren't the ones with the largest context windows. They're the ones with the best memory architectures.
Research sources: HMARS paper (arXiv:2606.28349, 2026), MemGraphRAG (arXiv:2606.00610), Hitchhiker's Guide to Agentic AI (arXiv:2606.24937).
Looking for the right tooling? Explore our Best Memory for Agentic Coding guide and MemPalace: Local-First AI Memory deep dive.