The memory database for AI agents — graph memory, hybrid search, audit trail.
Project description
engrava
The memory database for AI agents.
Graph memory, hybrid search, and a tamper-evident audit trail — 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.
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
pip install engrava[embeddings-openai] # OpenAI-compatible embeddings
Basic Usage
import asyncio
from engrava import SqliteEngravaCore
async def main() -> None:
store = SqliteEngravaCore(":memory:")
await store.ensure_schema()
# Create a thought
thought_id = await store.create_thought(
thought_type="OBSERVATION",
essence="Python is great for AI",
content="Python's async ecosystem makes it ideal for AI agents.",
priority="P2",
source="human",
)
# Retrieve it
thought = await store.get_thought(thought_id)
print(f"Stored: {thought.essence}")
# Create an edge between thoughts
second_id = await store.create_thought(
thought_type="INSIGHT",
essence="SQLite is underrated",
content="SQLite provides ACID transactions with zero setup.",
priority="P2",
source="human",
)
await store.create_edge(thought_id, second_id, "ASSOCIATION")
# Query with MindQL
from engrava import MindQLExecutor
executor = MindQLExecutor(store)
result = await executor.execute("FIND type=OBSERVATION LIMIT 5")
for row in result.rows:
print(row)
await store.close()
asyncio.run(main())
Configuration-Driven Setup
from engrava import load_config, SqliteEngravaCore
config = load_config("engrava.yaml")
store = SqliteEngravaCore(config.db_path)
await store.ensure_schema()
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. Supports association, causation, contradiction, and custom edge types.
Embedding Search
Store embeddings alongside thoughts and perform brute-force cosine similarity search. 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, and recency scoring.
MindQL Query Language
Declarative query language for the thought-graph:
FIND type=OBSERVATION priority=P1 LIMIT 10
COUNT status=ACTIVE
SELECT thought_id, essence WHERE type=INSIGHT
Extensible with custom commands via the hook system.
Extension System
Plug into the thought lifecycle via EngravaHooksProtocol:
from engrava import EngravaHooksProtocol, ThoughtRecord, ScoringContext
class MyHooks(EngravaHooksProtocol):
async def on_store(self, thought: ThoughtRecord) -> ThoughtRecord:
# Transform thoughts before persistence
return thought
async def score_function(
self, thought: ThoughtRecord, context: ScoringContext
) -> float:
# Custom relevance scoring
return thought.confidence or 0.5
Dreaming / Memory Consolidation
Built-in DreamingExtension for periodic memory consolidation — scores
thoughts via configurable signals, promotes high-value entries, and
(v0.4.0) creates REFLECTION thoughts by clustering semantically
related thoughts and computing centroid embeddings (no LLM required).
→ See docs/benchmarks.md for reproducible
evidence (synthetic benchmark suite runnable in ~5 minutes).
Multi-Service Isolation
Run multiple independent databases under one EngravaManager:
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
CLI
engrava --db mydata.db info # Database stats
engrava --db mydata.db query "FIND 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 # Garbage-collect archived thoughts
engrava --db mydata.db migrate # Ensure schema is up-to-date
engrava --db mydata.db export -o portable.json
engrava info now renders the same metrics snapshot contract exposed by
await store.metrics().
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
SqliteEngravaCorefor extended schemas - Zero external services — everything runs locally in-process
Documentation
- Upgrade Guide — compatibility matrix, backups, and troubleshooting
- Quick Start — 5-minute setup guide
- Configuration — YAML config format and options
- Extensions — Writing custom extensions and hooks
- Observability — Metrics snapshot API and event hooks
- API Reference — Full protocol and class reference
- MindQL — Query language syntax and examples
- Known Limitations — Platform notes and constraints
Development
pip install -e ".[dev]"
ruff check src/ tests/ # Lint
ruff format --check src/ tests/ # Format check
mypy --strict src/ # Type check
pytest --cov # Test with coverage
License
MIT — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file engrava-0.3.0.tar.gz.
File metadata
- Download URL: engrava-0.3.0.tar.gz
- Upload date:
- Size: 268.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f90ed5541f689b6957880deab9b2c66f01fe64590bad5c545a156d067d24818
|
|
| MD5 |
22a32d267c87b85b500368aa23caacb8
|
|
| BLAKE2b-256 |
6172e5436309d0b9220fe213b2946d2ccbdd297e0cd01b65c2c16893d632c7a5
|
Provenance
The following attestation bundles were made for engrava-0.3.0.tar.gz:
Publisher:
release.yml on sovantica/engrava
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
engrava-0.3.0.tar.gz -
Subject digest:
9f90ed5541f689b6957880deab9b2c66f01fe64590bad5c545a156d067d24818 - Sigstore transparency entry: 1702351878
- Sigstore integration time:
-
Permalink:
sovantica/engrava@0ebf9f19dc6472f4d07a4c304525fb30d396767a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sovantica
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0ebf9f19dc6472f4d07a4c304525fb30d396767a -
Trigger Event:
push
-
Statement type:
File details
Details for the file engrava-0.3.0-py3-none-any.whl.
File metadata
- Download URL: engrava-0.3.0-py3-none-any.whl
- Upload date:
- Size: 258.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f29f311aac3b8e3b575d26823270beb297ee46a0eb8fa9971a216a3848330b7b
|
|
| MD5 |
cf36b919496214f06294250e6b93477a
|
|
| BLAKE2b-256 |
51c1706a4681964a61e20ae03ab3ee503c8bbe8d932786ec90e1d83a59cbd509
|
Provenance
The following attestation bundles were made for engrava-0.3.0-py3-none-any.whl:
Publisher:
release.yml on sovantica/engrava
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
engrava-0.3.0-py3-none-any.whl -
Subject digest:
f29f311aac3b8e3b575d26823270beb297ee46a0eb8fa9971a216a3848330b7b - Sigstore transparency entry: 1702351956
- Sigstore integration time:
-
Permalink:
sovantica/engrava@0ebf9f19dc6472f4d07a4c304525fb30d396767a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sovantica
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0ebf9f19dc6472f4d07a4c304525fb30d396767a -
Trigger Event:
push
-
Statement type: