Skip to main content

Agent Memory Ledger

An append-only, tamper-evident ledger for LLM agent memory. When an agent makes a bad call, find out what it believed — and why.


The problem

An agent wrote user_employer: "Acme Corp" on January 1.

On April 5 it read that memory and sent an email to the user at Acme.

The user left Acme in March. The agent was never told.

Your memory backend shows user_employer = "Acme Corp". That is all it shows. There is no record of when the agent learned it, where it came from, whether it was ever revisited, or whether the agent even read it before it acted. The bug is undebuggable, because there is nothing to debug against.

What the ledger gives you

  2. WAS ANY OF IT STALE?
──────────────────────────────────────────────────────────────────

     ok     user_seniority    43 days old at read
  ⚠  STALE  user_employer     94 days old at read

  Two beliefs, read in the same instant. One is fine -- seniority
  was refreshed in February. The other had not been touched since
  January, and the world had moved on without telling the agent.

Two memories, consulted at the same moment. One is fine. One is three months stale and about to cause an incident. The ledger tells them apart.

Run it yourself:

python examples/stale_belief_incident.py

Quick start

pip install agent-memory-ledger
aml --db demo.db --agent demo-agent demo
aml --db demo.db --agent demo-agent incident 2026-04-05T10:05:00+00:00

The third command answers the question you actually have at 2am — why did the agent believe that?

Incident window: up to 2026-04-05T10:05:00

  WHAT IT READ
      ok   user_seniority         senior engineer        43d old at read
           why: drafting outreach email -- need seniority
    STALE  user_employer          Acme Corp              94d old at read
           why: drafting outreach email -- need current employer

  WHAT IT BELIEVED
    user_employer          = Acme Corp
    user_seniority         = senior engineer

  Chain verified: 3 operations.

The agent read user_employer one minute before it sent the email. The value was 94 days old. It was written once, in January, from a single onboarding message, and never checked again — the user changed jobs in March and nobody told the agent.

A memory backend can only tell you the value is Acme Corp. The ledger tells you when the agent read it, how stale it was at that instant, where it came from, and — via the hash chain — that nobody edited the record afterward to make the incident look better than it was.

The full scenario, with provenance and belief reconstruction, is in examples/stale_belief_incident.py. See ARCHITECTURE.md for how it works.

API

Call Answers
write(key, value, provenance=) Record a belief, and why
read(key, provenance=) Consult a belief — and log that you did
as_of(when) What did the agent believe at that instant?
history(key) Every change to this belief, with provenance
reads_before(when) What did the agent consult before it acted?
stale_reads(when, older_than=) Which of those were already out of date?
verify() Has the record been tampered with?
EntityResolver.resolve(agent, key) Are Acme Corp and ACME the same company?

How it works

  • Append-only. Nothing is ever updated or deleted. A delete records a tombstone — the fact that the agent forgot something is itself a fact worth keeping.
  • Hash-chained. Every operation is SHA256(prev_hash + payload). Edit a value, delete a row, or rewrite a provenance string, and verify() fails. The record is tamper-evident.
  • Bitemporal. Time-travel is a single indexed query, not a replay from genesis.
  • Reads are separate. Reads are 10–100× write volume and don't change belief, so they live outside the chain — but each one points at the exact ledger row the agent saw.
  • Merges are beliefs too. When the entity resolver decides Acme and ACME are the same company, that decision goes in the ledger with its confidence and method. Why the agent thinks two things are the same is itself auditable.

See ARCHITECTURE.md for the design in depth.

Status

v0.x — early, but real. 81 tests passing. Not yet on PyPI.

Install from source:

git clone https://github.com/nomarin-ui/agent-memory-ledger
cd agent-memory-ledger
pip install -e ".[dev]"
pytest

Roadmap

  • LangChain integration — wrap your existing memory, change nothing else
  • CLI for time-travel queries
  • Postgres adapter
  • PyPI release (v0.1.0)

Feedback

If you run agents in production and have ever asked "why did it think that?" — I would like to hear from you. Open an issue.

License

MIT

Metadata

Release files for agent-memory-ledger 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-memory-ledger 0.1.0
File Size Uploaded Provenance
agent_memory_ledger-0.1.0.tar.gz 31.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-memory-ledger 0.1.0
File Interpreter ABI Platform
agent_memory_ledger-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.5 kB

Release files / agent_memory_ledger-0.1.0.tar.gz

Download URL agent_memory_ledger-0.1.0.tar.gz
Size 31.7 kB
Tags Source
SHA-256 checksum
How to use checksums
fb2757e5d455666b8e9e48f50df6c1a8d48d3cb653b886207f0e269d65dd5eda
BLAKE2b-256 checksum
How to use checksums
1760711a58649764d3ecaafa059e744406d81e285c8efffdbe0aef1601abb740
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.2

Release files / agent_memory_ledger-0.1.0-py3-none-any.whl

Download URL agent_memory_ledger-0.1.0-py3-none-any.whl
Size 23.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ffd4f876083910479194de49554582b8252406f1116b946391f690fa42adcb6d
BLAKE2b-256 checksum
How to use checksums
f7e31de37f72d687cefbcbac72dbade536e39a7e9bd230a755e785c0a592c9be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.2

Security for agent-memory-ledger 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page