luplo

The AI memory tool that didn't exist.

Born to be audited.

Just ask.
If there's no memory, luplo says it doesn't know.

2026-04-22 09:23:14 actor:taehun query:"auth jwt rotation"3 items
hash:f9c2e8b… prev:7a1d3e4
2026-04-22 09:24:03 actor:taehun query:"prod db credentials"BLOCKED
policy:secrets-gate reason:"tag:prod not in actor.groups"
2026-04-22 09:24:52 actor:agent-01 query:"decision archaeology"12 items
hash:a8e9c1d… prev:f9c2e8b
2026-04-22 09:25:17 actor:contractor-42 query:"internal api keys"BLOCKED
policy:external-scope reason:"actor.role=external"
2026-04-22 09:25:44 actor:taehun query:"deploy rollback 2024-q4"5 items
hash:3b7f4a2… prev:a8e9c1d

Every access, every block, every reason. Forever. Hash-linked and tamper-evident.

The problem nobody calls a problem

Your AI memory is leaving the building.
Nobody calls it a leak.

Who accessed what knowledge and what decisions, and why — nobody knows. luplo starts here.

01 / markdown

A departing engineer zips the md folder. And walks out.

Inside: three years of design decisions, meeting notes, incident post-mortems, the "why" behind your architecture.

02 / memory stores

mem0 / Cognee DB exports into another agent

Memory is structured org knowledge. One command exports it, one command imports it elsewhere — same productivity, no friction. Which decision it backed, what answer it produced — nothing is logged, anywhere.

03 / the replay gap

"Why did we give that answer on October 14?"

A PM asks. Embedding models shift over time. Vector indexes rebuild with subtle differences every time.

By design

Three choices
that close the replay gap.

01 / DETERMINISTIC

On the same knowledge, the same query always returns the same result.

Not "looks similar" from a cosine. Because tsquery returns the same output for the same input, and memories are append-only.

02 / REPLAYABLE

Every query carries a tag.

actor_id, timestamp, query, result_ids, prev_hash. Six months later, re-run the audit with the same migration_id — identical output.

03 / GLOSSARY, NOT GUESSES

Synonyms are resolved by a glossary, not an embedding.

Abbreviations and aliases are expanded via a glossary extracted from the decision corpus itself — not an opaque vector space. Every expansion is auditable: which term, which alias, which decision it came from, and who registered it.

$ luplo audit retrievals --actor taehun --since 2025-10-01
 
2025-10-14 09:23 taehun"auth & jwt"3 items
2025-10-14 09:24 taehun"deployment"BLOCKED
└─ policy:prod-config
2025-10-14 09:26 taehun"migration rollback"7 items
2025-10-14 11:02 taehun"oauth refresh race"2 items
2025-10-15 14:17 taehun"mcp session id"1 item
 
# 5 reads / 1 block · hash chain verified · export ready

Every access, every block, every reason — forever. Hash-linked, tamper-evident, exportable as SOC 2 evidence.

Why "similar" isn't good enough

"auth" means three things.
Vector-based search treats them as one.

In your codebase: authn (who you are), authz (what you can do), and "auth" as shorthand for either. In a SOC 2 audit they're separate controls (CC6.1 vs CC6.3). In a vector store, they converge into the same cluster.

vector search
query:   "authz policy"
returns: 12 rows — login flows, password resets, OAuth, 2FA, …
reason:  "auth" dominates the embedding
         authn / authz collapse into the same cluster
audit:   opaque — which rows are authz? which aren't?
luplo
query:     "authz policy"
glossary:  authz ≠ authn  (conf=0.97)
expanded:  (authz | "authorization") & policy & !authn
returns:   3 rows — authorization policy decisions
audit:     term #authz sourced from
           D-2025-03 "split authn/authz for SOC 2 CC6.1"

Grounded in requirements engineering research

