Model or dataset
JordyZomer/lemmalog avatar
JordyZomer/lemmalog

lemmalog: a Datalog memory engine for LLM agents, with an MCP server

A Datalog engine for LLM agent memory: stratified rules, provenance-tracked facts, incremental derivation, and an MCP server that lets your harness use it as a shared brain.

311 stars29 forksRustMIT

At a glance

What is it?
lemmalog turns agent memory into a deductive database: base facts from extraction, stratified rules that derive closures and contradictions, provenance on every fact, and an MCP server that exposes the engine to Claude Code and Kimi CLI. It is a Rust crate at 0.2.0 under MIT, last pushed on 2026-09-15.
Who is it for?
Adopt lemmalog if your agent work involves long investigations, audits or multi-agent searches where you need to ask why a conclusion holds and retract a wrong fact without rebuilding everything. Do not adopt it if you want a drop-in vector store replacement with no rule authoring, or if you need the leapfrog triejoins and DBSP streaming deltas, which the README lists as future phases.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What lemmalog replaces, and for whom

The README states the thesis directly: an agent's memory should be a deductive database. The agent builds what the project calls a verifiable model of what it knows and reasons mechanically over how that knowledge changes, rather than trying to remember better than a vector store. That framing matters because it defines the failure it targets. A vector store returns passages that look similar to a query. It cannot tell you that two entities are the same, that a fact was superseded three turns ago, or that two derived conclusions contradict each other. lemmalog treats those as derivations over rules.

The intended user is someone building long-running agent work: investigations, debugging sessions, audits, multi-agent searches. The repository ships a generic agent skill at skills/lemmalog/SKILL.md that the README describes as making the engine the task's working memory for any long-running work, not one hardcoded workflow. The skill encodes what the README calls the discipline the live experiments converged on: assert as you verify with anchors and confidence, rules as experiments, query before re-reasoning, why before trusting, hypothesis lifecycles, decide from queries, report from the engine. If that list sounds like a workflow you already improvise in prompts, this project is aimed at you. If you want memory as a black box you never inspect, it is not.

The mechanism: stratified rules over provenance-annotated facts

The architecture has a clear boundary. Base facts are asserted at the ingestion boundary by an LLM extraction step, behind an Extractor trait with a memoized MockExtractor and an LlmExtractor. Rules then derive closures, temporal projections, contradiction candidates and relevance diffusion. Every fact carries provenance back to its source episodes, and each conversation turn updates derived views incrementally instead of re-deriving them, or worse, re-reasoning them in context.

The implementation is a runtime-parsed, stratified Datalog interpreter, not a proc-macro. Negation-as-absence is supported with negative-cycle rejection. Evaluation uses a seminaive fixpoint with per-epoch delta maintenance. Facts are bi-temporal through valid_from, valid_to and asserted_at columns plus a now() function. Annotations form a semiring: confidence under a product t-norm combined with provenance under set union, merged on re-derivation by taking max confidence, unioning provenance and deduping supports.

Two design choices are worth calling out. First, retraction is scoped. The README describes scoped negative deltas where retracting a fact recomputes only transitive dependents, and a DRed-lite scoped recompute where supersession rebuilds only what actually changed. Second, point queries can skip the full fixpoint: ask_deep uses magic-sets demand evaluation. The README claims indexed read paths give point lookups around 100 microseconds at 4 million facts; that is the project's own figure and I have not reproduced it.

The entity resolution section shows the style of the whole system. The LLM proposes star-shaped alias(Local, Canonical) edges, Datalog derives a symmetric-transitive closure, and canonical views project facts read-side only in src/canonical.rs. Topology violations, such as a local with two canonicals or a name that is both local and canonical, derive alias_conflict facts instead of merging identities. Retracting an alias edge collapses the closure and every downstream view in the same epoch.

Installing lemmalog and running a first query

The crate is on the repository only; the README gives no crates.io or package-manager install, so you build from source. The MCP server is behind a feature flag. Building it produces the lemmalog-mcp binary, which speaks stdio JSON-RPC and exposes 12 tools.

bash
cargo build --release --features mcp

Once built, register the server with a supported CLI. The README shows the Claude Code form and the Kimi CLI form; both point at the release binary by absolute path.

bash
claude mcp add lemmalog -- $(pwd)/target/release/lemmalog-mcp
kimi mcp add lemmalog -- $(pwd)/target/release/lemmalog-mcp

There is also a one-command installer that builds, registers the MCP server with every supported CLI it finds, and installs the skill. The same script removes registrations and the skill.

bash
./scripts/install.sh               # install
./scripts/install.sh --uninstall   # remove registrations + skill

For a first look without any CLI, the README documents a REPL launched with cargo run --bin lemmalog. It accepts rule, +, ?, ??, why, run, dump and batches as commands, so you can add facts, query them, and ask for a proof tree before wiring anything to an agent. Memory persists at $LEMMALOG_SNAPSHOT, defaulting to ~/.lemmalog/memory.snap. To keep a session's memory separate, pass the environment variable at registration time; the README notes both CLIs support --env KEY=VALUE on add.

bash
claude mcp add lemmalog --env LEMMALOG_MCP_PATH=/tmp/lemmalog.snapshot -- \
  $(pwd)/target/release/lemmalog-mcp

One inconsistency is worth flagging before you copy that line. The prose says memory persists at $LEMMALOG_SNAPSHOT, while the registration example sets LEMMALOG_MCP_PATH. The README does not reconcile the two names, so verify which one the binary reads in your setup rather than assuming the example is current.

