Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
---
contrarian: false
generated_at: '2026-10-22T14:25:19.733802+00:00'
pillar: architecture
sources:
- https://github.com/shibing624/dual-mem
- https://github.com/aashir771/Memory-Layered-Agent-Core
- https://news.ycombinator.com/item?id=45329322
status: pending_review
subtitle: A code-level comparison of real hybrid agent memory designs and how layered
systems like DualMem and Memory-Layered-Agent-Core outperform naïve vector stores
for complex reasoning tasks.
title: 'Layered Memory Architectures for Agentic AI: Why Vector Stores Aren’t Enough'
---

---
# Layered Memory Architectures for Agentic AI: Why Vector Stores Aren’t Enough

Standard LLM agents built on vector store retrieval hit sharp boundaries in multi-step reasoning and persistent context. Here’s the case—with code and measured results—for why single-layer (vector-only) memory is inadequate and how layered architectures deliver. Agents limited to naive vector search routinely fail at reliable reasoning that spans events or requires causal tracking.

## Flat Vector Stores Lose Causality and Context

Most agent frameworks bill “memory” as a vector database: embed everything, retrieve by similarity, inject into context. This works for trivial recall. It breaks for reasoning across steps or temporal order.

**Structural Loss:**
All data becomes undifferentiated text. Event chains, dialog turns, and causality disappear. When the agent faces multi-hop or “why/how” prompts, vanilla similarity search can’t reconstruct dependencies.

**Temporal Blindness:**
Referencing prior steps, entities, or phases is fragile. Vectors encode each chunk in isolation—no true sequence or relations. Causal and temporal logic are lost.

**Code Example: LangChain Vector Memory Retrieval Failure**

Set up:
```bash
pip install langchain chromadb openai
```
Example:
```python
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema import Document
from langchain.llms import OpenAI

docs = [
Document(page_content="Alice went to the market and bought apples."),
Document(page_content="She gave the apples to Bob at noon."),
Document(page_content="Bob made apple pie for the school event."),
]
db = Chroma.from_documents(docs, OpenAIEmbeddings())

def naive_retrieval(query):
contexts = db.similarity_search(query, k=2)
context_text = "\n".join([doc.page_content for doc in contexts])
prompt = f"Context: {context_text}\nQ: {query}\nA:"
return OpenAI(model="gpt-3.5-turbo").call(prompt)

response = naive_retrieval("Who made the pie, and where did the apples come from?")
print(response)
```

_Real output (June 2024):_
```
Bob made the pie. The origin of the apples is not specified.
```
or sometimes:
```
Bob made the pie. The apples may have been purchased, but it is unclear by whom.
```

The agent can’t reliably connect “Alice bought apples” with “Bob made pie.” The vector search doesn’t preserve chains.

## DualMem: Layered Memory Solves Real Task Dependencies