luplo's glossary builds on the REGICE / FastText-clustering / ILLOD+ line of work on automated term consolidation (Arora 2017, Bhatia 2020, Hasso 2022) — which establishes that controlled vocabulary with feature-based matching outperforms vector embeddings for abbreviations and spelling variants. luplo extends this to append-only decision corpora. Each time a decision supersedes another, the glossary itself changes — and the glossary becomes both the audit subject and its evidence.

Preemptive control

What you can't access, you can't query.

Draw boundaries with permissions. This file is the policy. luplo filters requests before the agent sees any content. luplo cloud also exposes per-user policy in the dashboard.

luplo.policy.yml
# deny-by-default for secrets; log every denial
rules:
  - match:
      tags: [prod, secrets]
    readable_by: [group:sre]
    audit_denials: true

  - match:
      item_type: decision
      visibility: internal
    readable_by: [role:employee]
    deny_export: true
trace / 2026-04-22 09:24:03
┌─ query
│ actor: contractor-42
│ query: "internal api keys"
├─ match
│ rule: secrets-gate
│ tag_hit: prod, secrets
│ required: [group:sre]
│ actor: [group:external]
├─ decision
BLOCKED
└─ logged
audit_id: f9c2e8b…
exports: SOC2·ISMS·ISO27001

Retrieval in vector stores is vector math. Retrieval in luplo is a permissioned read. Denials leave audit evidence (countable, exportable, defensible).

Where we draw the line

Not what luplo is for.

luplo is not a replacement for vector memory. If your agent needs semantic recall across unstructured chat history, tools like mem0, Cognee, LangMem do that well. Use them.

luplo's lane is different — for the organizational decisions, policies, and facts that must be retrieved the same way every time, by the same query, with a tag.

Honest comparison

Features our peers don't call features.

Every memory product offers recall. The difference is how they recall. They compete on recall quality, embedding cost, integration count. Provability isn't even on their roadmap — that's where the gap opens.

CAPABILITY luplo vector-based
(mem0, LangMem)
graph-based
(Cognee, Zep)
Recall mode
how results are produced
Deterministic Probabilistic Hybrid
Same query, 2 mo. later = same result?
byte-identical replay
Yes No No
Synonym / alias handling
auditable expansion
Glossary layer Vector space
(opaque)
Entity linking
(opaque)
Per-query retrieval log
actor · timestamp · query · result_ids
Full Optional Per product
Hash-chained audit
tamper-evident line linking
Yes
Policy gate
where access control happens
Before read (YAML) App layer
(build it yourself)
App layer
(build it yourself)
OSS license
copyleft vs permissive
AGPL Apache / MIT Apache

Comparison reflects public docs as of 2026-Q2. We'll open a PR if any row is wrong.

One product, different uses

Feel the calm
of deterministic results.

For CISOs

"Every action has a reason, and every reason can be replayed. Born to be audited!"

Hash-chained audit*. Per-actor retention. Tamper-evident exports. Formats auditors already know — a product born to be audited.

For CTOs

"It sits on top of the stack you already have."

No new vendor. No new DB. No new hire. If you're already running Postgres, luplo's operating cost trends to zero.

For engineers

"Building your own knowledge base? One Postgres will do."

No external embedding API. No vector DB to run. One docker compose up — MCP server included.

For product planners

"A spec drafted with Claude Code, handed to a teammate using Codex."

Why you chose this approach, why you didn't choose the alternatives, which external sources you consulted — all of it carries through.

For legal / CPO

"Who read what,
and under whose policy."

Every read carries actor, tag, policy match. DSR, retention. Append-only meets right-to-be-forgotten through tombstones and access blocks.

For chatbot builders

"Deterministic queries — the trust of an agent that can say 'I don't know'."

For chatbots that must follow a script, vector-based knowledge only piles on uncertainty. luplo brings calm.

* planned for v1.0

Born to be audited.
Ready to be installed.

AGPL core. Self-host with one docker compose up, or try luplo cloud for free.