Generated banner for Engrava
Generated logo for Engrava

Engrava

Memory frameworkOfficial Sovantica project

Created by Sovantica

Published in sovantica/engrava. Publisher page

12 GitHub stars

What it is

The memory database for AI agents - graph memory, hybrid search, tamper-evident thought/edge journal.
— the description by Sovantica

AutoGineer overview, from the brain’s own files

Engrava is an in-process memory database designed for AI agents, built on SQLite. It provides a structured way to store and retrieve agent thoughts using a graph-based model, where thoughts are linked by typed edges. The system supports hybrid search, combining vector similarity, full-text search (FTS5), recency, and priority. It includes built-in mechanisms for memory consolidation (dreaming), memory hygiene (archiving and garbage collection), and a tamper-evident journal for tracking mutations. Engrava operates as a library with no external service dependencies in its core path, allowing agents to maintain persistent, queryable state locally.

How it works

Memory model: Hybrid

AutoGineer overview, from the brain’s own files

Engrava uses a SQLite database to store thoughts and their relationships. It organizes data into thoughts and typed edges, which can be queried using the MindQL language. The system supports hybrid search by combining vector embeddings, keyword search, and metadata signals. It manages memory through a lifecycle that includes archiving and garbage collection, and it can consolidate memories into reflections. The system is extensible via hooks and provides an MCP server for integration with various AI agent frameworks.

Folders
FolderRoleFiles
.githubagent-config16
docsdocs37
examplesexamples13
scriptsscripts24
srcsource-code89
teststests201
.githooksfolder1

The agent reads

Requirements

Runtimes: Python >=3.11

Databases: SQLite

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)

Set it up

  1. This brain runs code automatically: 2 scripts. Review .githooks/commit-msg, Makefile before opening the folder in Claude Code. No step below turns a hook on for you.

    • .githooks/commit-msg: runs on git commit-msg
    • Makefile: echo "$(BLUE)>> Installing engrava + dev dependencies$(RESET)"; $(PIP) install --upgrade pip setuptools wheel; $(PIP) install -e ".[dev]"; bash scripts/install_hooks.sh; echo "$(GREEN)>> Done. Run 'make check' to verify quality gate.$(RESET)"
  2. Not scanned by AutoGineerIts dependencies are installed by pip or uv when you run it and were not scanned by AutoGineer (5 declared). https://pypi.org/project/engrava/
  3. Created by Sovantica. Published in sovantica/engrava. Licence: MIT License.

Usage

AutoGineer overview, from the brain’s own files

  • Persistent memory for autonomous AI agents
  • Personal knowledge base management
  • Conversation storage with semantic retrieval
  • Research notes with associative linking
  • Memory-backed agent development
  • Audit-trailed thought and edge tracking
“Store a new observation about a project requirement.”
The agent uses the remember() method to persist the thought, which is then indexed for future hybrid search and graph traversal.
“Retrieve relevant context for a coding task.”
The agent uses the recall() method, which performs a hybrid search across FTS5, vector, and graph signals to return ranked, contextually relevant thoughts.
“Query the memory graph for all observations with high priority.”
The agent executes a MindQL query: FIND thoughts WHERE thought_type = 'OBSERVATION' AND priority = 'P1'.
“Consolidate old memories to free up space.”
The agent triggers the DreamingExtension to cluster related thoughts and compute reflections, or uses the memory hygiene loop to archive low-signal thoughts.

Documentation by Sovantica

Engrava

The memory database for AI agents.

A queryable memory graph with bi-temporal valid-time predicates — in an in-process Python library over one SQLite file, with no generative-model call in the core write path.

Image: CI Image: PyPI Image: Python Image: License: MIT

Engrava is a standalone, in-process 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's built-in path. That is a property of the architecture's default signals and hooks rather than a measurement, unless a custom Dreaming signal or Memory Hygiene hook is configured to call one.

  • 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.

