Skip to content

What is mempill?

AI agents accumulate beliefs over time. A belief stored last week — “the API endpoint is api.example.com/v1”, “the user lives in Berlin” — may be false today. Most agent memory systems either overwrite the old belief silently (destroying history) or preserve it without any signal that it might be wrong. Neither approach is safe for long-running agents.

This is the temporal validity problem: a stored belief can be well-sourced and internally consistent yet factually wrong, because the underlying truth changed after the claim was recorded. The failure is not about bad data at write time; it is about the passage of time making previously-correct data stale — and the agent having no mechanism to detect or signal that staleness.

Imagine an agent stores the claim: “user.city = Berlin” (sourced from the user, high confidence). Three months later the user moves to Munich and the agent receives a new assertion: “user.city = Munich”.

A naive memory system either:

  • Overwrites — Berlin is gone. The history of the assertion is destroyed. The agent can never audit why it once believed Berlin, or when it changed.
  • Silently keeps both — the agent cannot tell which is current and picks arbitrarily or returns stale data.

mempill does neither. It records the new claim alongside the old one, detects the contradiction, and surfaces Contested — making the conflict explicit and auditable. Neither value is silently picked. An oracle (human or automated) can later adjudicate, at which point one claim is bounded by a validity assertion and the other is confirmed.

In code, the ergonomic API makes this a two-liner:

# Berlin until end of 2024, then Munich from 2025 onward — non-overlapping windows.
remember(engine, agent, "user", "city", "Berlin",
RememberOptions(valid_from="2020-01-01", valid_until="2024-12-31"))
remember(engine, agent, "user", "city", "Munich",
RememberOptions(valid_from="2025-01-01"))
result = recall(engine, agent, "user", "city")
print(result.as_str()) # 'Munich' — open-ended window covers today
print(result.is_contested()) # False — resolved by valid-time succession, not conflict

If the two facts had overlapping windows, recall would return is_contested() = True with both values in candidates — never a silent winner. See Quickstart (Python) for the full walkthrough.

mempill is an append-only, bi-temporal, provenance-aware claim store that surfaces conflict rather than silently resolving it.

Every claim is written once and never mutated. Supersession is recorded as a new bounded assertion that links back to the original. The engine maintains two time axes:

  • Transaction-time — engine-stamped at write time; reliable and immutable.
  • Valid-time — caller-supplied, fallible, and confidence-tagged. Represents when the asserted fact was actually true in the world.

Belief is never stored. It is recomputed at read time from the full claim history via a deterministic canonical fold (invariant I3/I8).

Provenance firewall. Every claim carries one of three typed provenance channels assigned at injection time and immutable thereafter:

  • External — first-hand assertion (user or tool result); cheap-path eligible.
  • RecallReEntry — engine output re-entering the write path; caught by the Amplification Guard to prevent belief amplification loops.
  • ModelDerived — model-emitted content; committed down-weighted.

The type system enforces exhaustiveness. Provenance cannot be changed after write.

Contested is first-class. When contradicting claims arrive and no oracle is present to adjudicate, the engine surfaces Contested rather than picking a winner. The 12-state disposition model makes every outcome observable.

Deterministic core, stochastic-behind-a-gate. The engine embeds no AI model. Extractor and oracle ports are pluggable traits; the host supplies implementations. Stochastic proposals never commit without passing the deterministic adjudication gate (component C7).

Single-writer-per-agent_id. A hard structural guarantee enforced by per-agent locks (SQLite) or advisory locking (PostgreSQL). Two concurrent processes must not hold write authority for the same agent_id.

  • Not a vector database. The embedding port (VectorPort) is a structural seam; the implementation is NoOp today. mempill stores claims, not embeddings.
  • Not an AI model. BYO extractor and oracle. mempill is the deterministic store that sits below your model — it never calls one itself.
  • Not a multi-backend store. One backend per deployment: SQLite for embedded single-agent use, PostgreSQL for multi-agent shared deployments. The two topologies are not mixed.