Hierarchical Memory
Category: Architecture
Problem
Not all memories are equal. A user's name should persist forever, last week's conversation topics should fade gradually, and the current session's working context should be immediately available but ephemeral. Treating all memories with the same storage and decay strategy leads to either information overload or premature forgetting.
Architecture
This pattern uses three namespace tiers in Dakera — each with its own decay configuration. Short-term memory captures the active session and decays aggressively. Long-term memory holds durable facts and decays slowly. Permanent memory stores identity-level information with no decay at all.
Flow
- Classify incoming memories by tier (ephemeral, durable, permanent)
- Route each memory to the appropriate namespace
- Configure per-namespace decay rates
- At recall time, query all tiers and merge results by relevance
Implementation
from dakera import Dakera
client = Dakera(base_url="http://localhost:3300", api_key="dk-...")
# Define the three memory tiers
TIERS = {
"short_term": {
"namespace_suffix": "stm",
"decay_rate": 0.15, # Aggressive: decays within hours
"default_importance": 0.5
},
"long_term": {
"namespace_suffix": "ltm",
"decay_rate": 0.005, # Slow: decays over weeks
"default_importance": 0.75
},
"permanent": {
"namespace_suffix": "perm",
"decay_rate": 0.0, # Never decays
"default_importance": 1.0
}
}
def store_hierarchical(user_id: str, content: str, tier: str):
"""Store a memory in the appropriate tier namespace."""
config = TIERS[tier]
namespace = f"user-{user_id}-{config['namespace_suffix']}"
client.memory.store(
content=content,
namespace=namespace,
metadata={
"tier": tier,
"importance": config["default_importance"]
}
)
def recall_all_tiers(user_id: str, query: str) -> list:
"""Recall from all memory tiers and merge results."""
all_results = []
for tier_name, config in TIERS.items():
namespace = f"user-{user_id}-{config['namespace_suffix']}"
results = client.memory.recall(
query=query,
namespace=namespace,
top_k=5
)
for r in results["results"]:
r["tier"] = tier_name
all_results.append(r)
# Sort by score, with permanent tier getting a boost
all_results.sort(key=lambda x: x["score"] * (1.2 if x["tier"] == "permanent" else 1.0), reverse=True)
return all_results[:10]
# Usage
store_hierarchical("alice", "User's name is Alice Chen", "permanent")
store_hierarchical("alice", "User is working on a React migration project", "long_term")
store_hierarchical("alice", "Currently debugging a useEffect hook", "short_term")
context = recall_all_tiers("alice", "Help with React hooks")
# Returns all relevant memories, prioritizing permanent identity facts
When to Use This Pattern
- Agents that maintain long relationships with users across many sessions
- Applications that need both immediate context and historical knowledge
- Systems where storage cost matters — aggressive decay on ephemeral data saves space
- Any architecture that mirrors human memory (working, episodic, semantic)
Key Considerations
- Promote memories between tiers — repeated short-term patterns should move to long-term
- Configure decay per namespace using Dakera's decay configuration API
- Keep permanent memory small and curated — it should only contain verified identity facts
- Consider a promotion heuristic: if a fact is recalled more than N times, upgrade its tier