Skip to main content

LBrain by Metavolve Labs — AI-native engineering memory with the Lair Protocol.

Project description

LBrain — a dragon coiled around a circuit-etched L

LBrain

Status: Beta BSD-3-Clause Python 3.10-3.13

BETA — use at your own risk. This is early software from a small team. It has not yet been through an independent security review. It runs on your machine against your files: keep backups, and don't point it at anything you can't afford to have read by a tool that is still being hardened. LBrain never deletes your source files, but that is a design commitment, not yet an audited guarantee.

Memory for AI agents that cites its sources — and says when it doesn't know.

Your agent reads a pile of your notes and answers confidently from the wrong one. LBrain serves each record with its source, its date, and a flag for whether it actually answers the question asked.

pip install "lbrain[local]"
lbrain init --source ~/notes
lbrain import && lbrain embed --stale
lbrain query "what did we decide about the deploy flag"

No API key. No account. Indexing and search run on-device — your documents and queries are never transmitted.

The one download, and what it's for

On first run LBrain fetches a ~67 MB embedding model (BAAI/bge-small-en-v1.5) and then runs it on your CPU. lbrain init tells you before it happens and asks; --yes skips the prompt.

That is the model coming down — not your documents going up. It is the only network call the on-device path ever makes. Afterwards embedding is fully offline, and the model is cached in ~/.cache/huggingface and never fetched again.

Why a model at all, and not just code? Searching by meaning needs text turned into coordinates, so that "did anyone test the mailbox" can find a note that says "dereference", "round trip" and "MX record" — sharing no words with the question. You cannot write rules for that; the number of ways to phrase an idea is unbounded. So a model is trained until related meanings land near each other. LBrain also runs a plain keyword index (SQLite FTS5) for what you literally typed, and fuses the two.

What the model is not. It does not generate text, has no opinions and remembers nothing. It is one deterministic forward pass — same text in, same 384 numbers out, every time. 33M parameters whose entire behaviour is text → coordinates. Closer to a learned lookup table than to a chatbot.

Prefer not to download it? Use a hosted embedder instead, under your own key and billing: lbrain init --gemini-key <KEY> --source ./docs. See Embeddings.

⟪note⟫
│ Deploy runbook          runbook.md · chunk 0 · dated 2026-05-14 · binds
│ The staging deploy uses tag v2 and the rollback flag is --safe.
⟪/note⟫

binds means the record answers the question. near-miss means it's the right subject but doesn't contain the answer — the case where retrieval quietly hands over the neighbour's value and the model presents it as fact.

Why

We profiled eight model architectures from seven organizations on the same near-domain retrieval task. Failure rates swung 1.3% / 35.7% / 16.7% depending only on how the records were structured — a 34.4 percentage-point absolute difference — while architecture explained ≈0% of the variance, with identical ordering in 8 of 8 models. Changing models didn't remove the effect. Telling the model not to guess didn't remove it either.

Across the models we tested, record structure dominated the failure pattern. So the fix belongs before generation, on the input side, and it has to be deterministic — a gate judged without another model call.

Related work — read these too

Four 2026 papers staked adjacent ground while we were building, and they deserve the citation:

  • Deceptive Grounding — Caruzzo, Yoo & Kim (arXiv:2607.09349): named and measured the failure mode — RAG responses that pass standard quality checks while attributing evidence to the wrong entity, in 8–87% of cases across 13 models, with domain-specialized models failing worse.
  • MemStrata (arXiv:2606.26511): deterministic supersession rules over a bi-temporal ledger, against stale-fact errors on evolving knowledge.
  • Engram (arXiv:2606.09900): a bi-temporal memory graph tracking provenance and contradictions — a lean retrieved context beats the full history.
  • Don't Ask the LLM to Track Freshness (arXiv:2606.01435): conflict resolution belongs in deterministic code, not model judgment — "the bottleneck … is assembly (post-retrieval aggregation), not storage."

We claim no priority over any of this. What our 8-model matrix adds is the controlled variable: it reproduced the same failure class independently, in a different domain, before it had a name — and showed the serving format, not the model, is the controlling variable. How a record is presented to the generator is the axis these works leave open, and it is the axis LBrain operates on.

Where it does not help

  • Not a hallucination fix. This is about answering from retrieved records. It does nothing about a model inventing facts from its weights with no retrieval involved.
  • Small, clean corpora barely benefit. If your notes are short and unambiguous, ordinary search is fine. The gain appears when records are numerous, overlapping, and stale in places.
  • Not a reasoning upgrade. It changes what the model is given, not what it does with it.
  • The gate is conservative — it will sometimes flag near-miss on a record you'd have accepted. That is the trade: fewer confident wrong answers, slightly more "I don't know."
  • A cold import of old notes will serve old decisions as current. Records are dated only when the filename carries a date, and a bulk copy resets every mtime to today — so newest-wins has nothing to order by. Read this first before importing an archive: either vet it, restore the dates, or knowingly run a calibration period.

We also killed three of our own claims while building this, including a headline result that turned out to be an artifact of our own prompt. The retractions are published with the findings.

How it works

  • Hybrid retrieval — vector + BM25 keyword, fused by reciprocal rank fusion.
  • Deterministic admissibility gate — classifies each record against the question as admissible, near-miss, or irrelevant, without another model call.
  • Supersession — a replaced note stops being served but is never deleted. Persistence and activation are separate concerns.
  • Honest dating — each record states whether its date came from the content, the filename, or the filesystem. No invented timestamps.
  • Untrusted-data fencing — retrieved text is fenced and labelled as data, never instructions, so a note can't hijack the agent reading it.