Where lemmalog breaks down or is the wrong tool

The README is unusually candid about its own past bugs, and that candour is useful for judging risk. Building entity resolution surfaced two long-lived engine bugs: the scoped recompute never processed same-stratum dependents, a latent stale-fact bug, fixed by SCC-condensation stratification plus a recompute fixpoint; and the invalidation pass ran before lower strata were materialized on first run, fixed by moving invalidation after evaluation. Both were caught by the differential harness, which tests 450 random programs against a naive fixpoint oracle plus parser fuzzing. A project whose correctness rests on incremental recompute needs exactly that kind of oracle, and the fact that these bugs existed in shipped code is the honest cost of the approach.

The larger limitation is scope. Leapfrog triejoins, described as worst-case-optimal joins, and DBSP streaming deltas are marked as future phases. If your workload is dominated by complex multi-way joins, the current evaluator is not the one the design document is aiming at. The README also notes that persistence saves a snapshot of episodes, EDB facts and rules, with derived facts rebuilt on load. That means load time scales with how much you can derive, not just how much you stored, which is a different cost profile from a vector index that loads in one pass.

Finally, the extraction boundary is an LLM. If the model asserts a wrong base fact with high confidence, the confidence propagates through the closure. The README says weak two-hop merges are visibly low-confidence, which helps, but the engine reasons over what it was given. lemmalog is the wrong tool if you cannot afford to author or maintain rules at all, or if your retrieval problem is genuinely fuzzy similarity with no structure to derive.

How lemmalog differs from a vector store plus a graph layer

The obvious alternative is a vector database with an added graph or entity layer, where retrieval stays similarity-first and relationships are metadata you filter on. The difference in approach is where reasoning happens. In that stack, the agent decides what to retrieve and reasons in context, so a contradiction between two retrieved passages is something the model may or may not notice. In lemmalog, contradictions are derivable: the README lists contradiction candidates among the things rules produce, and the entity resolution code derives alias_conflict facts rather than silently merging identities.

The second difference is change handling. A vector store typically re-embeds or re-indexes on update. lemmalog maintains per-epoch deltas, exposes an epoch change-log through changes_from and since, and feeds a new in memory context section from it. Retraction is a first-class operation with scoped recompute rather than a delete followed by a rebuild. The third difference is answerability. The why() function returns proof trees with cycle protection, so a claim can be traced to the episodes that support it. A similarity score does not give you that chain.

This is not a claim that one is better. A vector store handles paraphrase and open-ended recall that a rule engine cannot express, and lemmalog's own semantic side index acknowledges this: the Embedder trait, HashEmbedder, seed_mentions and near diffusion exist to blend embedding similarity into retrieval, and context_for_query combines BM25 with entity and graph boosting under a budget. The project is a hybrid, with deduction as the substrate.

Maintenance, upgrade cost and the MIT licence

The repository is not archived, and the last push was on 2026-09-15, two days before this writing, so the codebase is moving. There are no retrieved releases, which means the version in Cargo.toml, 0.2.0, is the number to track rather than a tagged release history. Expect to build from a commit.

The dependency surface is small, which lowers upgrade cost. Cargo.toml lists serde_json and ureq, both optional, behind two features: llm enables ureq and serde_json for OpenAI-compatible chat and embeddings, and mcp enables serde_json for the stdio server. There is no database driver, no async runtime and no network service to operate. The cost of upgrading is therefore mostly the cost of re-reading the design document, since datalog-context-engine-design.md carries what the README calls an honest status log of what shipped. That status log is the file to diff against your assumptions after you pull.

The operational cost sits elsewhere: rules. The rule registry supports versioned batches, agent install and uninstall, and backfill on change. Backfill on a rule change means editing a rule can trigger recomputation over existing facts, so rule churn has a price that a schema change in a vector store does not. Plan rule versions the way you plan migrations. The licence is MIT, which permits commercial use and modification, but this is not legal advice; check the LICENSE file for the exact terms and your own obligations.

Editorial conclusion

Adopt lemmalog if your agent work involves long investigations, audits or multi-agent searches where you need to ask why a conclusion holds and retract a wrong fact without rebuilding everything. Do not adopt it if you want a drop-in vector store replacement with no rule authoring, or if you need the leapfrog triejoins and DBSP streaming deltas, which the README lists as future phases. Before committing, clone the repository and run the REPL with cargo run --bin lemmalog to check that the rule grammar fits your facts, then run ./scripts/install.sh and confirm that $LEMMALOG_SNAPSHOT points where you expect, because the default is ~/.lemmalog/memory.snap.

Frequently asked questions

How do I install lemmalog?

Build it from the repository, since the README documents no package-manager install. The MCP server needs the feature flag: cargo build --release --features mcp. There is also ./scripts/install.sh, which builds, registers the MCP server with every supported CLI it finds, and installs the skill.

Does lemmalog work with Claude Code and Kimi CLI?

Yes. The README shows registering the built binary with claude mcp add lemmalog -- $(pwd)/target/release/lemmalog-mcp and the equivalent kimi mcp add form. The MCP server is stdio JSON-RPC and exposes 12 tools.

Where does lemmalog store its memory between sessions?

The README says memory persists at $LEMMALOG_SNAPSHOT, defaulting to ~/.lemmalog/memory.snap. Note that the registration example in the README instead passes --env LEMMALOG_MCP_PATH, and the README does not reconcile the two names, so confirm which one your binary reads.

Official sources

  1. Issues
  2. JordyZomer/lemmalog on GitHub
  3. License: MIT
  4. README
Community notes

Community notes