Skip to main content

Governed, provenance-first agent memory for AI systems.

Project description

Heartwood Memory

Governed, source-auditable memory for AI agents, embedded beside your existing systems of record.

Heartwood is a cryptographic trust root for agent memory: every memory is signed, recall runs under policy before ranking, the audit log is hash-chained and tamper-evident, and erasure emits a falsifiable per-subject key-destruction receipt. The package ships as an embedded Python library plus governed MCP adapter surfaces that run on your infrastructure.

Honest boundary. Heartwood is managed-key: the server decrypts to serve recall. The receipts below are source-auditable today. Deletion is a per-subject key-destruction workflow, not an instantaneous deletion guarantee. See Key custody & erasure.

Install

python -m pip install "heartwood-memory[recall,mcp]"

5-minute quickstart

Remember a governed memory, recall it under policy, and emit a key-destruction receipt:

from heartwood import Heartwood, Policy, Principal, prove_crypto_erase_path

# 1. Open an embedded, tenant-scoped store.
db = Heartwood(path="./heartwood.db", tenant="tenant:acme")

# 2. Remember. The record is signed and written to a hash-chained audit log.
db.remember(
    "Customer 42 is on the Enterprise plan.",
    subject="customer:42",
    created_by="agent:support",
    policy=Policy(classification="internal"),
)

# 3. Recall. Policy gates the candidate set before ranking.
principal = Principal(
    id="agent:support",
    tenant="tenant:acme",
    roles=("support",),
    clearance="internal",
)
out = db.recall(
    "what plan is customer 42 on?",
    principal=principal,
    filters={"subject": "customer:42"},
    k=5,
)

for hit in out["results"]:
    print(hit["content"], hit["provenance"]["signature_valid"])

# 4. Forget. This crypto-shreds the per-subject key and purges derived artifacts.
receipt = db.forget(
    "customer:42",
    mode="hard",
    actor="agent:support",
    reason="right-to-erasure request",
)
db.close()

proof = prove_crypto_erase_path(
    "./heartwood.db",
    tenant="tenant:acme",
    root_present=False,
).to_dict()
print(receipt["key_shredded"], proof["content_unrecoverable"])

Want governed memory for an MCP-capable agent instead of a library? See the governed MCP quickstart and the Codex local-stdio quickstart. Write and erase verbs are not exposed by default; operators opt in by naming them explicitly.

What you get - five receipts

Governance you can inspect and re-run at the record level:

Receipt What it does Boundary today
Signed provenance Every memory is signed; the signature and content hash are re-verified at read and surfaced on each result. Re-verified and surfaced, not yet enforced as a hard read failure.
Tamper-evident audit Hash-chained append-only log; verify_chain() detects an in-place edit or dropped row. Catches in-place tampering; tail-truncation needs an external anchor.
Policy before ranking Recall is restricted to cleared records before ranking; denied records are not scored, returned, or counted. Source-auditable; multi-tenant-at-scale validation is still in progress.
Key-destruction receipt forget(mode="hard") destroys the per-subject key and purges derived artifacts. Shows key destruction, not byte-level content deletion.
Faithfulness + egress gate Generated memories fail closed unless they pass a faithfulness check; rejected egress requests block the external-model call. Explicit override stores a downweighted, review-only copy.

Product shell

  • heartwood/ - embedded Python library: remember, recall, explain_recall, approve, forget, evaluate_egress, assess_faithfulness, remember_generated
  • heartwood/adapters/ - Anthropic Memory Tool and MCP adapter surfaces
  • sdk/typescript/ - TypeScript SDK helpers for governed memory and memory-tool workflows; governed recall parity is not shipped yet
  • examples/regulated-support/ - regulated-support demo with a generated compliance report
  • tests/ - product-shell smoke, provenance, policy, index, and memory-tool tests

Key docs

Run the console script after installation:

heartwood --help

For checkout development and test runs, install the local editable package:

python -m pip install -e ".[recall,mcp]"
python ./tests/smoke_test.py
python ./tests/test_memory_tool.py
python ./tests/test_provenance.py
python ./tests/test_trust_controls.py
python ./tests/test_index.py
python ./tests/test_inheritance.py

Run the TypeScript SDK tests:

npm --prefix ./sdk/typescript test

Run warm recall for hook/agent integration:

