DEV Community

John Cyriac
John Cyriac

Posted on

contextdb: a database for agentic memory — SQL, graph traversal, and vector search in one transaction

I've been building a Rust database purpose-built for agentic memory — the kind of workload where AI agents need to store decisions, find similar precedents by embedding, and traverse relationships between entities. It's called contextdb — Apache-2.0, 10-crate workspace, no unsafe.

It's not a general-purpose database. It's designed for a specific shape of problem: 10K-1M rows, sparse graphs with bounded traversal, append-heavy writes. The kind of workload you hit when building agent memory, AI coding tools, or edge AI systems.

The problem: if you're building this today, you're stitching together SQLite for state, a vector DB for embeddings, and application code for graph traversal. Three systems, three failure modes, no transactional consistency across them.

contextdb puts all three under one transaction:

BEGIN;

INSERT INTO decisions (id, agent_id, summary, embedding)
VALUES ('d-001', 'agent-7', 'Chose retry with backoff', vector([0.12, 0.85, ...]));

INSERT INTO edges (src, dst, edge_type)
VALUES ('agent-7', 'd-001', 'decided');

-- Find similar past decisions via vector search
SELECT id, summary
FROM decisions
ORDER BY embedding <=> vector([0.11, 0.83, ...])
LIMIT 5;

COMMIT;
Enter fullscreen mode Exit fullscreen mode

One query can combine all three — graph neighborhood, relational filter, vector ranking:

WITH neighborhood AS (
  SELECT b_id FROM GRAPH_TABLE(
    edges MATCH (start)-[:RELATES_TO]->{1,3}(related)
    WHERE start.id = $entity_id
    COLUMNS (related.id AS b_id)
  )
)
SELECT id, data FROM observations
INNER JOIN neighborhood n ON observations.entity_id = n.b_id
WHERE observation_type = 'config_change'
ORDER BY embedding <=> $query_embedding
LIMIT 5
Enter fullscreen mode Exit fullscreen mode

What makes it different from SQLite + extensions:

  • Vector search is built in — auto-HNSW at 1K vectors, pre-filtered search, same MVCC transaction as relational rows (not a bolted-on extension)
  • Graph traversal uses SQL/PGQ-style GRAPH_TABLE ... MATCH with bounded BFS, DAG enforcement, typed edges — not recursive CTEs
  • Policy constraints enforced by the engine: STATE MACHINE in DDL (not triggers), IMMUTABLE tables, DAG cycle prevention, PROPAGATE for cascading state changes
  • Single-file storage via redb, crash-safe
  • Bidirectional sync between instances over WebSocket (NATS transport)

Current state: v0.3.2, published on crates.io (contextdb-engine, contextdb-cli). Rust library + CLI today. Not a general-purpose database — it's optimized for the agentic memory niche and intentionally stays there.

cargo install contextdb-cli
contextdb-cli :memory:
Enter fullscreen mode Exit fullscreen mode

Links:

Python and TypeScript bindings are on the roadmap — contributions welcome.

Top comments (0)