embeddings-local carries a large first-run download. It pulls sentence-transformers and torch, plus a further, separate model download (~88 MB for all-MiniLM-L6-v2, cached under ~/.cache/huggingface/hub) on first use. On Linux, the PyPI build of torch also pulls the NVIDIA CUDA libraries as dependencies: several gigabytes, most of it usable only with an NVIDIA GPU. Without one, install the CPU-only build first (see Configuration: No NVIDIA GPU for the exact command and numbers). engrava-mcp[local] is the exact same download, reached through the server package instead of this one. If you do not need semantic search in-process, pip install engrava alone (no extra, no download, no model) already gives you keyword search, the graph, and MindQL — see Configuration → Quick-start profiles for that and the Ollama-backed alternative that keeps the model out of this process entirely.

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. This store has no SearchConfig of its own, and it still ranks with the same default weights — FTS 0.30, vector 0.55, recency 0.10, priority 0.05, graph 0.00 (opt-in) — as a store built with one; see Hybrid Search. 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.

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:

ProviderExtraBackend
SentenceTransformerProviderembeddings-localLocal model via sentence-transformers
OpenAICompatibleProviderembeddings-openaiAny OpenAI-compatible API
OllamaProviderembeddings-ollamaLocal Ollama server
HuggingFaceProviderembeddings-hfHuggingFace 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's row is inserted; 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 its default signals (no LLM calls), promotes high-value entries, and creates REFLECTION thoughts by clustering semantically related thoughts and computing centroid embeddings through a deterministic structural function, not an LLM. A custom signal you register with DreamingExtension runs whatever code it contains. 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 loop whose built-in scoring makes no LLM calls, that archives cold, low-signal thoughts — the default action, reversible via restore_thought — and, as a separately opted-in step, garbage-collects them (not reversible) once both restore windows have elapsed under their non-zero defaults — a cycle count and a wall-clock duration, either of which can be configured to 0 to disable that 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.

uvx vs. a persistent install. uvx engrava-mcp (equivalently uv tool run engrava-mcp) installs into "an ephemeral virtual environment in the uv cache directory" per uv's own --help text — fine for the lexical/network profiles above, which add nothing heavier than httpx. Once you are on the local profile (engrava-mcp[local], the same sentence-transformers + torch download as engrava[embeddings-local]), uv tool install 'engrava-mcp[local]' is the better fit: it installs once into a persistent environment — the same uvx engrava-mcp invocation then reuses that installed environment instead of resolving a fresh ephemeral one — and a later uv tool upgrade engrava-mcp re-pays only the changed packages, not the whole dependency tree.

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's --format json output carries every field of the metrics snapshot exposed by await store.metrics(), with the snapshot's own schema version renamed metrics_schema_version, plus two fields the snapshot itself does not carry, db_path and database_schema_version — see Upgrade Guide. The default text output is a shorter summary of that same data, not the full snapshot.

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)

  • Migrating from another memory system — concept mapping, porting calls, bulk import, and scoping/multi-tenancy

  • Embeddings — wiring a real embedding provider (local / OpenAI / Ollama / HuggingFace / custom)

  • MCP server (engrava-mcp) — expose a store to MCP clients (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) via the standalone server package: install, run, client config, tools/resources/prompts

  • Configuration — YAML config format and options

  • Upgrade Guide — compatibility matrix, backups, and troubleshooting

  • Extensions — Writing custom extensions and hooks

  • Observability — Metrics snapshot API

  • Audit Trail — Tamper-evident hash-chain journal (enabling, querying, verifying, security model)

  • Evidence and Conflicts — model claims, provenance, contested facts, and caller-owned clarification

  • Security — trust boundaries, data egress, tenant isolation, encryption posture, and journal limits

  • Error Handling and Recovery — decide when to retry, repair input, or replace a store

  • Benchmarks — release gates, versioned observed values, and LongMemEval

  • API Reference — Full protocol and class reference

  • CLI Reference — every engrava command and option

  • Glossary — quick definitions of every Engrava term

  • MindQL — Query language syntax and examples

  • Troubleshooting — symptom → cause → fix for common errors

  • FAQ — quick answers (LLM/keys, embeddings-optional, scale, concurrency, backups, …)

  • Performance & Scaling — the vector-backend switch, bulk-ingest, and dreaming cost at scale

  • Data Lifecycle & Retention — lifecycle states, TTL, archive-vs-delete, GDPR erasure, disk reclamation

  • Deployment — process model, database files on disk, containers, graceful shutdown

  • Concurrency — the WAL single-writer model, busy timeout, and per-service isolation

  • Backup & Recovery — WAL-safe backups, snapshot vs file copy, restore verification

  • Known Limitations — Platform notes and constraints

Development

make install   # deps + dev extras + local git hooks -- from the primary checkout
make gate      # fast: hooks-active + lint + format check + type check + goldens drift, ~70s
make check     # lint + format check + type check + the full test suite with coverage (unchanged; no hooks-active, no goldens drift)

make install also wires a commit-msg hook that lints the message of the commit a squash merge creates — including on a local branch that never opens a pull request, where nothing else does. It refuses to install from a linked worktree (core.hooksPath is shared across all of them). See CONTRIBUTING.md for what it covers and what it does not.

License

MIT — see LICENSE for details.

CHANGELOG.md

Changelog

All notable changes to engrava will be documented in this file.

The format is based on Keep a Changelog 1.1.0, and this project adheres to Semantic Versioning 2.0.0.

0.7.2 (2026-10-25)

Fixed
  • build: install numpy from a wheel on Python 3.14 (eb6c68c)

  • core: close the transaction a reused derived child or edge opened (762f9e1)

  • core: quarantine the store when an outer transaction rollback fails (00c31bd)

0.7.1 (2026-10-09)

Fixed
  • docs: ship the VS Code MCP example VS Code actually reads (0a2afbb)

  • infra: build EngravaManager stores with the full configuration (5ebdc46)

  • lifecycle: keep pinned reflections through the sweep, gc and TTL (4928047)

  • mindql: extension handlers get a read-only accessor instead of the live connection (847766a)

  • mindql: read values ending in or/and, and quoted literals, correctly (c5e7842)

  • mindql: the single-SELECT guard reads SQL comments and quoted identifiers (b34fcdf)

  • search: raise the per-arm candidate pool to at least top_k (3a34d0e)

  • search: single-source the hybrid-search defaults on SearchConfig (424efe2)

0.7.0 (2026-10-02)

Added
  • cli: add remember, recall and link one-shot commands (599d58b)

  • core: add a pre-insert preparation seam and stop bypassing overrides (6ba6660)

  • core: add a public way to attach a dreaming extension (d6f2966)

  • core: guard updates with an engine-maintained revision (809b3f4)

  • release: check that main carries the newest version tag (92f9ec8)

  • release: fail a release that moves the core schema on a patch bump (bc894b8)

  • release: fail a release whose computed version disagrees with the target (984abb6)

  • release: fail a run that silently published nothing for the target (10c3d63)

Fixed
  • assert atomic rollback, not partial survival, in v20->v21 test (5854aa5)

  • clear ruff check findings on release/v0.7.0 (17 -> 0) (fac993f)

  • cli: check the schema version before recall, remember and link open a database (255b97b)

  • cli: clear the journal too when restore --clear wipes the store (dbda8b9)

  • cli: error on a corrupt database instead of hanging forever (814afb7)

  • cli: exempt reflection centroid rows from restore's identity lock (c8c2c22)

  • cli: keep the full-text index consistent on every restore (c588b0f)

  • cli: make a snapshot export observe one consistent database state (d6d31dd)

  • cli: name the database in the error message (e048343)

  • cli: read export's thought and edge tables in one transaction (281b65f)

  • cli: refresh a persisted vector index entry a merge restore replaces (1441ab3)

  • cli: refuse a colliding merge into a store that has a journal (b4912bc)

  • cli: reject a malformed --filter key as a usage error (aa0a51c)

  • cli: reject a restored centroid whose vector width disagrees (58d6f0b)

  • cli: state what gc deletes, and pin the guards that stop it (0403e2c)

  • cli: tell the two schema versions apart (5e5c2c1)

  • cli: verify embedding identity against the target, not a provider (679c5d4)

  • cli: write snapshot and export output through a temp file (e74133b)

  • core: a no-op upsert_by_hash() no longer commits the caller's pending work (d92823b)

  • core: a write waits for another process's lock again instead of failing at once (356a08a)

  • core: bound the close of a wedged connection (92bbef5)

  • core: close the connection even when cancellation lands mid-cleanup (f7d592e)

  • core: drop a stale auto-embed completion instead of installing it (494c0dd)

  • core: exempt centroid vectors from the embedding identity lock (a70bcf6)

  • core: export the exceptions the documentation says to catch (ac3d892)

  • core: keep buffered accesses when a flush cannot take the write lock (cee9673)

  • core: keep the no-op upsert from committing after the seam merge (5f8787a)

  • core: keep the original error when rollback or pragma cleanup fails (332a318)

  • core: keep the update contract under contention, and journal what a delete really removed (554b354)

  • core: make a read-modify-write a critical section across tasks (48ff5ae)

  • core: make a vector's ownership follow its thought, not its row (807874e)

  • core: make a write and its confirming read-back failure-atomic (af09cf5)

  • core: make an embedding write and its vector-index update atomic (a41f02e)

  • core: make the child deletes atomic with the parent delete again (33982b6)

  • core: recover a row update and its journal entry together (aa5acd8)

  • core: reject a negative or boolean get_edges limit (d9f2dfb)

  • core: roll back or quarantine a failed commit instead of leaving it open (cb1355f)

  • core: sample transaction ownership again before upsert_by_hash's decisive probe (7a8fd06)

  • core: say when the unembedded row survives an auto-embed failure (059efa4)

  • core: serialise the dedup probe-and-insert across connections (7bb7c6c)

  • core: skip derivation only inside the current task's own transaction window (067f28c)

  • core: stop a write-free call from committing the caller's transaction (6f622a2)

  • core: store every timestamp in one canonical UTC form (02cd72d)

  • docs: correct auto-embed durability claims in api-reference/configuration (6b6b628)

  • docs: correct EmbeddingConfig.require_embedding durability docstring (a2254e5)

  • docs: split auto-embed durability into two independent questions (4a77d8e)

  • docs: stop conflating durability with method, add missing precondition (e1c00fa)

  • docs: teach the cleanup the library ships in every example (a6c61fa)

  • domain: say whether a metrics snapshot was actually measured (918161c)

  • dreaming: compute the cohesion gate as the cosine similarity it names (a851882)

  • dreaming: roll back a reflection whose own embedding fails (2fde4af)

  • embeddings: stop a rejected first write from locking corpus identity (6f2dbc9)

  • embeddings: stop logging the embedding provider's raw error message (06b323d)

  • extensions: roll back the migration savepoint on cancellation too (c7d9708)

  • hygiene: make a failed or cancelled hygiene pass leave nothing behind (bbb1ca2)

  • infra: keep one manager caller's cancellation away from the others (60acdac)

  • infra: share one lifecycle lock across create, delete, and close_all (1a157f6)

  • infra: wait for the aiosqlite worker after a failed connect (203baf9)

  • journal: a failed derived record undoes only itself, even inside your transaction (7aebc9a)

  • journal: make create, delete and outcome writes recover together with their journal entry (68eb360)

  • migration: make a migration step apply completely or not at all (2f5a949)

  • migration: roll back legacy-history adoption's savepoint on cancellation too (304327c)

  • migration: unwind a savepoint cancelled while it opens (0324c1f)

  • mindql: match quoted values exactly, including repeated whitespace (481fbee)

  • mindql: reject a LIMIT or OFFSET too large for SQLite to store (7ce08ce)

  • release: close the gaps the last round's claims papered over (a71edc8)

  • release: one boundary around reading the target, not a longer catch list (e5b46e9)

  • release: one lookup, one claim, and close three more false passes (48ebba7)

  • release: stop the was-published gate from passing on nothing (bdeb668)

  • search: apply collapse and reflection caps to the query-less fallback (1543c7f)

  • search: bound edge retrieval and graph ranking's neighbour fetch in SQL (60f7b47)

  • search: keep search query text out of the FTS fallback logs (1db1b6c)

  • search: keep the query-less fallback's order under the reflection cap (af8f162)

  • search: stop graph ranking from double-counting a cross-chunk edge (4b2a0dd)

  • search: turn cycle recency fully off at a zero weight (ef1f87a)

  • update stale schema-version golden to 21 (4a78102)

0.6.0 (2026-08-10)

Added
  • add derived-records extension seam (c9d55cb)

  • core: add derive_existing() backfill for the derived-records seam (1c79611)

  • core: add opt-in cycle-provider seam and max_cycle accessor (29d46e5)

  • edges: add generic metadata carrier with schema v19 migration (08a4cb3)

  • extensions: add zero-dependency split modes to StructuralSplitProducer (320b88e)

  • hygiene: add a wall-clock restore window before permanent GC (35c2769)

  • hygiene: guard archival behind a minimum inactivity age and a usage-signal gate (0ce64b7)

  • search: add transaction-time recency axis with caller-supplied now (49f8c9b)

  • search: exclude archived thoughts from default retrieval (963e60c)

  • search: reject wrong-dimension query vectors and count vector-arm degradation (fe128f1)

Fixed
  • cli: cover the expiry sweep and report an unreadable snapshot (4ab31e4)

  • cli: give an invalid --service name a distinct, clean error (5f5372d)

  • cli: purge the vector index when gc collects a thought (44c6ffc)

  • cli: validate a resolved empty or default service name (6318f98)

  • cli: validate snapshot-restore input against a typed model and restore atomically (d35dc5b)

  • close Free audit source follow-ups (d919d85)

  • config: enforce uniform validation across sections and construction paths (97a9af7)

  • config: make the validated value the value that gets used (e1d7d00)

  • config: use assign-to-variable message in unknown-key rejection (69bce4e)

  • core: reject inverted valid_from/valid_until intervals (dd9305f)

  • dreaming: propagate real integrity failures during edge creation (79241c2)

  • embeddings: name the provider member a search needs instead of failing on it (5e461f6)

  • infra: harden core bootstrap and edge integrity classification (be054f6)

  • infra: keep foreign-key enforcement safe on every swap failure path (c393980)

  • infra: make the v11->v12 child-table swap atomic via a savepoint (7b9a1d0)

  • infra: write only the fields an update owns (9d72125)

  • journal: reclaim per-connection append locks with a weak-key registry (412dcd8)

  • mindql: build the passthrough guard on a value the module owns (6e8db02)

  • mindql: validate identifiers where the query is executed (d4d8111)

  • read-only: capability-separate the read-only view from the core protocol (1033a2e)

  • search: keep FTS5 MATCH valid so quoted and wildcard queries never silently drop BM25 (5c99b88)

  • search: quote exposed FTS5 boolean operators so bare queries never lose BM25 (ad7ec85)

  • sqlite: harden core migration registry (5c9ec91)

  • sqlite: harden extension migration identity and statement splitting (cfc5e95)

0.5.0 (2026-07-08)

⚠ BREAKING CHANGES
  • changelog: the in-tree MCP server is removed from engrava. The engrava[mcp] optional-dependency extra, the in-engrava engrava-mcp console script, and the in-tree server module are gone; a plain 'pip install engrava' is unaffected. The server moved to the standalone engrava-mcp package (uvx engrava-mcp), which consumes engrava's public API. Migrate per the docs/upgrade.md 0.4 -> 0.5 notes.

