Skip to main content

Auditable memory engine for agents.

Project description

aetnamem

A local-first, zero-dependency Python engine for provenance-aware agent memory and optional guarded actions. The reference store is one SQLite file. Its security claims are deterministic and testable, but deliberately narrower than “the database is trusted” or “every external action is reversible.”

  • Provenance is required. Extracted records link to their source episode; derived proposals instead cite existing episode or record IDs. Records also carry source, session, turn, time, confidence, status, and trust metadata.
  • Classified untrusted content is quarantined. Records classified as webpage or tool output land quarantined until promote(). Correct origin classification is a host responsibility: an untrusted caller that may lie about source_type is outside this local API's trust boundary. promote() records a trust transition but does not authenticate human confirmation; protect or withhold that capability when the agent itself is untrusted.
  • Recognized corrections supersede. When extraction assigns the same fact_key, the new trusted record supersedes the previous active record; the old record remains inspectable. Unrecognized or unkeyed contradictions are not automatically resolved.
  • Memory content is logically purged. forget() tombstones matching records, clears their content and fact key, clears matching source episode text, removes FTS entries, and returns a deletion receipt. SQLite free pages, WAL files, filesystem snapshots, replicas, and backups require their own secure-erasure and retention controls.
  • The audit log is independently checkable. Engine-generated memory and guarded-action transitions join a per-subject SHA-256 chain specified in audit-log specification. The standard-library independent verifier imports no aetnamem code. Hash chaining detects edits relative to a trusted head; externally anchored checkpoints are required to detect suffix deletion or replacement of the entire database.
  • Sensitive values are separated on guarded paths. Core memory and guarded-action events use content digests and structural metadata. Raw action arguments and before-images live in an erasable payload table. retain_query_text=True stores raw recall queries, and the low-level log_action() method accepts caller-provided payloads, so callers must not place secrets or raw content there.

Guarantee boundaries

boundary engine enforces deployment must provide
memory origin quarantine based on the supplied/classified source type authentic source attribution when callers are not trusted
quarantine promotion only quarantined records can be promoted; transition is audited authenticated user confirmation and access control to promote()
audit history canonical hashes, per-subject chaining, receipt binding external checkpoint anchoring against database-owner rewriting
memory erasure logical purge from live tables and indexes backup/WAL/snapshot retention and forensic secure deletion
action authority exact-plan HMAC signed by a reviewer-key holder protecting that key and the staging boundary from the agent
approver identity records the supplied approver label identity authentication; the shared HMAC does not prove that label
external effects adapter preconditions, receipts, postcondition checks, explicit uncertainty provider-specific idempotency and authoritative recovery where needed

Install & use

pip install aetnamem
# or, from a checkout:
pip install -e .
from aetnamem import Memory

m = Memory("./memories.db")          # or ":memory:"

m.remember("user-1", "My preferred airport is SFO.", session_id="s1")
m.remember("user-1", "Actually, use OAK as my preferred airport going forward.",
           session_id="s2")

m.recall("user-1", "Which airport should I fly from?")
# -> [{'content': "User's preferred airport is OAK.", 'status': 'active', ...}]

m.forget("user-1", utterance="Forget my preferred airport.")
m.inspect("user-1")                  # full evidence dump, incl. audit chain check

The core verbs — remember, recall, list, forget, inspect, audit — plus promote (quarantine release), log_action (agent audit events), consolidate, persona, scenes, propose, checkpoint, and verify are available from Python and the CLI, so any process that can run a shell command is a client:

aetna000 remember   ./memories.db user-1 "My preferred airport is SFO." --session s1
aetna000 recall     ./memories.db user-1 "Which airport should I book from?"
aetna000 forget     ./memories.db user-1 --utterance "Forget my preferred airport."
aetna000 list       ./memories.db user-1 --all
aetna000 promote    ./memories.db user-1 rec_...
aetna000 log-action ./memories.db user-1 tool_call --payload '{"tool":"calendar"}'
aetna000 consolidate ./memories.db user-1
aetna000 persona    ./memories.db user-1
aetna000 scenes     ./memories.db user-1
aetna000 inspect    ./memories.db user-1
aetna000 audit      ./memories.db user-1
aetna000 checkpoint ./memories.db ./checkpoints.jsonl   # anchor this file externally
aetna000 verify     ./memories.db --checkpoints ./checkpoints.jsonl
python tools/verify_audit.py ./memories.db --checkpoints ./checkpoints.jsonl  # no aetnamem import

The standalone tools/verify_*.py commands are included in Git checkouts and source distributions. Wheel-only installs should use aetna000 verify and aetna000 actions verify, which cover the same integrity rules.

Guarded actions

Guarded-actions mode turns a proposed tool mutation into a canonical hash-bound WorldPatch: exact operation digests, resource preconditions, adapter fingerprints, causal evidence, authority, approval, execution attempts, verification, compensation, and a receipt all share the subject's audit chain. Evidence that merely informed_by an operation is distinct from the host-attested authorized_by evidence that permits it.

The first reference adapter performs root-confined UTF-8 file writes and deletes. It is classified as verified compensatable, not transactionally reversible: Aetna rechecks the before-state, executes only an exact approved plan, observes the after-state, and verifies any compensation against the captured before-state.

mkdir -p ./workspace

# Agent/host staging boundary: no reviewer key is needed here.
aetna000 actions stage ./memories.db user-1 filesystem write_text \
  --root ./workspace \
  --args '{"path":"report.md","content":"reviewed content"}' \
  --actor researcher-agent \
  --authority-id task-42 \
  --authority-digest 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

aetna000 actions show    ./memories.db act_...

# Separate trusted reviewer/executor shell. Persist this key securely.
export AETNA000_APPROVAL_KEY="$(python -c 'import secrets; print(secrets.token_hex(32))')"
aetna000 actions approve ./memories.db act_... --approver-label user-1
aetna000 actions commit  ./memories.db act_... --root ./workspace
aetna000 actions verify  ./memories.db act_...
python tools/verify_actions.py ./memories.db act_...  # no aetnamem import

Changing the persisted plan, adapter manifest, approval binding, expiry, or guarded file precondition prevents execution. Raw arguments, before-images, and provider receipts live in the erasable action payload plane; audit events contain only structural metadata and digests. Erase those payloads after their retention period with aetna000 actions purge-payloads ./memories.db act_.... If a process dies across an external execution boundary, use aetna000 actions recover ./memories.db act_...; it fences in-flight effects as uncertain and emits a recovery_required receipt instead of retrying.

Compatible external transaction journals can join the same forensic timeline without copying their raw arguments, snapshots, results, claimed actors, or client IDs into the audit plane:

aetna000 actions import-journal ./memories.db user-1 ./source-journal.db \
  --source-id production-agent

Imports are idempotent per source/transaction and are explicitly labeled unverified_operational_journal: importing external evidence does not upgrade its mutable status rows or claimed identities into Aetna proof.

The HMAC approval key belongs in the human/reviewer process, not the agent-facing process. The --approver-label value is attribution; the shared key authenticates key possession, not that label. Likewise, CLI --authority-id/--authority-digest flags are only host-attested when a trusted host controls the staging command. The filesystem CLI is a reference vertical slice; the MCP gate, Telegram reviewer, additional execution providers, Firestore, and X adapters are tracked explicitly in the roadmap. Protocol and security details are in guarded-actions guide.

Use from agents (MCP)

aetna000 mcp currently serves memory verbs only as MCP tools over stdio: newline-delimited JSON-RPC implemented with the standard library only, so the zero-dependency promise holds. Defaults: database at ~/.aetnamem/memories.db (override with --db or $AETNAMEM_DB) and subject default (--subject), so single-user personal agents need no per-call subject wiring. It is not yet an action interception gateway and does not prevent an agent from calling other write tools directly.

Claude Code:

claude mcp add aetnamem -- aetna000 mcp

