A stateful memory layer that gives AI agents the ability to remember, reconcile conflicts, validate facts, and explain every decision across sessions.
Traditional AI agents fail in four critical ways:
| Problem | Description |
|---|---|
| 🔴 Context Loss | Facts are forgotten when conversations span multiple sessions |
| 🟠 Silent Inconsistencies | Contradictory facts are stored without resolution (e.g. "lives in SF" and "lives in NYC" simultaneously) |
| 🟡 Hallucinations | Agents fabricate answers instead of recalling stored memory |
| 🔵 Opaque Decisions | No explanation for why a fact was accepted, rejected, or superseded |
Memora solves all four.
- 🔐 JWT Authentication — Multi-user system with secure PBKDF2 password hashing
- 🕸️ Entity-Relationship Graph — Visual node-edge memory graph with real-time updates
- ⚖️ Conflict Detection & Resolution — Stability-aware rules distinguish stable facts (birthday) from time-varying facts (employer, city)
- 🔍 Fact Extraction — Hybrid pipeline: LLM-based (OpenAI) with rule-based offline fallback for employer, city, birthday, pet, preferences, hobbies, and name
- ✅ Validation Layer — Multi-rule validation with type checking, length limits, and plausibility guards for all properties
- 📜 Full Audit Trail — Every memory state transition (created → superseded → disputed) is logged
- 🔄 Reflection Engine — Background consolidation worker that resolves stale disputes
- 🧮 Local Vector Similarity — Offline TF-IDF matching with no external dependencies
- 📊 Interactive Dashboard — Dark-mode Streamlit UI with live graph visualization
- 🛡️ API Hardening — Rate limiting (60 req/min), OWASP security headers, input sanitization
- 📊 Memory Analytics —
/statsendpoint with property distribution and graph metrics - 🐳 Docker Compose — One-command stack with Nginx proxy and optional Prometheus monitoring
[ User Message ]
│
▼
[ Fact Extractor ] ────► Extracts Candidate Facts (LLM or Rule-based)
│
▼
[ Normalizer ] ─────────► Standardizes values (SF → San Francisco)
│
▼
[ Validator ] ──────────► Plausibility checks (age range, date format)
│
▼
[ Conflict Detector ] ──► Finds overlapping active memories
│
▼
[ Resolution Engine ] ──► Applies stability rules (supersede / dispute / merge)
│
▼
[ Memory Graph (SQLite) ] ► Persists state transitions & logs Audit Event
│
▼
[ Response Generator ] ──► Answers using resolved active profile context
Not every contradiction is the same. Memora distinguishes between stable and time-varying properties:
| Property | Stability | Conflict Behaviour |
|---|---|---|
birthday |
🔒 Stable | New value marked disputed, original stays active |
dog_name |
🔒 Stable | New value marked disputed, original stays active |
city |
🔄 Time-varying | Original marked superseded, new value becomes active |
employer |
🔄 Time-varying | Original marked superseded, new value becomes active |
preference |
🔄 Time-varying | History preserved, most recent value is active |
hobby |
🔄 Multi-value | All values coexist as active |
📍 Scenario A: Relocation & Job Change
Session 1: "I work at Google in San Francisco"
Session 2: "I just moved to New York for my new job at Meta"
Result:
employer: Google → superseded ✗
employer: Meta → active ✓
city: San Francisco → superseded ✗
city: New York → active ✓
🐶 Scenario B: Stable Fact Recall
Session 1: "My dog's name is Max"
Session 5: "What's my dog's name?"
Result: Agent answers "Max" — no hallucination
🎂 Scenario C: Stable Fact Conflict
Session 1: "My birthday is July 15th"
Session 3: "My birthday is July 20th"
Result:
birthday: July 15 → active ✓ (stable, kept)
birthday: July 20 → disputed ⚠️ (requires clarification)
🌶️ Scenario D: Preference Reversal
Session 1: "I hate spicy food"
Session 2: "I love spicy food actually"
Result: Preference history preserved, latest value is active
git clone https://github.com/NitheshK4/Memora.git
cd Memora
pip install -r requirements.txt./start.sh| Service | URL |
|---|---|
| 📊 Dashboard | http://localhost:8503 |
| 📖 API Docs | http://localhost:8002/docs |
Default login: seed_user / password123
Copy .env.example to .env and add your OpenAI key for richer fact extraction:
cp .env.example .env
# Add: OPENAI_API_KEY=sk-...Without a key, Memora runs fully offline using built-in rules.
# Start full stack (API + Frontend + Nginx)
docker compose up --build
# With Prometheus monitoring
docker compose --profile monitoring up --build| Service | URL |
|---|---|
| 🌐 Proxy | http://localhost |
| 📊 Dashboard | http://localhost:8503 |
| 📖 API Docs | http://localhost:8002/docs |
| 📊 Metrics | http://localhost:9090 (monitoring profile) |
python tests/run_all_tests.py====================================================
✅ All 26 Tests Passed (100%)
====================================================
Test coverage includes:
- Unit tests: conflict detector, resolver, validator, memory DB
- Integration tests: full pipeline, multi-session learning
- Graph tests: entity merging, JWT auth, reflection engine
- Performance tests: memory matching latency under load
Memora/
├── app/
│ ├── __init__.py # Package metadata & version
│ ├── api.py # FastAPI routes (JWT-protected)
│ ├── auth.py # PBKDF2 hashing + pure-Python JWT
│ ├── memory_agent.py # Chat orchestrator
│ ├── memory_db.py # CRUD + similarity search
│ ├── graph_store.py # Entity-Relationship graph engine
│ ├── extractor.py # Hybrid fact extraction (LLM/rules)
│ ├── conflict_detector.py# Contradiction detection
│ ├── resolver.py # Stability-aware resolution rules
│ ├── reflection.py # Background consolidation engine
│ ├── validator.py # Multi-rule type & plausibility checks
│ ├── normalizer.py # Value canonicalization
│ ├── embeddings.py # Local TF-IDF vector similarity
│ ├── vector_store.py # TF-IDF + OpenAI embedding store
│ ├── property_registry.py# Stability metadata registry
│ ├── rate_limiter.py # Sliding window rate limiting
│ └── security_headers.py # OWASP security headers
├── frontend/
│ └── app.py # Streamlit dashboard
├── tests/ # 26 automated tests
├── scripts/
│ ├── seed_db.py # Demo data seeder
│ ├── backup_db.py # Database backup utility
│ └── benchmark.py # Performance benchmarks
├── docs/
│ ├── architecture.md # System design paper
│ ├── api_spec.md # OpenAPI documentation
│ └── research_rationales.md
├── deploy/
│ ├── nginx.conf # Reverse proxy config
│ └── prometheus.yml # Metrics scraper config
├── docker-compose.yml # Full-stack orchestration
├── Dockerfile
├── SECURITY.md # Vulnerability disclosure policy
├── CONTRIBUTING.md
├── requirements.txt
└── start.sh # One-command startup script
| Method | Endpoint | Description |
|---|---|---|
POST |
/register |
Create a new user account |
POST |
/token |
Login and receive JWT token |
POST |
/chat |
Send a message and store facts |
GET |
/memories |
Get active memory profile |
GET |
/memories/history |
Full fact version history |
GET |
/memories/audit |
Complete audit event log |
GET |
/memories/search?q= |
Semantic similarity search |
POST |
/memories/clear |
Reset user memory graph |
GET |
/graph/snapshot |
ER graph node-edge data |
POST |
/reflection/trigger |
Run consolidation cycle |
GET |
/stats |
Memory analytics & property distribution |
GET |
/health |
Backend health check |
- Local Vector Similarity: TF-IDF is lightweight and offline-friendly but lacks deep semantic understanding — connect OpenAI embeddings or ChromaDB for production use
- Rule Extractor Scope: The offline regex extractor covers core scenarios; complex natural language benefits from the OpenAI key
- pgvector / ChromaDB integration for dense semantic embeddings
- Multi-entity relationship tracking (e.g. multiple pets with individual profiles)
- LLM-driven dispute resolution with explanation generation
- WebSocket-based real-time memory update streaming
- Export memory graph as JSON / RDF
- OAuth2 / SSO integration for enterprise deployments
- Configurable rate limit tiers per user role