Added
  • core: action-outcome feedback loop and mutable action lifecycle (2008a3f)

  • core: add opt-in deterministic memory-hygiene forgetting loop (9167948)

  • core: batch/get-or-create write primitives and embed-failure visibility (e9c2021)

  • core: opt-in typed provenance-context capture at create_thought (b8b8fa3)

  • dreaming: activate consolidation — reachable scoring + live access substrate (5114f81)

  • embeddings: opt-in asymmetric query/document prefixes (12e61fb)

  • journal: expose hash-chain verification via API, CLI, and on-open gate (b26f519)

  • mindql: read-surface ergonomics — IN, boolean WHERE, ORDER BY, OFFSET, EXPLAIN, bound SELECT (eca5a74)

  • remove the in-tree MCP server (now the standalone engrava-mcp package) (1417e91)

  • search: add collapse_key de-fragmentation to hybrid retrieval (6c80277)

  • search: add metadata and visibility filters to ranked retrieval (a56fcc7)

  • search: add opt-in per-unit retention depth for collapse backfill (e72cd22)

  • search: batch read-path decode, inbound edge index, eviction visibility (0e1b81f)

Fixed
  • dreaming: add opt-in cold-start clustering fallback (35aedab)

  • lifecycle: make archived thoughts restorable to ACTIVE (88c2e3e)

  • search: apply filters/visibility in the query-less fallback arm (2f0640e)

  • search: correct the sqlite-vec backend — purge deleted vectors, fill top_k (d884052)

  • search: neutral midpoint for the degenerate min-max fusion case (815f23b)

  • use absolute GitHub links in README so PyPI does not 404 (acf56bf)

Documentation
  • changelog: curate 0.5.0 Unreleased block and mark MCP removal breaking (5cf3a78)

0.4.0 (2026-06-18)

Added
  • add bi-temporal valid-time to thoughts and edges (456bcb6)

  • add temporal query predicates and invalidate primitive (86de77f)

  • api: add remember() and recall() convenience methods on the store (be9b110)

  • mcp: add delete_thought and delete_edge tools (84b87f6)

  • mcp: add guided memory prompts (1f6fa36)

  • mcp: add MCP server with read tools (engrava[mcp] extra) (68a8085)

  • mcp: add memory filters and pagination (57357b7)

  • mcp: add write tools, opt-in read-only mode, and per-tool safety annotations (79d7604)

  • mcp: expose memory as resources (thought, stats, recent) (c54dcf7)

  • mcp: map known failures to typed, actionable tool errors (8b615cc)

  • mindql: add store-level execute_mindql entry point (1c8ffb4)

  • reflections inherit temporal extent from members (8fba769)

Fixed
  • assert plan-shape invariant for temporal queries, not scan-vs-index (0e4e176)

  • embed full thought content without duplication or silent truncation (36e08e7)

  • embeddings: retry transient errors with bounded backoff (897c46f)

  • keep quoted MindQL values as strings and reject malformed conditions (d88043d)

  • let natural-language queries reach the full-text index (bb6b729)

  • match exact table token in query-plan helpers (cd4ecc2)

  • mcp: keep query_memory parse errors FIND-only (5f4ea20)

  • mcp: map write-tool errors and complete the 0.4.0 documentation (6794436)

Changed
  • tune sqlite pragmas and add hot-path indexes (1256303)

0.3.1 (2026-06-02)

Fixed
  • vector: load sqlite-vec extension on the connection's worker thread (457d2f7)

  • vector: re-disable extension loading in finally after load attempt (e9ab267)

0.3.0 (2026-06-02)

Added
  • graph memory database — dreaming consolidation, hybrid search, audit trail (ed82259)

[0.2.0] — 2026-04-12

Breaking Changes
  • None.

Database Changes
  • Schema version bumped to core-5.

  • Added access_count, last_accessed_at, confirmation_count, consolidated_from, and visibility to the thought table.

  • Existing databases upgrade automatically through ensure_schema().

