Cryptographic action receipts for AI agents: canonical JSON, Ed25519 signing, Merkle log, FastAPI ingest, LangGraph middleware, Postgres store, HTML rendering.
Project description
Maatora
Cryptographic, tamper-evident audit log for AI agents. Built for EU AI Act Article 12, SOC 2, and HIPAA — open-source under MIT.
Why this exists
AI agents take real actions in production: they call APIs, move money, update records, send messages. When something goes wrong — a regulator asks "what did the agent do?", a customer asks "did your agent really authorize this?", or an engineer asks "why did it call that tool with those arguments?" — you need a forensic chain you can prove, not just a dashboard you can show.
Most observability tools for agents (LangSmith, Langfuse, Helicone) provide tamper-resistant audit logs: the data is hard to modify because access is controlled. This SDK provides tamper-EVIDENT records: any modification breaks a cryptographic chain and is publicly detectable by anyone holding the public key.
This is the difference between "trust our SaaS" and "verify it yourself."
30-second quickstart
pip install maatora
from maatora import receipt
class InMemoryStore:
def __init__(self): self.receipts = []
def append(self, r): self.receipts.append(r)
store = InMemoryStore()
@receipt(action="transfer_funds", store=store)
def transfer_funds(actor_id: str, amount: float, to: str) -> dict:
return {"transferred": amount, "to": to}
transfer_funds(actor_id="agent-alpha", amount=100.0, to="alice")
print(store.receipts[0])
# {'action': 'transfer_funds', 'actor_id': 'agent-alpha',
# 'timestamp': 1716000000.0, 'input_hash': '...', 'output_hash': '...',
# 'status': 'success', 'error': None}
For Ed25519 signing and external verification, see
examples/04_verify_externally.py.
Verify it yourself
The central claim of the library is tamper-evident: anyone holding
the public key can detect any modification to a signed receipt. Here is
the 30-second proof, runnable as-is after pip install maatora:
from maatora import generate_keypair, sign, verify
priv, pub = generate_keypair()
canonical = b'{"action":"transfer","actor_id":"agent-alpha","amount":100}'
sig = sign(priv, canonical)
# Happy path — bytes unchanged since signing.
assert verify(pub, canonical, sig) is True
# Tampered path — a single byte changed; signature no longer holds.
assert verify(pub, canonical.replace(b"100", b"999"), sig) is False
print("Tamper-evident verification works as documented.")
This is the property no observability dashboard can offer: not "modifications are unlikely because access is controlled," but "any modification is publicly detectable by anyone holding the public key, without trusting us."
For verification against a wrong public key and signatures over full
canonical-JSON receipts, see
examples/04_verify_externally.py.
What you get
- Tamper-evident — Ed25519 signatures on every action, append-only Merkle log over SHA-256
- EU AI Act ready — full reconstructability, parent/child call trees, retention controls. See COMPLIANCE.md for a clause-by- clause mapping
- Framework-agnostic — works with LangGraph, AutoGen, CrewAI, LlamaIndex, or any Python callable
- Drop-in — one decorator on your tool functions, or one middleware wrap on your graph nodes
- Self-host or embed — minimal FastAPI ingest server included, or store receipts directly in your own database
- MIT forever — core SDK will never be relicensed. See LICENSING.md for the full layered model
How it compares
| This SDK | LangSmith | Langfuse | Helicone | |
|---|---|---|---|---|
| Cryptographic action signatures | ✅ | ❌ | ❌ | ❌ |
| Tamper-evident Merkle log | ✅ | ❌ | ❌ | ❌ |
| Verifiable proof for compliance | ✅ | ❌ | ❌ | ❌ |
| Open-source self-host | ✅ MIT | ❌ | ✅ MIT | partial |
| Observability dashboards | minimal | ✅ | ✅ | ✅ |
| Cost tracking | ❌ | ✅ | ✅ | ✅ |
Different tools for different jobs. Use this SDK alongside an observability tool, not instead of one.
Modules
| Module | Purpose |
|---|---|
receipt_canonical_json |
Deterministic JSON serialization (RFC 8785 style) |
ed25519_signer |
Keypair generation, signing, verification |
receipt_models |
Pydantic v2 models for receipts |
receipt_decorator |
@receipt wrapper for any function |
langgraph_middleware |
Drop-in middleware for LangGraph / agent frameworks |
merkle_log |
Tamper-evident append-only log |
fastapi_ingest |
Minimal HTTP endpoint to receive receipts |
postgres_store |
Persistence to PostgreSQL |
cli_viewer |
Local CLI for browsing receipts |
html_summary_renderer |
Human-readable audit reports |
Examples
Runnable examples live in examples/:
01_simple_decorator.py— minimal integration02_langgraph_middleware.py— agent-framework integration03_fastapi_ingest.py— centralized ingest endpoint04_verify_externally.py— Ed25519 sign, verify, tamper detection
CLI
maatora list
maatora show <receipt-id>
Compliance
This SDK is designed to help satisfy:
- EU AI Act Article 12 — record-keeping for high-risk AI systems (deadline August 2026)
- SOC 2 CC7.2 — tamper-evident audit logs of who accessed what data
- HIPAA Security Rule — integrity controls for audit records of PHI access
- GDPR Article 30 — records of processing activities
See COMPLIANCE.md for the clause-by-clause mapping. This document is informational, not legal advice. For your specific deployment, hire an auditor.
Roadmap
The roadmap reflects an audience-first phase. Cloud and enterprise modules are planned as separate repositories under a different license (see LICENSING.md) and are not on the current core roadmap.
Core SDK (this repository, MIT forever):
- Multi-agent call tree examples and helpers
- SIEM-export formats (Splunk HEC, Datadog Logs, Elastic ECS)
- HTML audit report polish
- LlamaIndex and CrewAI native integrations
- Documentation site (mkdocs-material)
- Reproducible benchmarks (signature throughput, Merkle proof size)
Contributing
Contributions are welcome under the Developer Certificate of Origin (DCO).
Sign off your commits with git commit -s. A CONTRIBUTING.md with
detailed guidelines will be added before the public launch.
Good first contributions:
- additional examples for your favorite agent framework
- additional storage backends (DuckDB, SQLite WAL mode, ClickHouse)
- documentation improvements
- SIEM exporters
Community
Community channels (Discord, Twitter/X, newsletter) will be announced before the public launch. For now, please open a GitHub issue for questions, bug reports, or feature requests.
License
MIT — free for any use including commercial. See LICENSE.
The full layered licensing model (core MIT forever, planned BSL for premium modules, planned proprietary cloud service) is documented in LICENSING.md.
Security
A formal threat model — assets, trust boundaries, STRIDE-organized threats and their mitigations, cryptographic choices and known limitations — is published as THREAT_MODEL.md. Read it before deploying in a setting where the receipts will be relied on for compliance or forensics.
To report a concern about the integrity of receipts, the signing process, or anything that could mislead a downstream auditor, follow the process in SECURITY.md — open a private GitHub Security Advisory rather than a public issue.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file maatora-0.1.0.tar.gz.
File metadata
- Download URL: maatora-0.1.0.tar.gz
- Upload date:
- Size: 31.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47392ee018dda31d5ec27efccbc7abad6281d79587303d11c9d1da5b4bed2fa7
|
|
| MD5 |
19026960daf9e2d3353302f493108de6
|
|
| BLAKE2b-256 |
e1e4fc4b4eaa6575f4446bc4a65a444246eec5447c934dd66d7b6e2d6d2de094
|
Provenance
The following attestation bundles were made for maatora-0.1.0.tar.gz:
Publisher:
publish.yml on Sergiipis/maatora
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
maatora-0.1.0.tar.gz -
Subject digest:
47392ee018dda31d5ec27efccbc7abad6281d79587303d11c9d1da5b4bed2fa7 - Sigstore transparency entry: 1662986038
- Sigstore integration time:
-
Permalink:
Sergiipis/maatora@739729e2db182ac0c796f4b17b289ad16102a604 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Sergiipis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@739729e2db182ac0c796f4b17b289ad16102a604 -
Trigger Event:
push
-
Statement type:
File details
Details for the file maatora-0.1.0-py3-none-any.whl.
File metadata
- Download URL: maatora-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e6b0b6acf77067c770404897e0901dc12e397d3cc5ecfd5dbf2a936243ae3c8
|
|
| MD5 |
ba3defeaaaf4a3e9f1ee9f145702ee82
|
|
| BLAKE2b-256 |
9ea04d1526433b1999ff6706cfb9cbb11067f8c3cb3b52c94462bc4358425876
|
Provenance
The following attestation bundles were made for maatora-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Sergiipis/maatora
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
maatora-0.1.0-py3-none-any.whl -
Subject digest:
4e6b0b6acf77067c770404897e0901dc12e397d3cc5ecfd5dbf2a936243ae3c8 - Sigstore transparency entry: 1662986096
- Sigstore integration time:
-
Permalink:
Sergiipis/maatora@739729e2db182ac0c796f4b17b289ad16102a604 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Sergiipis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@739729e2db182ac0c796f4b17b289ad16102a604 -
Trigger Event:
push
-
Statement type: