Skip to main content

Long-term memory for AI agents — every recall returns a conflict and confidence verdict. Open-source Python SDK with MCP server, local SQLite, BM25.

Project description

atlaso

PyPI Python License MCP Registry Docs

Long-term memory for AI agents — every recall() returns a confidence verdict (is_confident, has_disagreement, agreement_score, conflict_peers) so your agent stops confidently retrieving stale or contradictory facts. Open-source Python SDK with MCP server. Local SQLite + BM25. Zero telemetry.

from atlaso import Memory

m = Memory()
m.add("Alice prefers dark mode", user_id="alice")

for hit in m.recall("dark mode", user_id="alice"):
    if hit.has_disagreement:
        print(f"⚠ conflicts with {hit.conflict_peers}")
    elif hit.is_confident:
        print(f"✓ {hit.content}")
    else:
        print(f"? lead, not settled: {hit.content}")

What makes atlaso different

Memory stores return hits. atlaso returns hits plus a verdict on whether the hits are settled. Built around Field 3.0 — polarity-aware deposits and dispersion-aware recall — so when two memories disagree, your agent finds out before the LLM does.

atlaso typical memory store
Recall returns hits + confidence + conflict verdict hits
When sources disagree flagged via has_disagreement silent
Retrieval backend BM25 over SQLite FTS5 (local) vector DB + embedding API
Schema append-only with explicit contradicts edges mutable rows
LLM dependency none required usually required for embedding
MCP server built-in (pip install atlaso[mcp] — 9 tools) typically a separate package
Cross-tenant isolation per-user SQLite files shared collection with filter
Telemetry none varies

If you've used mem0, Letta, Zep, or Cognee — atlaso is the version that comes with a confidence signal on every recall, runs fully local with no API key, and ships an MCP server in the same pip install. Apache 2.0. 135 tests on the public surface. Python 3.10+.

Built around Field 3.0

Field 3.0 is the data model under the hood. Every deposit carries:

  • Polaritypositive / negative / cautionary / open — the stance of the claim.
  • Evidence gradeanecdotal / observed / replicated / verified — gated by claim breadth.
  • Scope — six experimental facets (note, model, dataset, env, version, n, seed) telling you under what conditions the claim holds.
  • Contradictions — first-class edges, not metadata. Revising a fact deposits a new one with contradicts=[old_id]; the audit chain is preserved forever.

When an agent calls m.recall(...), results are grouped by scope, and every hit is annotated with whether it agrees with its neighbors, whether its scope-bag has internal disagreement, and whether the SDK considers it safe to act on. Your agent gets data back; it also gets a verdict on whether the data is settled.

Full docs: rendered at https://www.atlaso.ai/docs · plain Markdown in ./docs/ for offline / on-GitHub reading · listed in the official MCP Registry.


Install

pip install atlaso              # core library
pip install atlaso[mcp]         # + MCP server (Claude Code, Cursor, Codex, Windsurf)

Python 3.10+. No phone-home, no analytics, no signup. The library runs entirely in your process against on-disk SQLite.

Quickstart — single user

from atlaso import Memory

m = Memory()
m.add("I prefer oat milk in lattes", user_id="me")
hits = m.recall("oat milk", user_id="me")
print(hits[0].content)

SaaS — multi-tenant

from atlaso import AsyncMemory
from fastapi import FastAPI, Depends

memory = AsyncMemory()
app = FastAPI()

@app.post("/remember")
async def remember(text: str, user = Depends(current_user)):
    handle = memory.for_user(user.id)        # bind to authenticated identity
    return await handle.add(text)

The for_user(user.id) pattern is the recommended path. The lower-level memory.add(text, user_id="alice") exists for admin tooling but is the wrong shape for request handlers — see Authorization.

Recall with conflict awareness

results = m.recall("what does Alice eat?", user_id="alice")
print(results.explain())
# → "5 matching memories disagree. Read both groups before using as fact."

for r in results:
    if r.has_disagreement:
        print(f"⚠ {r.content}  conflicts with {r.conflict_peers}")
    elif r.is_confident:
        print(f"✓ {r.content}")
    else:
        print(f"? unconfirmed: {r.content}")

results.explain() is action language, not internals. Empty / confident / disagreement / thin-evidence each get their own one-sentence verdict.

Memory health

print(m.health(user_id="alice").explain())
# → "Memory is healthy (FMI 82/100). Searches are returning confident answers."

The Field Maturity Index is a 0–100 geometric mean of Coverage × Precision × Resolution × Density — a single readable number for "how settled is what I know about this user?"

Retract, don't delete

m.retract(deposit_id, user_id="alice", reason="this fact was wrong")

Soft tombstone by default — the row stays citable in contradicts=. hard_delete=True is the GDPR/PII escape. reason= is required because Atlaso keeps a retraction trail.

What we deliberately don't ship

  • No update(). Atlaso deposits are immutable evidence. To revise an earlier finding, deposit a new one with contradicts=[old_id]. The audit trail is the point.
  • No telemetry. Atlaso never phones home.
  • No required LLM. add() and recall() work with pure SQL + lexical retrieval. Bring your own embedder/extractor only if you want them.
  • No cross-tenant footguns on autocomplete. Cross-tenant operations live in from atlaso.admin import ... behind a confirm="I_UNDERSTAND_THIS_CROSSES_TENANTS" literal. They never appear on m.<TAB>.

Framework integrations

atlaso[mcp] covers Claude Code, Cursor, Codex, Windsurf, Cline via MCP — zero per-framework code.

For Python agents, see the recipes in docs/recipes/:

pip install atlaso[langchain] and the four other framework extras are reserved namespaces — they install only atlaso core today and emit a one-line FrameworkExtraReservedWarning when the SDK detects the framework is installed alongside it. Real adapters land in v0.1.x.

Inspect what you have

m.peek("alice")
# PeekView(user_id='alice', showing 4 of 4, FMI 0/100):
#   · [open       ] Alice prefers dark mode in the UI
#   · [open       ] Alice's preferred coffee is oat-milk lattes
#   · [open       ] Alice's birthday is March 15
#   · [open       ] Alice usually wakes up around 7am

(The default polarity is open — undecided / observed-but-not-stance-claimed. Stronger polarities like positive or negative require corresponding evidence. See the Glossary below.)

m.peek(user_id) is the "show me what's stored without writing a query" primitive. It returns a PeekView that iterates like a list but renders as a compact table in your REPL or notebook.

Debug a recall

hits = m.recall("dark mode", user_id="alice")
print(hits[0].explain())
# Returned because the text matched (BM25 score 1.842).
# Polarity: open. Evidence: anecdotal.
# This bag has only one deposit on the context (no scope facets set).
# Treat as a lead, not a settled finding.

hit.explain() answers "why did I get this result and should I act on it?" in plain language — no Field 3.0 jargon leaks. Useful for production-debugging unexpected retrievals.

Use it from bash — atlaso CLI

Once pip install atlaso lands, the atlaso command is on PATH and every Memory verb has a CLI mirror. Same vocabulary as the Python API, same vocabulary as the MCP tools — one mental model:

atlaso add "Alice prefers oat milk" --user alice
atlaso recall "coffee" --user alice
atlaso peek alice
atlaso health alice
atlaso list-recent --user alice --limit 5
atlaso get <deposit_id> --user alice
atlaso contradict "Alice moved to Brooklyn" <old_id> --user alice --reason "user moved"
atlaso retract <deposit_id> --user alice --reason "wrong fact"           # soft tombstone
atlaso retract <deposit_id> --user alice --reason "GDPR" --hard          # purges FTS index too

Add --json to add / recall / get / list-recent / peek / health / contradict / retract to get machine-parseable output for piping into jq or shell scripts:

atlaso list-recent --user alice --limit 100 --json | jq '.[] | select(.polarity == "negative")'
atlaso recall "milk preferences" --user alice --json | jq '.is_confident'

atlaso --help lists every subcommand. Each subcommand has -h for its own usage. Errors print as atlaso <cmd>: <ErrorType>: <message> (no stack traces) so they're shell-friendly.

Health-check the install

$ atlaso doctor
atlaso doctor
──────────────────────────────────────────────────
   atlaso 0.1.0a3 importable
   Field 3.0 engine vendored
   storage path: /Users/me/work/.atlaso  (auto-resolved)
   engine round-trip (add  recall  retract)
   atlaso[mcp] installed (run: python -m atlaso mcp)
──────────────────────────────────────────────────
OK  atlaso is healthy.

End-to-end install + path + engine sanity check in five seconds. Returns 0 on healthy, 1 if anything's broken.

Glossary

If the words below feel unfamiliar, read this once. Five sentences each.

  • Deposit — a single saved fact. Immutable; revise by depositing a new one with contradicts=[old_id].
  • Polarity — the stance of the deposit: positive (supported), negative (refuted), cautionary (works under conditions), open (undecided / question / hypothesis — this is the default).
  • Evidence grade — how strong the support is: anecdotal (one source, no measurement), observed (one careful measurement), replicated (multiple independent measurements agree), verified (independently checked against ground truth).
  • Scope — the experimental facets describing under what conditions the claim holds: note, model, dataset, env, version, n, seed. All optional.
  • Bag — deposits that share the same scope facets are in one "scope-bag." The dispersion signals (is_confident, has_disagreement, agreement_score) are computed per-bag.
  • Contradicts — a list of deposit ids this finding supersedes. The new deposit + the contradiction edges are committed atomically.
  • FMI — Field Maturity Index, a 0–100 health score. Geometric mean of Coverage × Precision × Resolution × Density. Returned by m.health(); the four components are interpretable separately.

License

Apache 2.0.

Status

v0.1.0a6 — research preview, ships from PyPI on every release. The public API is design-locked for v0.1+; new methods may land, existing signatures and return types follow semver inside the alpha track. Read the release notes before upgrading.

Links

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

atlaso-0.1.0a6.tar.gz (105.5 kB view details)

Uploaded Source

Built Distribution

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

atlaso-0.1.0a6-py3-none-any.whl (56.2 kB view details)

Uploaded Python 3

File details

Details for the file atlaso-0.1.0a6.tar.gz.

File metadata

  • Download URL: atlaso-0.1.0a6.tar.gz
  • Upload date:
  • Size: 105.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for atlaso-0.1.0a6.tar.gz
Algorithm Hash digest
SHA256 70ab30f8d861aab0c1eacd611262531cf9bf4a7e4a47add885cdc0f94cea2934
MD5 3f1f83f89e89da1ea3c0ed90369889db
BLAKE2b-256 75959f388662157a73d893acb66ec6ce1db1d8f42ef569a9a24182654918d925

See more details on using hashes here.

File details

Details for the file atlaso-0.1.0a6-py3-none-any.whl.

File metadata

  • Download URL: atlaso-0.1.0a6-py3-none-any.whl
  • Upload date:
  • Size: 56.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for atlaso-0.1.0a6-py3-none-any.whl
Algorithm Hash digest
SHA256 d93a80e81d2f5035d708f15f75dfa1b2e3cbd30ecf3a31cbd85e0ae8aea4560f
MD5 41b14bbe293b0c4cd2f5a071134f7bcd
BLAKE2b-256 a7b6305bee2650c5cc491288f4d35e6fb52f674886a19a86924817a4248488d9

See more details on using hashes here.

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