翻訳待ち:Show HN: Engrava – a local graph memory database for AI agents (SQLite, MIT)
AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。ソース概要:Uh oh! There was an error while loading. Please reload this page. Notifications You must be signed in to change notification settings Fork 0 Star 1 BranchesTags Open more actions menu Latest commit History 275 Commits 2…
AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。
Uh oh! There was an error while loading. Please reload this page. Notifications You must be signed in to change notification settings Fork 0 Star 1 BranchesTags Open more actions menu Latest commit History 275 Commits 275 Commits Folders and files NameName Last commit message Last commit date .github .github docs docs examples examples scripts scripts src/engrava src/engrava tests tests .commitlintrc.js .commitlintrc.js .cursorrules .cursorrules .gitattributes .gitattributes .gitignore .gitignore .releaserc.json .releaserc.json AGENTS.md AGENTS.md BRANCHING.md BRANCHING.md CHANGELOG.md CHANGELOG.md CLAUDE.md CLAUDE.md CODE_OF_CONDUCT.md CODE_OF_CONDUCT.md CONTRIBUTING.md CONTRIBUTING.md LICENSE LICENSE MANIFEST.in MANIFEST.in Makefile Makefile README.md README.md SECURITY.md SECURITY.md commit-scopes.json commit-scopes.json pyproject.toml pyproject.toml uv.lock uv.lock Repository files navigation The memory database for AI agents. Graph memory, hybrid search, and a tamper-evident thought/edge journal — one pip install, no server, no LLM. Engrava is a standalone embedded database for AI agent memory. Built on SQLite, it provides thought CRUD, edge-based knowledge graphs, embedding-based similarity search, full-text search (FTS5/BM25), and a declarative extension system — all in a single package with zero external service dependencies. Benchmark results are published, and the runs are reproducible from a separate repository. Every published run is Group A — memory_pipeline_llms: [], no language model anywhere in the memory layer. That is a property of the architecture rather than a measurement, so it holds across releases. Benchmark results — the live table: every published row with the comparability segment it belongs to. engrava-benchmark — the runner. Clone it and reproduce a result against the package from PyPI. MIT. Discussions — questions; reproduction questions belong in the Q&A category. Use Cases AI agent persistent memory Personal knowledge base Conversation storage with semantic search Research notes with associative linking Any application that needs a thought-graph with embeddings Quick Start Installation pip install engrava Optional extras: pip install 'engrava[vec]' # sqlite-vec vector search backend pip install 'engrava[embeddings-local]' # sentence-transformers embeddings (local model) pip install 'engrava[embeddings-openai]' # OpenAI-compatible embeddings API pip install 'engrava[embeddings-ollama]' # Ollama local embeddings server pip install 'engrava[embeddings-hf]' # HuggingFace Inference API embeddings Dreaming/consolidation and the knowledge graph need no extra — they are part of the base install. Basic Usage Store a memory and search for it in two calls — no IDs to generate, no record to assemble: import asyncio import aiosqlite from engrava import SqliteEngravaCore async def main() -> None: # SqliteEngravaCore wraps an open aiosqlite connection. async with aiosqlite.connect(":memory:") as conn: conn.row_factory = aiosqlite.Row store = SqliteEngravaCore(conn) await store.ensure_schema() await store.remember("Python is great for AI agents") await store.remember("SQLite needs no server") result = await store.recall("what language is good for agents?") for thought_id, score in result.results: thought = await store.get_thought(thought_id) if thought is not None: print(f"{thought.essence} (score: {score:.3f})") asyncio.run(main()) remember() stores the text as a thought (generating its ID for you) and returns the stored ThoughtRecord; recall() runs the same hybrid search as search_hybrid() and returns the ranked results. For full control — setting priority, thought type, metadata, or the cognitive cycle on a write — build a ThoughtRecord yourself and call create_thought(). From here, link thoughts with typed edges, query them with MindQL, or run the full ingest → dream → search tour in the Quick Start guide. Configuration-Driven Setup from engrava import SqliteEngravaCore # from_config opens and OWNS the connection — use it as an async context manager. async with await SqliteEngravaCore.from_config("engrava.yaml") as store: # The schema is already applied by from_config. thought = await store.get_thought("some-id") See docs/configuration.md for the full YAML schema. Upgrading Automatic schema migration runs on first connection. See the upgrade guide for compatibility notes, backup guidance, and troubleshooting steps. Features Thought CRUD Create, read, update, and archive thoughts with full lifecycle management. All models are frozen Pydantic objects — mutations happen via evolve(). Edge-Based Knowledge Graph Link thoughts with typed, weighted edges. Edge types include ASSOCIATED, DEPENDS_ON, DERIVED_FROM, CONSOLIDATED_FROM (created by dreaming), and CONTESTED_BY. Embedding Search Store embeddings alongside thoughts and search them with the built-in NumPy cosine backend or the optional sqlite-vec backend (pip install 'engrava[vec]'). Pluggable embedding providers: Provider Extra Backend SentenceTransformerProvider embeddings-local Local model via sentence-transformers OpenAICompatibleProvider embeddings-openai Any OpenAI-compatible API OllamaProvider embeddings-ollama Local Ollama server HuggingFaceProvider embeddings-hf HuggingFace Inference API CallbackProvider (built-in) Custom callable Full-Text Search (FTS5) SQLite FTS5 virtual table with BM25 ranking. Hybrid search combines vector similarity, text relevance, recency, priority, and graph connectivity. Signals that cannot run for a query are skipped and the remaining weights are redistributed. MindQL Query Language Declarative query language for the thought-graph: FIND thoughts WHERE thought_type = 'OBSERVATION' AND priority = 'P1' LIMIT 10 COUNT thoughts WHERE lifecycle_status = 'ACTIVE' SELECT thought_id, essence FROM thought WHERE thought_type = 'BELIEF' Extensible with custom commands through MindQLExecutor or an ExtensionManifest; the lifecycle hook registry is reserved and is not consulted by the core executor. Extension System Plug into the thought lifecycle via EngravaHooksProtocol. Subclass DefaultEngravaHooks when you only need selected active methods: from engrava import DefaultEngravaHooks, ThoughtRecord class MyHooks(DefaultEngravaHooks): async def on_store(self, thought: ThoughtRecord) -> ThoughtRecord: # Observe or enrich the object returned after persistence. return thought async def decay_function( self, thought: ThoughtRecord, elapsed_cycles: int ) -> float: # Supply a decay multiplier to an enabled Memory Hygiene pass. return 1.0 Core currently invokes on_store, on_retrieve, and decay_function. on_store runs after the source thought is durable; changing its return value does not rewrite the persisted row. score_function and mindql_extension_registry() remain reserved protocol methods and are not called by core. Dreaming / Memory Consolidation Built-in DreamingExtension for periodic memory consolidation — scores thoughts via configurable signals, promotes high-value entries, and creates REFLECTION thoughts by clustering semantically related thoughts and computing centroid embeddings (no LLM required). Available since 0.3.0. → See docs/benchmarks.md for reproducible evidence (synthetic benchmark suite runnable in ~5 minutes). Forgetting / Memory Hygiene The subtractive half of memory maintenance, paired with Dreaming: an opt-in, reversible, no-LLM loop that archives cold, low-signal thoughts — and, as a separately opted-in step, garbage-collects them only after both a cycle and a wall-clock restore window. OFF by default; once enabled, archived thoughts drop out of default retrieval and can be restored (restore_thought / include_archived). → See docs/memory-hygiene.md for the loop, protection, restore windows, and the honest deletion posture. Tamper-Evident Thought/Edge Journal Opt-in hash-chain journal that records thought and edge mutations (plus action status/verification_status transitions) as SHA-256-linked, before/after entries — a tamper-evident thought/edge journal, not a whole-database audit (embeddings and action creation are not covered). Off by default, one config flag to enable. Query history with store.journal.get_entries(...) and validate the chain with store.verify_journal(), which audits whatever chain is on disk independent of the current journal.enabled state — the store.journal writer handle does not exist while journaling is off, but the chain earlier sessions wrote is still in journal_entry and still needs verifying. → See docs/audit-trail.md for enabling, querying, verification, and the security model (what "tamper-evident" does and does not guarantee). Multi-Service Isolation Run multiple independent databases under one EngravaManager: from pathlib import Path from engrava import EngravaManager async with EngravaManager(data_dir=Path("./data")) as mgr: agent_a = await mgr.get_store("agent-a") agent_b = await mgr.get_store("agent-b") # Completely isolated databases MCP Server Want Engrava as a memory server for your agent? The MCP server ships as its own package, engrava-mcp — a native stdio server (no HTTP shim) with read tools, optional write tools, attachable engrava:// resources, and guided prompts, for any MCP client (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code): uvx engrava-mcp # or: pip install engrava-mcp engrava-mcp pulls engrava in transitively, so installing it also gives you the import engrava library. See the engrava-mcp package for install, client configuration, the full tool/resource/prompt reference, and read-only mode. CLI engrava --db mydata.db info # Database stats engrava --db mydata.db query "FIND thoughts WHERE thought_type = 'OBSERVATION' LIMIT 5" engrava --db mydata.db snapshot -o backup.jsonl engrava --db mydata.db restore -i backup.jsonl engrava --db mydata.db gc # Collect ARCHIVED thoughts + their edges/embeddings/actions engrava --db mydata.db migrate # Ensure schema is up-to-date engrava --db mydata.db export -o portable.json gc physically deletes ARCHIVED thoughts together with every edge touching one on either end — including edges whose other end is still live — their embeddings and the actions sourced from them, then reconciles the vector index by removing every vec0 row no embedding row owns; on a vec0-indexed store where sqlite-vec cannot be loaded — most commonly because engrava[vec] is not installed — a pass that is about to delete stops before deleting anything and exits 1 rather than stranding those vectors in an index nothing can then reach them through. engrava info now renders the same metrics snapshot contract exposed by await store.metrics(). See the CLI reference for every command and option. Architecture SQLite with WAL mode for concurrent reads Frozen Pydantic models — immutable domain objects Async-first — all I/O via aiosqlite Hook-based extension — zero monkey-patching Template method pattern — subclass SqliteEngravaCore for extended schemas Zero external services — everything runs locally in-process Documentation Documentation Index — choose a path by task: learn, build, operate, extend, or migrate Core Concepts — the mental model (thought, edge, reflection, cycle, …) — start here The Bi-temporal Model — the optional valid-time axis: query a fact as of any instant, invalidate without deleting Positioning — when Engrava is (and isn't) the right tool, and how it compares Quick Start — 5-minute setup guide Tutorial — build a small notes memory end to end Recipes — copy-paste snippets for common tasks (store a turn, retrieve context, TTL, dedup, …) Building a memory-backed agent — the end-to-end agent turn loop (ingest → retrieve → generate → consolidate) Mi [truncated for AI cost control]