export HEARTWOOD_RECALL_TOKEN="$(openssl rand -hex 24)"
heartwood serve-recall --db ./heartwood.db --tenant tenant:ops --host 127.0.0.1 --port 8765
heartwood recall --url http://127.0.0.1:8765 --tenant tenant:ops --query "what memory applies here?" --k 5 --json
heartwood bench-recall --url http://127.0.0.1:8765 --tenant tenant:ops --query "what memory applies here?" --repeat 10 --max-p95-ms 500 --require-pass

Bulk-write JSON/JSONL records through the public tenant-aware API:

heartwood bulk-remember --input ./records.jsonl --db ./heartwood.db --tenant tenant:ops --output ./heartwood-bulk-report.json
python ./tests/test_bulk_api.py

Research & Proof Harnesses

Heartwood began as a proof project: before building ambitious cognition, prove boring trust - retrieval quality, generated-memory faithfulness, and deletion lineage. You do not need these harnesses to use the product; they exist so the governance claims above can be inspected and re-run.

Evidence boundary: the shipped package is heartwood/ plus its SDK and adapter surfaces. Product-facing enterprise retrieval evidence comes from experiments/product-retrieval/, which ingests the enterprise trace through Heartwood.remember() and evaluates Heartwood.recall(). The older experiments/typed-memory/ retrieval numbers remain research/proof-core evidence, useful for design exploration and adapter validation but not a substitute for product API gates.

Experiments

Run the Phase 0 end-to-end suite:

python ./experiments/phase0-trust-suite/src/phase0_trust_suite.py

Run the portable suite for fresh clones, manual verification, or containers without local LongMemEval fixtures:

python ./experiments/phase0-trust-suite/src/phase0_trust_suite.py --skip-longmemeval

Run the suite with the live Postgres adapter gate:

python ./experiments/phase0-trust-suite/src/phase0_trust_suite.py --include-postgres

Run typed-memory enterprise and LongMemEval benchmarks:

python ./experiments/typed-memory/src/typed_memory_benchmark.py --dataset enterprise --require-pass
python ./experiments/typed-memory/src/typed_memory_benchmark.py --dataset longmemeval-s-session-100 --require-pass

Run the product API enterprise retrieval benchmark:

python ./experiments/product-retrieval/src/heartwood_product_benchmark.py --require-pass
python ./experiments/product-retrieval/src/heartwood_product_benchmark.py --phase1-scale --require-pass

Run the SQLite-backed local memory-plane path:

python ./experiments/typed-memory/src/memory_plane_cli.py ingest --db ./experiments/typed-memory/results/heartwood_memory_plane.sqlite
python ./experiments/typed-memory/src/memory_plane_cli.py recall --db ./experiments/typed-memory/results/heartwood_memory_plane.sqlite --query-id q_customer42_refund_eligibility
python ./experiments/typed-memory/src/memory_plane_cli.py inspect --db ./experiments/typed-memory/results/heartwood_memory_plane.sqlite
python ./experiments/typed-memory/src/memory_plane_cli.py export-eval --db ./experiments/typed-memory/results/heartwood_memory_plane.sqlite --jsonl-output ./experiments/typed-memory/results/recall_eval_export.jsonl
python ./experiments/typed-memory/src/storage_adapter_smoke.py --require-pass

Run snapshot import and statistical reporting:

python ./experiments/typed-memory/src/snapshot_import_smoke.py --require-pass
python ./experiments/typed-memory/src/confidence_interval_report.py --result ./experiments/typed-memory/results/enterprise_latest.json --require-pass

Run the live Postgres adapter directly:

python ./experiments/typed-memory/src/postgres_adapter_smoke.py --require-pass

Run database/search-specific Phase 0 harnesses:

python ./experiments/filtered-search/src/filtered_search_benchmark.py --require-pass
python ./experiments/temporal-conflict/src/temporal_conflict_benchmark.py --require-pass
python ./experiments/context-ablation/src/context_ablation_benchmark.py --require-pass

Run the recall benchmark:

python ./experiments/recall-benchmark/src/benchmark.py

Run the realistic-trace threshold gate after benchmark result files exist:

