{"id":"d9f1b356-f884-4c00-86fc-8a379a5389be","slug":"amnis","kind":"mcp","name":"amnis","summary":"☀️ Persistent Memory + RAG + Wiki Compilation for AI Agents — MCP server + Web UI with interactive knowledge graph","owner":"mandoof1","repoUrl":"https://github.com/mandoof1/amnis","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-06-15T09:45:42.000Z","addedAt":"2026-10-21T04:41:56.988Z","logoUrl":"https://avatars.githubusercontent.com/u/72626983?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["memory-knowledge","search","cloud-infra"],"tags":["ai-agents","knowledge-graph","llm","memory","python","rag"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-21T04:48:09.780Z","sample":false,"url":"https://conduits.dev/tools/amnis","language":"Python","transports":["stdio"],"install":{"pypi":"amnis"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Amnis ☀️\n\n**Persistent Memory + RAG + Wiki Compilation for AI Agents**\n\nAmnis is a three-layer memory system that gives AI agents long-term, structured knowledge across sessions. It plugs into any MCP-compatible client (Hermes, Claude, etc.) and provides a self-hosted web dashboard for visualization.\n\n---\n\n## Why Amnis?\n\nLLMs are stateless. Every conversation starts from zero. Amnis fixes that by adding:\n\n| Layer | Purpose | Backend |\n|-------|---------|---------|\n| **Memory Store** | Persistent facts, preferences, events with categories, importance, tags | SQLite |\n| **RAG Engine** | Hybrid search over local documents (markdown notes, code, plain text) | ChromaDB + sentence-transformers + FTS5 |\n| **Wiki Compiler** | Karpathy-style structured knowledge pages auto-generated from all sources | Markdown + cross-refs |\n\nTogether, these create a **personal knowledge graph** that grows smarter over time.\n\n---\n\n## Features\n\n- **Hybrid RAG search** — Reciprocal Rank Fusion (RRF) blending semantic (ChromaDB) + keyword (FTS5) results for precision\n- **Heading-aware chunking** — Respects H1–H6 boundaries so sections stay intact\n- **Episodic memory** — Chronological event log with auto-pruning, outcome tracking, and per-episode importance\n- **Reflection hierarchy** — Observations auto-clustered into mid-level themes (Stanford Generative Agents paper)\n- **Working memory** — In-memory ring buffer for agent scratchpad, with JSON persistence and episodic flush\n- **Pruning pipeline** — Low-importance, stale, and near-duplicate fact cleanup with confidence decay (0.98^days)\n- **Contradiction detection** — Polarity-based flagging of conflicting facts\n- **Semantic dedup** — Cosine-similarity merging of near-identical memories\n- **Web UI** — Dashboard, interactive knowledge graph, memory browser, wiki viewer\n- **MCP server** — 18+ tools for agent integration\n\n---\n\n## Research Foundation\n\nAmnis is built on published research across cognitive architectures, generative agents, information retrieval, and episodic memory. Every layer maps to a specific paper or finding.\n\n### CoALA Framework (Princeton 2023)\n\nThe [Cognitive Architectures for Language Agents](https://arxiv.org/abs/2309.02427) paper defines four memory types for AI agents. Amnis implements all four as concrete backends:\n\n| CoALA Memory Type | Amnis Implementation | Backend |\n|---|---|---|\n| **Working Memory** — agent's scratchpad for current context | `amnis/memory/working.py` — ring buffer with push/get/pop/clear, JSON persistence, automatic eviction at 20 slots, `flush_to_episodic()` for persisting transient context | In-memory + JSON file |\n| **Episodic Memory** — autobiographical recall of past interactions | `amnis/memory/episodic.py` — timestamped event log with outcome tracking (success/failure/neutral), structured results, session-scoped queries, auto-pruning | SQLite (`conversation_logs`) |\n| **Semantic Memory** — facts, preferences, domain knowledge | `amnis/memory/store.py` + `amnis/rag/engine.py` — categorized facts with importance scoring (1–10), confidence tracking, tags, hybrid RAG search using Reciprocal Rank Fusion | SQLite (`memory_facts`) + ChromaDB + FTS5 |\n| **Procedural Memory** — how to act, workflows, tool selection | Wiki Compiler (`amnis/wiki/compiler.py`) — auto-generated structured knowledge pages cross-referenced across all three layers | Markdown wiki |\n\n### Generative Agents (Stanford 2023)\n\nThe Stanford paper on [Generative Agents: Interactive Simulacra of Human Behavior](https://arxiv.org/abs/2304.03442) found that **removing reflection broke emergent behaviors** — agents stopped forming high-level beliefs from raw observations. Amnis implements a reflection hierarchy in `amnis/memory/consolidation.py`:\n\n```\nRaw observations → Embedding clustering (cosine >0.75) → Theme synthesis → Stored as `theme` facts\n```\n\n- Up to 5 theme clusters per consolidation run\n- Existing themes are reinforced (confidence +0.05, importance +1) rather than duplicated\n- Themes carry cross-references to source observations for full traceability\n\n### Episodic Memory (arXiv 2024)\n\nThe [Episodic Memory is the Missing Piece for Long-Term LLM Agents](https://arxiv.org/abs/2502.06975) paper identifies five required properties for episodic memory. Amnis meets all five:\n\n| Property | Amnis Implementation |\n|---|---|\n| Long-term storage | SQLite persistence across sessions with configurable retention (default 180 days) |\n| Explicit reasoning | `amnis_episodic_recall` MCP tool returns structured episodes with summaries, topics, and outcome |\n| Single-shot learning | Each `log_episode()` call encodes a unique experience from one exposure |\n| Instance-specific content | Every episode captures full role + content + timestamp + outcome |\n| Contextual relations | Episodes are bound to `session_id`, ranked by importance, filterable by outcome |\n\n### Hybrid Search with RRF\n\nAmnis uses **Reciprocal Rank Fusion** (k=60) to blend semantic search (ChromaDB cosine similarity) with keyword search (SQLite FTS5 full-text search). This technique, widely cited in the RAG literature, ensures chunks must rank well in **both** methods to score highly:\n\n```\nrrf_score(chunk) = 1/(60 + rank_semantic) + 1/(60 + rank_keyword)\n```\n\nCombined with **heading-aware chunking** (respects H1–H6 boundaries, configurable via `chunk_size`/`chunk_overlap`), this preserves document structure during ingestion — sections stay intact rather than being split mid-paragraph.\n\n### Memory Consolidation Pipeline\n\nInspired by the Mem0/Letta agent memory frameworks and the Generative Agents consolidation process, Amnis runs a background pipeline at `amnis/memory/consolidation.py`:\n\n1. **Extract** — scan recent conversation logs, extract structured `MemoryFact` records with computed importance scores\n2. **Contradiction detection** — polarity scoring flags facts with opposite sentiment on the same topic, confidence is reduced on both\n3. **Semantic dedup** — cosine similarity >0.9 merges near-identical facts (longer/more specific version wins)\n4. **Reflect** — cluster observations into theme-level beliefs (Stanford finding)\n5. **Prune** — decay confidence by 0.98^days since last access, remove stale/low-importance/near-duplicate facts at `amnis/memory/pruning.py`\n\n### Disk Impact\n\nAll of this runs in **~5.9 MB** for a typical setup (242 memories + 425 RAG chunks + 32 wiki pages). Zero new dependencies beyond ChromaDB, sentence-transformers, and SQLite.\n\n```\nMemory facts (SQLite)      ~100 KB / 1,000 facts\nEpisodic logs (SQLite)      ~50 KB / 1,000 episodes\nChromaDB vectors           ~2 MB / 500 chunks\nFTS5 keyword index         ~1 MB / 500 chunks\nWiki pages (markdown)     ~200 KB / 50 pages\n```\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                      Amnis Core                              │\n│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐   │\n│  │   Memory     │  │    RAG       │  │     Wiki         │   │\n│  │   Store      │  │   Engine     │  │   Compiler       │   │\n│  │  (SQLite)    │  │ (ChromaDB    │  │   (Markdown)     │   │\n│  │              │  │  + FTS5)     │  │                  │   │\n│  └──────┬───────┘  └──────┬───────┘  └────────┬─────────┘   │\n│         │                 │                   │              │\n└─────────┼─────────────────┼───────────────────┼──────────────┘\n          │                 │                   │\n          ▼                 ▼                   ▼\n┌─────────────────────────────────────────────────────────────┐\n│                    MCP Server (stdio)                        │\n│  18+ tools: remember, recall, forget, search, hybrid-search,│\n│  episodic-log, episodic-recall, prune, consolidate,         │\n│  compile-wiki, wiki_query, status, ...                      │\n└─────────────────────────────────────────────────────────────┘\n                              ▲\n                              │ MCP / HTTP\n              ┌───────────────┼───────────────┐\n              ▼               ▼               ▼\n       ┌──────────┐    ┌───────────┐   ┌──────────┐\n       │  Hermes  │    │  Web UI   │   │  Other   │\n       │  Agent   │    │ (port     │   │  MCP     │\n       │          │    │  8799)    │   │  Clients │\n       └──────────┘    └───────────┘   └──────────┘\n```\n\n---\n\n## Quick Start\n\n### Prerequisites\n- Python 3.11+\n- ~2GB RAM for embedding model (all-MiniLM-L6-v2, 33MB)\n\n### Install\n\n```bash\ngit clone https://github.com/mandoof1/amnis.git\ncd amnis\n\npython3 -m venv env\nsource env/bin/activate          # fish: source env/bin/activate.fish\npip install -e .\n\n# For the test suite and linter:\npip install -e \".[dev]\"\n```\n\nThis installs an `amnis` command on your PATH. `python -m amnis ...` works\nidentically everywhere below.\n\n### Initialize & Run\n\n```bash\namnis init            # create data dirs, index notes, compile the wiki\namnis status          # health and size of every layer\namnis server          # MCP stdio server (this is also the default)\namnis web             # dashboard on http://127.0.0.1:8799/\n```\n\n### Upgrading from 0.1\n\n0.1 had no keyword index for memories, so recall fell back to a substring\nmatch. Build the index once:\n\n```bash\namnis reindex\n```\n\nThe database schema migrates itself on first run — two columns are added and\nthe missing indexes are created in place. Nothing is dropped or rewritten.\n\n---\n\n---\n\n## CLI Commands\n\n| Command | Description |\n|---------|-------------|\n| `init` | Create data dirs, index notes, compile the wiki |\n| `server` | Run the MCP stdio server (default when no command is given) |\n| `web [--host H] [--port P]` | Run the dashboard |\n| `remember \"fact\" [-c CATEGORY] [-i 1-10] [-t a,b] [--context X]` | Store a memory |\n| `recall [\"query\"] [-c CATEGORY] [-n N] [-m MIN] [-t a,b] [--no-semantic]` | Retrieve memories |\n| `forget <memory_id>` | Delete a memory and everything derived from it |\n| `search \"query\" [-n N] [--mode hybrid\\|semantic\\|keyword]` | Search indexed documents |\n| `index <path> [--origin note\\|wiki\\|memory\\|compiled]` | Index a single file |\n| `index-notes` | Index everything under the notes directory |\n| `index-wiki` | Index the wiki directory |\n| `reindex` | Rebuild the memory keyword index |\n| `compile-wiki [topic ...]` | Build wiki pages |\n| `wiki-query \"question\"` | Ask the wiki a question |\n| `wiki-lint` | Report stale, sourceless, and duplicate pages (exit 1 if any) |\n| `consolidate` | Extract facts from recent logs, then reflect |\n| `prune [--dry-run]` | Decay, deduplicate, and prune the memory store |\n| `episodic-log <session> <role> <content>` | Log a conversation turn |\n| `episodic-recall [--session-id S] [--topic T] [--role R] [-n N]` | Retrieve episodes |\n| `episodic-prune [--days N]` | Drop episodes past the retention window |\n| `status` | Show memory/RAG/wiki/episodic stats |\n\nEvery command accepts `--json` for machine-readable output.\n\n---\n\n## MCP Tools (for Hermes, Claude, etc.)\n\nConfigure in your MCP client's config (Hermes `config.yaml` shown):\n\n```yaml\nmcp_servers:\n  amnis:\n    command: /path/to/amnis/env/bin/python\n    args: [\"-m\", \"amnis.server.mcp\"]\n```\n\nAll 23 tools generate their JSON Schema from Python type hints, so a tool's\nsignature and its advertised schema cannot drift apart.\n\n### Memory Tools\n\n| Tool | Description |\n|------|-------------|\n| `amnis_remember` | Store a fact with category, importance (1-10), tags |\n| `amnis_recall` | Recall memories by meaning and keyword |\n| `amnis_update_memory` | Edit a memory in place, keeping its ID and history |\n| `amnis_forget` | Delete a memory and its wiki mirror and vectors |\n| `amnis_memory_stats` | Totals, category breakdown, average importance |\n| `amnis_consolidate` | Extract facts from conversation logs, then reflect |\n| `amnis_reindex_memories` | Rebuild the memory keyword index |\n| `amnis_prune_memory` | Cleanup pipeline (decay, stale, duplicates); `dry_run` supported |\n\n### Search Tools\n\n| Tool | Description |\n|------|-------------|\n| `amnis_search` | Semantic search, with an optional metadata filter |\n| `amnis_hybrid_search` | RRF fusion of semantic and FTS5 keyword search |\n| `amnis_index_file` | Add one file to the vector store |\n| `amnis_index_notes` | Index the whole notes directory |\n| `amnis_rag_stats` | Chunk count, source count, embedding model |\n| `amnis_list_sources` | List indexed documents, filterable by origin |\n\n### Episodic Tools\n\n| Tool | Description |\n|------|-------------|\n| `amnis_episodic_log` | Log a turn, auto-extracting topics and a summary |\n| `amnis_episodic_recall` | Retrieve episodes by session, topic, or role |\n| `amnis_episodic_stats` | Episode count, session count, date range |\n| `amnis_episodic_prune` | Drop episodes past the retention window |\n\n### Wiki Tools\n\n| Tool | Description |\n|------|-------------|\n| `amnis_compile_wiki` | Build wiki pages from notes and memory |\n| `amnis_wiki_query` | Ask the wiki a question |\n| `amnis_wiki_lint` | Find stale pages, missing sources, duplicate titles |\n| `amnis_wiki_stats` | Page count, distinct source count, last compile |\n\n### System Tools\n\n| Tool | Description |\n|------|-------------|\n| `amnis_status` | Health of all layers; reports `degraded` per-layer rather than failing |\n\n---\n\n## Web UI\n\n```\nhttp://127.0.0.1:8799/\n```\n\n**Seven views:**\n\n- **◈ Dashboard** — live stats per layer, recent memories, category distribution\n- **✦ Memories** — browse, search, filter; edit in place without losing IDs\n- **⌕ Search** — hybrid / semantic / keyword search with the real ranking signal shown\n- **⬡ Graph** — knowledge graph of memories, wiki pages, and documents\n- **▤ Wiki** — page list plus a rendered markdown viewer with working `[[wiki links]]`\n- **◷ Episodes** — logged conversation turns, filterable by session and topic\n- **⚙ Maintenance** — consolidate, prune (with a dry-run preview), reindex\n\nKeyboard: `Ctrl/Cmd+K` command palette, `1`–`7` to switch views, `n` new memory,\n`/` jump to search, `r` refresh.\n\nThe dashboard is a **single self-contained HTML file** — no CDN scripts, no\nwebfonts, no outbound requests of any kind. The graph is a small canvas force\nsimulation rather than a 490 KB third-party bundle, and it cools to zero CPU\nonce laid out. Light, dark, and system themes.\n\n---\n\n## Data Layout\n\n```\n~/amnis/\n├── data/                   # or $AMNIS_DATA_DIR\n│   ├── memory.db           # SQLite: facts, wiki pages, documents, episodes\n│   ├── keyword.db          # SQLite FTS5: chunk + memory keyword indexes\n│   ├── chroma/             # ChromaDB vector embeddings\n│   ├── notes/              # Your source documents (indexed)\n│   ├── wiki/               # Compiled .md wiki pages\n│   │   └── facts/          # One .md mirror per stored memory\n│   └── working_memory.json # Working-memory scratchpad\n├── env/                    # Python environment\n└── .env                    # Optional: AMNIS_* overrides\n```\n\nAll data is **local-first**. Nothing leaves your machine.\n\n---\n\n## Configuration\n\nEvery setting is an environment variable prefixed `AMNIS_`, or a line in a\n`.env` file in the working directory. All are optional.\n\n```bash\n# Paths — everything else derives from AMNIS_DATA_DIR unless set explicitly\nexport AMNIS_DATA_DIR=~/custom/amnis/data\nexport AMNIS_NOTES_DIR=~/Documents/Notes      # default: $AMNIS_DATA_DIR/notes\nexport AMNIS_WIKI_DIR=~/custom/wiki           # default: $AMNIS_DATA_DIR/wiki\n\n# Retrieval\nexport AMNIS_EMBEDDING_MODEL=all-MiniLM-L6-v2\nexport AMNIS_CHUNK_SIZE=512\nexport AMNIS_CHUNK_OVERLAP=64                 # must be < chunk_size\nexport AMNIS_RRF_K=60\n\n# Memory behaviour\nexport AMNIS_IMPORTANCE_KEYWORDS='[\"rust\",\"kubernetes\"]'   # +1 importance\nexport AMNIS_DEDUP_SIMILARITY_THRESHOLD=0.85\nexport AMNIS_CONFIDENCE_DECAY_RATE=0.98\nexport AMNIS_PRUNE_UNACCESSED_DAYS=60\n\n# Server\nexport AMNIS_HOST=127.0.0.1\nexport AMNIS_PORT=8799\nexport AMNIS_API_TOKEN=...                    # require X-Amnis-Token on writes\nexport AMNIS_ALLOW_INDEX_OUTSIDE_NOTES=false  # confine /api/index-file\n```\n\n`amnis status` lists any `AMNIS_*` variable that no setting consumes, so a\ntypo surfaces instead of being silently ignored.\n\nThere is no `config.yaml`; `amnis/config.py` is the single source of truth\nfor the schema.\n\n### Security note\n\nThe dashboard binds to `127.0.0.1` and its read endpoints are unauthenticated.\nIf you expose it beyond localhost, set `AMNIS_API_TOKEN` — every mutating\nendpoint then requires a matching `X-Amnis-Token` header. `/api/index-file`\nrefuses paths outside the notes and wiki directories unless you opt out.\n\n---\n\n## Systemd Service (Auto-start on Linux)\n\nCreate `~/.config/systemd/user/amnis-web.service`:\n\n```ini\n[Unit]\nDescription=Amnis web dashboard\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=%h/amnis/env/bin/python -m amnis web\nWorkingDirectory=%h/amnis\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n```\n\n```bash\nsystemctl --user daemon-reload\nsystemctl --user enable --now amnis-web\nsystemctl --user status amnis-web\n```\n\n`%h` expands to your home directory, so the unit is not user-specific.\n\n---\n\n## Development\n\n```bash\npip install -e \".[dev]\"\npytest          # 79 tests, ~2s (the vector layer is stubbed out)\nruff check .\nruff format --check .\n```\n\nCI runs the same three commands on Python 3.11, 3.12, and 3.13, then builds a\nwheel and asserts every subpackage is actually inside it.\n\n---\n\n---\n\n## Example Workflow\n\n```bash\n# 1. Index your notes (any markdown/text directory)\namnis index-notes\n\n# 2. Store some explicit memories\namnis remember \"Prefers dark mode in all editors\" -c preference -i 8 -t ui,config\namnis remember \"Hermes Agent uses FastAPI + MCP stdio\" -c fact -i 7 -t project,architecture\n\n# 3. Run consolidation to extract facts from conversation logs\namnis consolidate\n\n# 4. Compile the wiki from memories + notes\namnis compile-wiki\n\n# 5. Hybrid search\namnis search \"memory architecture\" --mode hybrid\n\n# 6. Query the wiki\namnis wiki-query \"What are the key architectural decisions?\"\n\n# 7. In Hermes/Claude, just ask naturally:\n#   \"What did I say about dark mode preference?\"\n#   \"Search my notes for 'memory consolidation'\"\n#   \"Compile the wiki for the 'architecture' topic\"\n```\n\n---\n\n## Roadmap\n\n- [ ] Incremental note indexing (watch for file changes)\n- [ ] Graph export (GraphML, JSON) for external tools\n- [ ] Multi-vault support\n- [ ] Auth proxy for remote web UI access\n- [ ] Plugin system for custom memory types\n- [ ] High-level belief synthesis across theme clusters\n\n---\n\n## Screenshots\n\n![Amnis Dashboard](assets/screenshots/dashboard.png)\n*Dashboard: stats cards, recent memories feed, memory-by-category bar chart*\n\n![Amnis Memory Graph](assets/screenshots/graph.png)\n*Interactive knowledge graph showing memory cluster relations*\n\n---\n\n## License\n\nMIT — use freely, contribute back if you can. See [LICENSE](LICENSE).\n\n---\n\n## Credits\n\nBuilt on:\n- [ChromaDB](https://www.chromadb.com/) — vector database\n- [sentence-transformers](https://www.sbert.net/) — embeddings\n- [FastAPI](https://fastapi.tiangolo.com/) — web framework\n- [SQLAlchemy](https://www.sqlalchemy.org/) — persistence, plus SQLite FTS5 for keyword search\n- [MCP](https://modelcontextprotocol.io/) — agent protocol\n\nThe dashboard has no frontend dependencies: the graph, markdown renderer, and\ncommand palette are all hand-written and ship inside a single HTML file.\n\n## Research\n\nA comprehensive research report on AI Memory and RAG architectures — including how Amnis maps each academic finding to production code — is available at:\n\n➡️ **[docs/research-memory-rag.md](docs/research-memory-rag.md)**\n\nGenerated by NotebookLM from 44 sources (CoALA, Generative Agents, Mem0, Letta, and more), with implementation mapping for every layer of the Amnis system.\n\n---\n\n*Memory is how agents get smarter over time.*\n"}