Added
  • Full-text search (FTS5) — search_fts() method with BM25 ranking on essence and content fields. Hybrid search combines vector similarity, text relevance, and recency scoring via configurable SearchConfig weights.

  • Extension system — EngravaHooksProtocol with 5 hook points (on_store, on_retrieve, score_function, decay_function, mindql_extension_registry). DefaultEngravaHooks provides no-op defaults.

  • Dreaming / memory consolidation — DreamingExtension with 5 pluggable signal types (ConfidenceSignal, ConfirmationSignal, FrequencySignal, RecencySignal, StalenessSignal) and configurable gate thresholds.

  • sqlite-vec backend — optional SqliteVecSearchBackend for hardware-accelerated vector search via the vec extra.

  • Multi-service isolation — EngravaManager for running multiple independent databases, each with its own schema, embeddings, and FTS index.

  • YAML configuration — load_config() factory, EngravaConfig with SearchConfig, DreamingConfig, EmbeddingConfig, and ServicesConfig sections.

  • 5 embedding providers — SentenceTransformerProvider, OpenAICompatibleProvider, OllamaProvider, HuggingFaceProvider, CallbackProvider.

  • MindQL enhancements — COUNT, SELECT with WHERE clauses, extensible command registry via hooks.

  • CLI enhancements — export, import, gc, migrate subcommands. Multi-service --service flag for snapshot/restore/export.

  • Read-only store — ReadOnlyEngrava wrapper that raises ReadOnlyViolationError on write attempts.

  • ExtensionManifest value object for extension discovery and registration.

  • HybridSearchResult model combining vector, FTS, and recency scores.

  • EmbeddingModelMismatchError exception for restore-time model validation.

  • Open source release: standalone repository, MIT license, GitHub Actions CI/CD, PyPI publishing.

Changed
  • Bumped version from 0.1.0 to 0.2.0.

  • pyproject.toml URLs now point to the standalone GitHub repository.

  • Description updated to "Thought-graph database for AI agents".

Fixed
  • --re-embed flag now raises an error when no embedding provider is configured instead of silently succeeding.

  • snapshot --service validates service existence before attempting export.

  • EngravaManager.get_store() uses asyncio.Lock to prevent race conditions during concurrent lazy initialization.

[0.1.0] — 2026-04-01

Breaking Changes
  • Initial release.

Database Changes
  • Initial SQLite schema introduced.

  • No downgrade guarantees; follow forward-only upgrade policy from later releases.

Added
  • Initial release (internal).

  • SqliteEngravaCore — async thought/edge/embedding/action CRUD.

  • ThoughtRecord, EdgeRecord, EmbeddingRecord, ActionRecord frozen Pydantic models.

  • 9 domain enums (ThoughtType, Priority, LifecycleStatus, EdgeType, etc.).

  • Brute-force cosine similarity embedding search.

  • MindQLParser and MindQLExecutor — FIND and basic query support.

  • CLI with info, query, snapshot, restore subcommands.

  • Schema migration support via ensure_schema().

402 files · 357 not served here

Advantages

Limitations

Security

Risk level: Low risk

This brain runs

Git hooks (1)

  • .githooks/commit-msg (commit-msg): runs on git commit-msg

Agent instructions that run or fetch something (4)

  • AGENTS.md: Run `git commit` and it fires on the patterns it checks for.
  • CLAUDE.md: pip install -e ".[dev]"
  • CLAUDE.md: Run a clean test suite locally before pushing;
  • CLAUDE.md: Branch from `dev`, follow Conventional Commits, run the local quality gate before pushing.

Install scripts (1)

  • Makefile (make install): echo "$(BLUE)>> Installing engrava + dev dependencies$(RESET)"; $(PIP) install --upgrade pip setuptools wheel; $(PIP) install -e ".[dev]"; bash scripts/install_hooks.sh; echo "$(GREEN)>> Done. Run 'make check' to verify quality gate.$(RESET)"
  • Low risk: scripts-present (.githooks/commit-msg)
  • Low risk: network-instructions (CLAUDE.md:40)
  • Low risk: network-instructions (pyproject.toml:98)
  • Low risk: scripts-present (scripts/install_hooks.sh)

Attribution and licence

Created by
Sovantica
Declared authors
  • Sovantica (declared in pyproject.toml)
Publisher
Sovantica (Official Sovantica project)
Source
sovantica/engrava · commit f6a8b73
Licence
MIT License (files served here)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Sovantica.

Install from source

357 of its files are not served here, so there is no ZIP. sovantica/engrava at f6a8b73