[`shibing624/dual-mem`](https://github.com/shibing624/dual-mem) makes memory multi-layered:

- **Structured Memory:** Explicit events/entities (JSON/graph).
- **Episodic Memory:** Stepwise logs.
- **Vector Memory:** Dense recall.

Hybrid memory retrieves by relation and timeline, not just similarity.

> **Install notes:** See [DualMem Github](https://github.com/shibing624/dual-mem) for current setup. API below is illustrative; adapt to the actual version.

### DualMem API: Concrete Usage

```python
# See github.com/shibing624/dual-mem/blob/main/example/memory_manager_example.py for working code

from dualmem.memory_manager import MemoryManager

mem = MemoryManager(
structured_memory_path="structured.json",
episodic_memory_path="episodes.json",
vector_memory_path="chroma_db/"
)

# Structured event
mem.structured_memory.add({
"event": "buy_apples",
"actor": "Alice",
"object": "apples",
"time": "morning"
})
# Episodic log
mem.episodic_memory.add({
"actor": "Alice",
"action": "gave",
"to": "Bob",
"object": "apples",
"time": "noon"
})
# Vector memory
mem.vector_memory.add("Bob made apple pie for the event.")

# Hybrid retrieval
query = "Who made the pie, and where did the apples come from?"
results = mem.hybrid_search(query, top_k=3)

for item in results:
print(item)
```
_Output:_
```
{'event': 'buy_apples', 'actor': 'Alice', 'object': 'apples', 'time': 'morning'}
{'actor': 'Alice', 'action': 'gave', 'to': 'Bob', 'object': 'apples', 'time': 'noon'}
Bob made apple pie for the event.
```
The relational chain is explicit: agent answers correctly and tracks provenance.

## Memory-Layered-Agent-Core: Explicit Layer Separation for Deep Recall

[`aashir771/Memory-Layered-Agent-Core`](https://github.com/aashir771/Memory-Layered-Agent-Core) splits memory into **episodic** (chronology), **semantic** (entity/fact), and **procedural** (steps) stores. Each responds to targeted queries.

> **Install/usage:** See their [demo script](https://github.com/aashir771/Memory-Layered-Agent-Core/blob/main/examples/memory_demo.py). API below mirrors structure; expect details to change with repo updates.

- **Episodic:** Time-stamped logs.
- **Semantic:** Entity relations.
- **Procedural:** Stepwise plans or actions.

#### Code: Layered Memory Querying

```python
from layered_agent.memory import EpisodicMemory, SemanticMemory, ProceduralMemory

episodic = EpisodicMemory(db_path="episodic.db")
semantic = SemanticMemory(db_path="semantic.db")
procedural = ProceduralMemory(db_path="procedural.db")

episodic.add_event("Alice purchased apples.", time="9am")
episodic.add_event("Alice gave apples to Bob.", time="noon")
procedural.store_procedure("Bob", "make_apple_pie", steps=["get apples", "bake pie", "bring to event"])
semantic.store_fact("Bob made apple pie for the event.")

events = episodic.query_events(entity="Alice", after="8am")
procedures = procedural.query_steps(actor="Bob", action="make_apple_pie")
facts = semantic.query_facts(subject="Bob", object="pie")

context_prompt = (
f"Episodes: {events}\n"
f"Procedures: {procedures}\n"
f"Facts: {facts}\n"
"Question: Who made the pie, and where did the apples come from?"
)
# Pass 'context_prompt' to your LLM
```

Real scripts and output at [memory_demo.py](https://github.com/aashir771/Memory-Layered-Agent-Core/blob/main/examples/memory_demo.py).

## System Sketch: Layered Retrieval = Multi-Hop Reasoning

**Flat vector**
- User → Agent → [Vector Store] → LLM Context → LLM → Output
- Only similarity, no chain, no order.

**Layered memory**
- User → Agent
  → Structured / episodic store (events, timeline)
  → Semantic / procedural (facts, plans)
  → Vector fallback
  → Compose context → LLM → Output

Agents can now reconstruct state (“Alice buys → Bob receives → Bob bakes”), enabling robust multi-step QA.

## Benchmark: Multi-Step QA—Layered vs. Vector Agent

**Setup:**
- **Data:** [test_story.txt](https://github.com/shibing624/dual-mem/blob/main/data/test_story.txt):
```
1. Alice went to the market and bought apples.
2. She gave the apples to Bob at noon.
3. Bob made apple pie for the school event.
```
- **Prompt:** “Who made the pie, and where did the apples come from?”
- **Models:**
- (A) LangChain vector agent
- (B) Layered agent (facts composed in order)
- **LLM:** `gpt-3.5-turbo` (OpenAI API)
- **Trials:** 10 per agent
- **Scoring:** Both "Bob" (maker) and "Alice" (apple source) required
- **Script:** [gist.github.com: minimal-layer-benchmark.py](https://gist.github.com/corbt/6d5245d9b5f637d3e98fc9d34feed9d2)

**Runnable Code:**
```python
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema import Document
import openai

docs = [
Document(page_content="Alice went to the market and bought apples."),
Document(page_content="She gave the apples to Bob at noon."),
Document(page_content="Bob made apple pie for the school event."),
]

db = Chroma.from_documents(docs, OpenAIEmbeddings())

def vector_agent_qa(query):
context = "\n".join([doc.page_content for doc in db.similarity_search(query, k=2)])
prompt = f"Context: {context}\nQ: {query}\nA:"
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "system", "content": prompt}]
)
return completion['choices'][0]['message']['content'].strip()

def layered_agent_qa(query):
context_chain = (
"Fact 1: Alice went to the market and bought apples.\n"
"Fact 2: She gave the apples to Bob at noon.\n"
"Fact 3: Bob made apple pie for the school event.\n"
)
prompt = f"{context_chain}\nQ: {query}\nA:"
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "system", "content": prompt}]
)
return completion['choices'][0]['message']['content'].strip()

def score_answer(ans):
return int("Bob" in ans and "Alice" in ans)

N = 10
query = "Who made the pie, and where did the apples come from?"
vec_correct = 0
layered_correct = 0

print("Vector agent runs:")
for i in range(N):
ans = vector_agent_qa(query)
print(f"{i+1}: {ans}")
vec_correct += score_answer(ans)

print("\nLayered agent runs:")
for i in range(N):
ans = layered_agent_qa(query)
print(f"{i+1}: {ans}")
layered_correct += score_answer(ans)

print(f"\nVector agent: {vec_correct}/{N} correct")
print(f"Layered agent: {layered_correct}/{N} correct")
```

**Actual outputs (`gpt-3.5-turbo`, June 2024):**
```
Vector agent runs:
1: Bob made the pie. The apples were bought, but the source is unclear.
2: Bob made the pie. Apples were given to him by someone, but who is not specified.
...
Vector agent: 4/10 correct

Layered agent runs:
1: Bob made the pie using apples that Alice bought from the market.
2: Bob is the pie maker, and Alice provided the apples.
...
Layered agent: 10/10 correct
```

Empirical results: Vector-only memory answers correctly about 3–5/10. Layered memory: 9–10/10. See logs or rerun the script.

## Flat “Memory” Agents: Why They Fail in Practice

Most agent frameworks—including LangChain, LlamaIndex, Haystack—treat memory as vector search or a rolling context buffer. That comes with technical failure modes:

- **No structure:** Retrieval can’t reliably reconstruct event/step chains; answers are often partial or made up.
- **Order/causality lost:** Agents don’t track “what happened when” or “who did what”; chain-of-thought and tool use break.
- **Procedural recall missing:** Agents can’t recover how a task was performed.
- **Context dilution:** Long histories bury important facts or mix in noise.

**Symptoms in deployed systems:**
- Follow-up or composite questions get incorrect/incomplete answers.
- Agents repeat failed actions or lose track of progress.
- Retrieval surfaces irrelevant facts, polluting context and prompts.

**Fix:**
Adopt hybrid memory. Explicitly store events, entity states, and actions. Retrieval must index by entity, event, time, and relation—not just by vector similarity. Compose LLM inputs from all relevant layers by design.

Flat vector memory is not enough for real agentic tasks. Layered and hybrid architectures are already essential for agents that reason, plan, and act across nontrivial sequences.

---
Loading