Use it with your agent

Five MCP tools: lair_query, lair_search, lair_protocol_check, lair_check_action, lair_stats.

# Claude Code
claude mcp add -s user lbrain -- /path/to/lbrain/scripts/lbrain-mcp

# Any client speaking streamable-http
lbrain mcp --transport streamable-http --host 127.0.0.1 --port 7370

⚠️ The HTTP server has no built-in auth and exposes the whole corpus. Bind to 127.0.0.1, or put authenticated TLS ingress in front. Never publish it on a public interface.

Or skip MCP entirely — lbrain query, search, import, doctor all work from the shell.

Embeddings

Provider Setup Where your text goes
local (default) none nowhere — on-device ONNX, 384-dim (one-time model download)
gemini your own key Google, under your key
openai your own key OpenAI, under your key

lbrain init uses local unless you pass --gemini-key/--api-key on the command line. A key sitting in your environment is never treated as consent to send your corpus to a third party. See the Privacy Policy for every network call LBrain can make, and when — §3 lists them all. See docs/KEYS.md.

Known issues — read this before filing

Most reports land in one of these. Checking first is faster than waiting for us.

Symptom Cause / fix
TOMLDecodeError on any command right after init, on Windows You are on 0.1.0, which is yanked. It wrote an unparseable config.toml on Windows paths. pip install -U lbrain (≥ 0.1.1), then delete ~/.lbrain/config.toml and re-run init.
UnicodeEncodeError during init, on Windows Same fix — 0.1.0 wrote template files in the locale encoding. Fixed in 0.1.1.
Build errors installing [local] (fastembed / onnxruntime / sqlite-vec) Native wheels. Upgrade pip first (pip install -U pip), which resolves nearly all of these. On Windows a wheel may be missing for a very new Python — 3.10–3.13 are supported; 3.14+ may have no wheel yet.
First embed pauses, then works One-time ~67 MB model download. It is the model coming down, not your notes going up. Offline after that.
“It says my provider is Gemini but I never set that” Run lbrain doctor. It marks every setting [config] or [DEFAULT]. In 0.1.0 an API key in your environment silently selected a hosted provider; 0.1.1 refuses to treat an ambient key as consent.
Results changed after switching provider Changing provider changes the vector space. Re-embed (lbrain embed --all); doctor exits non-zero on drift until you do.
A note is missing from results but the file exists Usually imported-but-not-embedded. lbrain stats shows the gap; lbrain embed --stale closes it.
I edited only the YAML frontmatter and nothing changed Known in 0.1.1 and earlier: change detection hashed the body only, so type: / description: edits were skipped and the old value persisted. Fixed in the next releaseimport will report meta-refreshed: N. Workaround today: touch the body (a trailing newline is enough) to force a re-index.
Two brains on one machine interfering Use LBRAIN_HOME=/path/to/brain2 per invocation.

Not listed? Then it is worth an issue — please use the template, it asks for lbrain doctor --json.

Something wrong?

lbrain doctor

Prints the effective config with per-setting provenance — [config] vs [DEFAULT] — and whether your stored vectors match your current embedding settings. Include its output in any issue.

docs/DEVELOPER-NOTES.md covers the symptoms that look like bugs and aren't — switching embedding providers on an existing brain, two brains on one machine, imported-but-not-embedded records, and why a note can vanish from results without being deleted.

More

Truth hierarchy: your source files are authoritative; the index is a derivative cache. If they disagree, trust the file and re-run lbrain import && lbrain embed --stale.

Requires Python 3.10+. SQLite + sqlite-vec + FTS5 — no daemon, no server, no WASM.

Your Python must be able to load SQLite extensions. Apple's /usr/bin/python3 and the python.org macOS installers are built without it, and sqlite-vec cannot load. Check yours:

python3 -c "import sqlite3; print(hasattr(sqlite3.connect(':memory:'), 'enable_load_extension'))"

If that prints False, use Homebrew's (brew install python@3.12), or build with PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" under pyenv. Linux distro packages normally have it enabled.

License

BSD-3-Clause — see LICENSE. Copyright (c) 2026 Metavolve Labs, Inc.

Patents pending. The licence covers the code; it does not grant patent rights.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lbrain-0.1.3.tar.gz (242.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lbrain-0.1.3-py3-none-any.whl (190.2 kB view details)

Uploaded Python 3

File details

Details for the file lbrain-0.1.3.tar.gz.

File metadata

  • Download URL: lbrain-0.1.3.tar.gz
  • Upload date:
  • Size: 242.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lbrain-0.1.3.tar.gz
Algorithm Hash digest
SHA256 15cef1c977dfe383fbeb110955cc591f8b79b2d6fe7f14754868f754e157901e
MD5 e3f13c6f6efeb0fcb3c6abca80204b02
BLAKE2b-256 a7976e0cff7ed5dde7e0866766cb5c794205a5ae806496ce7750ff40b737a29a

See more details on using hashes here.

Provenance

The following attestation bundles were made for lbrain-0.1.3.tar.gz:

Publisher: release.yml on metavolve-labs/lbrain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lbrain-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: lbrain-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 190.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lbrain-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 746a65ea32199039e44b0bc6d5e605955cb45e78a4ef139774ffd8bd9d26614f
MD5 6fac74461e1ded4c34c7d7c08f6ccf04
BLAKE2b-256 08cde45b5d4dd4976c6ba2a8508f43ca47aa69d1f284fd62f1c550e9d97ca3d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for lbrain-0.1.3-py3-none-any.whl:

Publisher: release.yml on metavolve-labs/lbrain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page