python ./experiments/recall-benchmark/src/evaluate_thresholds.py ./experiments/recall-benchmark/results/longmemeval_s_session_100.json ./experiments/recall-benchmark/results/longmemeval_s_turn_100.json ./experiments/recall-benchmark/results/longmemeval_m_session_25.json ./experiments/recall-benchmark/results/longmemeval_m_turn_25.json ./experiments/recall-benchmark/results/longmemeval_s_session_50_dense.json ./experiments/recall-benchmark/results/longmemeval_s_turn_50_dense.json --output ./experiments/recall-benchmark/results/phase0_threshold_results.json --markdown-output ./docs/results/phase-0-threshold-results.md

Run deletion-lineage smoke test:

python ./experiments/deletion-lineage/src/deletion_smoke.py --subject customer_42

Run realistic deletion-lineage retrieval-path test:

python ./experiments/deletion-lineage/src/deletion_realistic.py --subject customer_42

Run negative missing-lineage deletion test:

python ./experiments/deletion-lineage/src/deletion_negative.py --subject customer_42

Run faithfulness-gate smoke test:

python ./experiments/faithfulness-gate/src/faithfulness_smoke.py

Run realistic and negative faithfulness-gate tests:

python ./experiments/faithfulness-gate/src/faithfulness_realistic.py
python ./experiments/faithfulness-gate/src/faithfulness_negative.py

Run egress-policy gate tests:

python ./experiments/egress-policy/src/egress_policy_gate.py
python ./experiments/egress-policy/src/egress_policy_gate.py --requests ./experiments/egress-policy/data/negative_requests.jsonl --output ./experiments/egress-policy/results/negative_latest.json --expect-no-unsafe-external
python ./experiments/egress-policy/src/provider_registry_gate.py

Run resilience gates for adversarial tenancy, local concurrency, and deletion chaos:

python ./experiments/resilience/src/adversarial_multitenant.py
python ./experiments/resilience/src/scale_concurrency_soak.py
python ./experiments/resilience/src/deletion_chaos.py

Run example framework adapter contract tests for Hermes/OpenClaw-style memory surfaces:

python ./experiments/adapter-contracts/src/framework_adapter_contracts.py

Build the local container image:

docker build -t heartwood-memory:local .

Run the Heartwood MCP server with a persistent local volume:

docker run --rm -it -v heartwood-data:/data -e HEARTWOOD_TENANT=tenant:local heartwood-memory:local

Run the local Compose stack with Heartwood MCP plus Postgres:

docker compose up --build

Build and run the verification image instead of the runtime image:

docker build --target verify -t heartwood-memory-verify .
docker run --rm heartwood-memory-verify

The verification image runs the portable trust suite. Run the local suite from the repo when the generated LongMemEval fixtures are available.

License

The core package in this repository is MIT licensed; see LICENSE. Commercial support, signed release distribution, managed key custody, and hosted services may be offered separately from the MIT core.

Current Bias

Prove boring trust before building ambitious cognition:

  • provenance
  • typed memory routing
  • policy-aware recall
  • temporal state
  • deletion completeness
  • generated-memory faithfulness
  • repeatable evals

The cognitive database vision should be earned by evidence from these loops.

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

heartwood_memory-0.1.2.tar.gz (138.3 kB view details)

Uploaded Source

Built Distribution

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

heartwood_memory-0.1.2-py3-none-any.whl (105.2 kB view details)

Uploaded Python 3

File details

Details for the file heartwood_memory-0.1.2.tar.gz.

File metadata

  • Download URL: heartwood_memory-0.1.2.tar.gz
  • Upload date:
  • Size: 138.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for heartwood_memory-0.1.2.tar.gz
Algorithm Hash digest
SHA256 11e1bd87b94813f446c5987d46f24b29405e0a3dad84b5c59369dbe03150100d
MD5 faa2c3f4991d372504431227e816a905
BLAKE2b-256 c3ba34668a798d746b514bbccdfb0a55f1ebca5ad5039b67f41110d555e881a4

See more details on using hashes here.

File details

Details for the file heartwood_memory-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for heartwood_memory-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ca1f8a76cf52f8b892f36df9eaedffb9a5774160b86371cd29683968ec3467c4
MD5 9207d293f4594462b144c7ae185daf29
BLAKE2b-256 296086267828a6a793e3343cc6585f8b09569884a3afcdd61fc7a4ae0c5c2f00

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