Claude Desktop / any host with JSON MCP config (OpenClaw's MCP bridge takes the same command + args shape):

{
  "mcpServers": {
    "aetnamem": {
      "command": "aetna000",
      "args": ["mcp", "--db", "/home/you/.aetnamem/memories.db"]
    }
  }
}

The agent gets memory_remember, memory_recall, memory_recall_block (bounded prompt-injection block), memory_persona, memory_capture (auto-capture with digest-only assistant/tool logging), memory_list, memory_forget, memory_promote, memory_audit, memory_verify, and memory_log_action.

subject_id is a storage scope chosen by the caller, not an authenticated tenant identity. Likewise, exposing memory_promote lets the agent request a promotion; use a trusted approval layer or omit that tool when promotion must be human-only.

Grok/xAI users: the Grok/xAI guide shows how to expose aetnamem as xAI function-calling tools today, with a local playground that lets Grok search, capture, forget, and audit memory while the engine keeps provenance and deletion receipts. xAI Remote MCP is the deployment path once the local stdio MCP server is exposed behind an HTTP/SSE gateway.

OpenClaw users: the native integration is a native plugin that adds automatic memory — auto-recall injection before every prompt and auto-capture after every turn — on top of the same engine and audit chain. The policy gates run server-side, so a hostile webpage summarized by the agent still cannot plant durable memory, deletion still returns receipts, and you can independently audit the same SQLite file with aetna000 verify or tools/verify_audit.py while the agent uses it. Full tool catalog, host configs, and troubleshooting: integration guide.

Integrating with other agent frameworks

The rule is: MCP first, native adapter only when it adds lifecycle hooks. Do not fork the memory semantics per host. aetnamem should stay the auditable engine; framework integrations should be thin wrappers that call the same MCP/Python verbs and preserve the same audit trail.

For any MCP-capable host, start with:

aetna000 mcp --db ~/.aetnamem/memories.db --subject you

Then configure the host to expose the memory_* tools. This is the right first path for Hermes-style agents, Claude Desktop, Claude Code, and any framework that can launch a stdio MCP server.

Build a native adapter only when the framework gives useful hooks:

hook point aetnamem call purpose
before prompt/context build memory_persona + memory_recall_block inject bounded, audited context
after user/agent turn memory_capture capture user facts; log assistant/tool output as digests
before history write strip <user_persona> / <relevant_memories> prevent recall feedback loops
explicit agent tools memory_recall, memory_forget, memory_audit, memory_verify search, request logical purge, and verify recorded behavior

Native adapters should pass the host's session_id and turn_id whenever available, so memory reads, writes, tool calls, forgets, and user-visible responses line up in one audit timeline.

Priority targets:

framework / host first integration native adapter shape
OpenClaw implemented native plugin hook-based auto-recall/capture
Hermes MCP setup guide first memory-provider/plugin wrapper if its provider API is stable
LangGraph Python helper node/store recall node before model call, capture node after turn
OpenAI Agents SDK tools + runner/session wrapper pre-run context builder and post-run capture
CrewAI external memory tools memory adapter if its memory API can preserve receipts/audit IDs
Microsoft Agent Framework / Semantic Kernel plugin/tools context provider plus action logging
LlamaIndex / Haystack tool/component wrapper long-term memory component, not replacement for short-term chat state

The adapter directory should stay organized by host:

integrations/
  openclaw/
  hermes/
  langgraph/
  openai-agents/
  crewai/
  microsoft-agent-framework/
  llamaindex/
  haystack/

Each adapter should document the same guarantees: untrusted content stays quarantined, deletion returns receipts, recall injection is bounded and audited, and the SQLite database can still be verified externally with aetna000 verify or tools/verify_audit.py.

Compliance posture

The architecture separates mutable content tables from an engine-append-only, hash-chained audit table. This can support accountability, access, rectification, and deletion workflows, but it is not compliance certification or legal advice. forget() performs a logical purge in the live database; it does not by itself sanitize SQLite free pages, WAL files, backups, exports, or external replicas. Checkpoint placement, retention, secure erasure, access control, identity, lawful basis, and jurisdiction-specific requirements remain deployment responsibilities. See the audit-log specification for the precise integrity threat model.

Memory layers

  • L0 — episodes: raw turns, append-only, purged by deletion.
  • L1 — records: extracted facts with provenance.
  • L2 — scenes: deterministic per-session view (aetna000 scenes).
  • L3 — persona: live-derived snapshot of active facts (aetna000 persona, MCP memory_persona) — no cached persona is stored; each generated snapshot carries its source record IDs.
  • Derived proposals: external LLM/batch jobs submit candidates via aetna000 propose / Memory.propose_facts(); they land quarantined with mandatory evidence links and only activate through promote().

How recall works

Recall has top-k semantics, like a vector store: every active record is scored (SQLite FTS5 full-text relevance with porter stemming, plus trust and recency priors) and the best limit are returned. Quarantined, superseded, and tombstoned records are never candidates. Every recall writes a retrieval event containing all candidate scores, so the ranking itself is auditable. Pass min_score= to drop weak matches.

What v0 is and is not

v0 extraction is deterministic (generic sentence patterns: "my X is Y", "use Y as my X", "remember that …", "I avoid …") so that policy failures are debuggable, not probabilistic. The local Python API, CLI, MCP server, deterministic consolidation, persona snapshots, scenes, checkpoints, and independent memory verifier are implemented. Guarded Actions additionally ships an action ledger, exact-plan shared-key approvals, filesystem reference adapter, recovery fencing, external journal import, and independent action verifier. The MCP action gate, authenticated host identity, encrypted payloads, LLM-backed extraction, vector similarity, HTTP deployments, and additional storage backends remain roadmap work — see the roadmap. The policy gates in aetnamem/core/policy.py are the product; nothing in the engine may reference the vocabulary of a benchmark scenario.

Documentation

  • Integration guide — full CLI reference (every command, flags, output shapes, exit codes) and MCP server reference (transport, flags, tool catalog, host configs for Claude Code / Claude Desktop / OpenClaw-style bridges, security properties, troubleshooting).
  • OpenClaw setup — visual (Mermaid) walkthrough of wiring aetnamem into OpenClaw or any MCP host: setup flow, runtime sequence, the quarantine gate, and the external audit loop.
  • Grok/xAI guide — Grok/xAI function-calling quickstart, local playground, and Remote MCP deployment notes.
  • Auditing guide — how to use the auditability: checkpoint cadence and anchoring recipes, verifying after an incident, handling erasure/access/rectification requests with receipts, reviewing quarantine, logging agent actions onto the same chain, and what to hand an external auditor.
  • Audit-log specification — the frozen wire format: canonical serialization, hash preimages, chain/checkpoint/receipt verification rules, and the threat-model table.
  • Guarded actions — action modes, authority boundaries, state transitions, guarantees, and non-guarantees.
  • Roadmap — completed foundation work and remaining product, provider, security, and interface tasks.
  • Architecture plan — architecture plan and roadmap.

Benchmark

Development is gated on MemoryStackBench's seven_sins_v0_1 suite (webpage poisoning, retention after deletion, missing provenance, stale temporal updates, overgeneralization). Current score: 33/33, with unit tests covering the same gates on non-benchmark vocabulary to keep the score honest.

git clone https://github.com/aetna000/MemoryStackBench.git
cd MemoryStackBench
cp /path/to/aetnamem/bench/adapters/aetnamem.py memorybench/adapters/aetnamem.py
cp /path/to/aetnamem/bench/targets/aetnamem.yaml targets/aetnamem.yaml
PYTHONPATH=/path/to/aetnamem:$PWD \
python -m memorybench.cli run \
  --target targets/aetnamem.yaml \
  --suite suites/seven_sins_v0_1 \
  --out runs/aetnamem-local

License

AGPL-3.0 (see the license). Anyone may use aetnamem, including commercially, but derivative works — including software that serves aetnamem over a network — must be released under the same terms.

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

aetnamem-0.2.0.tar.gz (127.3 kB view details)

Uploaded Source

Built Distribution

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

aetnamem-0.2.0-py3-none-any.whl (75.0 kB view details)

Uploaded Python 3

File details

Details for the file aetnamem-0.2.0.tar.gz.

File metadata

  • Download URL: aetnamem-0.2.0.tar.gz
  • Upload date:
  • Size: 127.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for aetnamem-0.2.0.tar.gz
Algorithm Hash digest
SHA256 53c88ae24f864aad599cb71c6bcaaa754f4deb803e462fa8d12da3006d677a10
MD5 5cc8c042dbef81e0645cbf82760e300f
BLAKE2b-256 5502c9413252de56ab3c995ff7d6362c17cf93145eb7234e07b3ed16c122303c

See more details on using hashes here.

Provenance

The following attestation bundles were made for aetnamem-0.2.0.tar.gz:

Publisher: publish.yml on aetna000/aetnamem

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

File details

Details for the file aetnamem-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: aetnamem-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 75.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for aetnamem-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 25cddad116dc86e290b94ab56102986aef626d9bf942dcafacd574d7087cf049
MD5 34e2d93ce92d9a59acb855dfb6e71b34
BLAKE2b-256 c4cf702f9c62ea3a7c87760b15fca83cc006329a725cdb2859347fab584fd571

See more details on using hashes here.

Provenance

The following attestation bundles were made for aetnamem-0.2.0-py3-none-any.whl:

Publisher: publish.yml on aetna000/aetnamem

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