A three-layer persistent memory system for AI agents.
Knowledge graph + daily notes + tacit knowledge, with automated fact extraction, contradiction detection, and recency-scored retrieval. Built in bash, no dependencies beyond jq.
Key insight: Memory is infrastructure, not a feature. Embeddings measure similarity, not truth. You need structure, timestamps, and maintenance.
Inspired by @rohit4verse's architecture.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RETRIEVAL LAYER β
β retrieve-memory.sh β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββ β
β β Entity βββ Summary βββ Fact βββ Daily β β
β β Match β β Load β β Search β β Notes β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββ β
β Cascading stages with recency scoring β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β STORAGE LAYERS β
β β
β Layer 1: Knowledge Graph memory/entities/ β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β alice/items.json β atomic facts β β
β β alice/summary.md β weekly snapshot β β
β β acme-corp/items.json β β
β β acme-corp/summary.md β β
β β index.json β metadata index β β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Layer 2: Daily Notes memory/YYYY-MM-DD.md β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β Raw timeline. Written continuously. β β
β β Durable facts extracted β Layer 1 β β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Layer 3: Tacit Knowledge MEMORY.md β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β How your human operates. Preferences, β β
β β patterns, communication style. β β
β ββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β COMPOUNDING ENGINE β
β β
β Extraction (every 30 min) Synthesis (weekly) β
β ββββββββββββββββββββββ ββββββββββββββββββββββ β
β β Scan sources β β Rewrite summaries β β
β β Extract facts β β Resolve conflicts β β
β β Dedup + validate β β Prune old facts β β
β β Detect conflicts β β Update MEMORY.md β β
β ββββββββββββββββββββββ ββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Clone the repo
git clone https://github.com/Martian-Engineering/agent-memory.git
cd agent-memory
# Bootstrap the memory directory
bash setup.sh ~/my-workspace/memory
# Add your first fact
bash ~/my-workspace/memory/pipelines/add-fact.sh alice person "Alice is the lead engineer at Acme Corp" manual
# Add a relationship edge
bash ~/my-workspace/memory/pipelines/add-edge.sh alice person "Alice works at Acme Corp" works_at acme-corp manual
# Build the entity index
bash ~/my-workspace/memory/pipelines/build-entity-index.sh
# Retrieve context
bash ~/my-workspace/memory/pipelines/retrieve-memory.sh "what does alice do"Set MEMORY_HOME to point at your memory directory:
export MEMORY_HOME=~/my-workspace/memoryAll scripts auto-detect paths from their own location, but MEMORY_HOME overrides when set.
Every important person, company, or project gets a folder:
memory/entities/
alice/
items.json β timestamped atomic facts
summary.md β weekly-rewritten snapshot
acme-corp/
items.json
summary.md
index.json β metadata for all entities
Atomic facts are the source of truth:
{
"id": "uuid",
"content": "Alice got promoted to VP of Engineering",
"source": "conversation",
"sourceRef": "session-123",
"entityType": "person",
"createdAt": "2026-01-28T23:00:00Z",
"status": "active",
"supersedes": null,
"edge": null
}Nothing is ever deleted. When facts change, the old fact is marked historical and the new one links back via supersedes. The knowledge graph preserves how understanding evolves.
Optional structured edges enable graph traversal:
{
"content": "Alice works at Acme Corp",
"edge": {
"subject": "alice",
"predicate": "works_at",
"object": "acme-corp"
}
}The raw timeline. Write continuously throughout the day β session notes, decisions, context. Durable facts are extracted into Layer 1 by the automated pipeline.
Not facts about the world β facts about your human. Communication preferences, work patterns, tool preferences. Updated manually or by synthesis when patterns emerge.
Two automated processes maintain the system:
Scans your data sources (conversation logs, meeting notes, transcripts) for durable facts. Uses the validated wrapper for automatic deduplication and contradiction detection.
See prompts/extract-facts.md for the extraction prompt template.
For each entity:
- Reviews all facts in
items.json - Rewrites
summary.mdwith current state - Marks contradicting facts as historical
- Prunes old historical facts (truncates, never deletes)
- Updates
MEMORY.mdif new patterns emerge
See prompts/weekly-synthesis.md for the synthesis prompt template.
bash memory/pipelines/retrieve-memory.sh "what is alice working on"Cascading stages:
- Entity matching β Searches
index.jsonfor entities matching query terms - Summary loading β Loads
summary.mdfor matched entities (up to 5), sorted by recency - Fact search β If insufficient results, searches all
items.jsonfor matching active facts (up to 10) - Daily notes fallback β If still insufficient, searches recent daily notes (last 7 days)
Recency scoring uses exponential time decay:
score = e^(-Ξ» Γ days_old) where Ξ» = ln(2) / half_life
| Age | Score |
|---|---|
| Today | 1.000 |
| 1 day | 0.977 |
| 1 week | 0.871 |
| 30 days (half-life) | 0.500 |
| 60 days | 0.250 |
| 90 days | 0.125 |
Configure via RECENCY_HALF_LIFE_DAYS (default: 30).
The retrieval tool logs which entities and facts get accessed most often:
bash memory/pipelines/report-hot-facts.shadd-fact-validated.sh wraps fact insertion with three safety layers:
- Deduplication β Jaccard similarity (word overlap). Facts >70% similar to existing active facts are rejected.
- Contradiction detection β Anchor pattern matching. When "Alice works at X" arrives and "Alice works at Y" already exists, the old fact is automatically marked
historical. - Write rules β Rejects low-signal facts: too short (<15 chars), transient states ("is tired"), vague language ("might be", "probably").
# All four outcomes:
bash pipelines/add-fact-validated.sh alice person "Alice joined Acme as CTO" conversation
# β ADDED: Added fact abc-123 to alice
bash pipelines/add-fact-validated.sh alice person "Alice joined Acme as CTO" conversation
# β DEDUPE: New fact is 1.00 similar to existing: "Alice joined Acme as CTO..."
bash pipelines/add-fact-validated.sh alice person "Alice works at NewCorp now" conversation
# β SUPERSEDED: Added fact def-456, marked abc-123 historical
bash pipelines/add-fact-validated.sh alice person "Alice is tired" conversation
# β REJECTED: Contains transient/vague pattern: 'is tired'The system implements two complementary decay mechanisms:
- New facts contradicting old ones mark the older fact
historical - Weekly synthesis rewrites summaries focusing on
activefacts - Historical facts get brief mentions ("Previously worked at X, now at Y")
- Facts older than 6 months with
historicalstatus get content truncated
Exponential time decay ensures newer facts surface first in search results:
score = e^(-Ξ» Γ days_old) where Ξ» = ln(2) / 30
Why both: Semantic decay adds LLM judgment about relevance. Recency scoring adds temporal ordering. A fact from 3 months ago that was never contradicted should rank higher than a trivial fact from yesterday.
agent-memory/
README.md β This file
LICENSE β MIT
setup.sh β Bootstrap script
pipelines/
add-fact.sh β Low-level fact insertion
add-fact-validated.sh β Validated wrapper (use this)
add-edge.sh β Structured relationship edges
retrieve-memory.sh β Tiered retrieval + recency scoring
build-entity-index.sh β Rebuild index.json
checkpoint-save.sh β Save session state
checkpoint-load.sh β Load session state
report-hot-facts.sh β Access frequency reports
update-memory-status.sh β Maintenance logging
prompts/
extract-facts.md β Extraction pipeline docs
extract-facts-task.md β Extraction cron task
weekly-synthesis.md β Synthesis pipeline docs
weekly-synthesis-task.md β Synthesis cron task
templates/
entities/
README.md β Schema documentation
index.json β Empty starter
MEMORY-template.md β Layer 3 template
- bash (4.0+)
- jq β JSON processing
- uuidgen β Fact ID generation (available on macOS and most Linux)
No cloud services, no API keys, no database. Just files.
Architecture inspired by @rohit4verse's thread on persistent memory for AI agents (January 2026).
Built by Martian Engineering.
MIT