attest-protocol
Python SDK for the Action Receipts protocol
Create, sign, hash-chain, store, and verify cryptographically signed audit trails for AI agent actions.
Install
pip install attest-protocol
Quick start
Create and sign a receipt
from attest_protocol import (
create_receipt,
generate_key_pair,
hash_receipt,
sign_receipt,
CreateReceiptInput,
Chain,
Issuer,
Outcome,
Principal,
)
from attest_protocol.receipt.create import ActionInput
# Generate an Ed25519 key pair
keys = generate_key_pair()
# Create an unsigned receipt
unsigned = create_receipt(CreateReceiptInput(
issuer=Issuer(id="did:agent:my-agent"),
principal=Principal(id="did:user:alice"),
action=ActionInput(
type="filesystem.file.read",
risk_level="low",
),
outcome=Outcome(status="success"),
chain=Chain(
sequence=1,
previous_receipt_hash=None,
chain_id="chain_session-1",
),
))
# Sign and hash
receipt = sign_receipt(unsigned, keys.private_key, "did:agent:my-agent#key-1")
receipt_hash = hash_receipt(receipt)
Verify a receipt
from attest_protocol import verify_receipt
valid = verify_receipt(receipt, keys.public_key)
print(f"Signature valid: {valid}") # True
Verify a chain
from attest_protocol import verify_chain
# Verify a list of receipts (e.g. [receipt] from the example above)
result = verify_chain([receipt], keys.public_key)
print(f"Chain valid: {result.valid}")
print(f"Receipts verified: {result.length}")
if not result.valid:
print(f"Broken at index: {result.broken_at}")
Action taxonomy
The standardized action taxonomy (action types and risk levels) is defined in the protocol specification. Taxonomy classification will be added in a future milestone (M3).
What is an Action Receipt?
A W3C Verifiable Credential signed with Ed25519, recording:
| Field | What it captures |
|---|---|
| Action | What happened, classified by a standardized taxonomy |
| Principal | Who authorized it (human or organization) |
| Issuer | Which agent performed it |
| Outcome | Success/failure, reversibility, undo method |
| Chain | SHA-256 hash link to the previous receipt (tamper-evident) |
| Privacy | Parameters are hashed, never stored in plaintext |
API reference
Receipt creation and signing
from attest_protocol import (
create_receipt, # Build an unsigned receipt from input fields
generate_key_pair, # Ed25519 key pair (PEM-encoded)
sign_receipt, # Sign with Ed25519Signature2020 proof
verify_receipt, # Verify a receipt's signature
)
Hashing and canonicalization
from attest_protocol import (
canonicalize, # RFC 8785 JSON canonicalization
hash_receipt, # Hash receipt (excluding proof) -> "sha256:<hex>"
sha256, # Hash arbitrary data -> "sha256:<hex>"
)
Chain verification
from attest_protocol import (
verify_chain, # Verify signatures, hash links, and sequence numbering
)
Types (Pydantic v2 models)
from attest_protocol import (
ActionReceipt, # Signed receipt with proof
UnsignedActionReceipt, # Receipt before signing
Action, ActionTarget, Authorization, Chain,
CredentialSubject, Intent, Issuer, Operator,
Outcome, Principal, Proof, StateChange,
)
Subpackage imports
from attest_protocol.receipt import create_receipt, sign_receipt
from attest_protocol.receipt.hash import canonicalize
from attest_protocol.receipt.types import CONTEXT, CREDENTIAL_TYPE
TypeScript SDK compatibility
camelCase aliases are available for users coming from the TS SDK:
from attest_protocol import (
createReceipt, # = create_receipt
generateKeyPair, # = generate_key_pair
signReceipt, # = sign_receipt
verifyReceipt, # = verify_receipt
hashReceipt, # = hash_receipt
verifyChain, # = verify_chain
)
Cross-language compatibility
This SDK produces byte-identical output to @attest-protocol/attest-ts:
- RFC 8785 canonical JSON matches exactly
- SHA-256 hashes are identical
- Ed25519 signatures from either SDK verify in the other
Cross-language compatibility is verified by test vectors generated from the TypeScript SDK.
Project structure
src/attest_protocol/
receipt/
types.py # Pydantic models for all receipt types
create.py # Receipt creation with auto-generated IDs
signing.py # Ed25519 signing and verification
hash.py # RFC 8785 canonicalization + SHA-256
chain.py # Chain verification
Development
uv sync --all-extras
uv run pytest # run tests
uv run ruff check . # lint
uv run ruff format . # format
uv run pyright # type check
| Language | Python 3.11+ |
| Types | Pydantic v2, pyright strict mode |
| Linting | ruff |
| Testing | pytest |
| Dependencies | pydantic>=2.0, cryptography>=41.0 |
Ecosystem
| Repository | Description |
|---|---|
| attest-protocol/spec | Protocol specification, JSON Schemas, canonical taxonomy |
| attest-protocol/attest-ts | TypeScript SDK (npm) |
| attest-protocol/attest-py (this package) | Python SDK |
| ojongerius/attest | MCP proxy + CLI (reference implementation) |
License
Apache 2.0 — see LICENSE.
Metadata
Release files for attest-protocol 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| attest_protocol-0.2.0.tar.gz | 49.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| attest_protocol-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 69.6 kB
Release files / attest_protocol-0.2.0.tar.gz
| Download URL | attest_protocol-0.2.0.tar.gz |
|---|---|
| Size | 49.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f72331c5179748c15993b7a1b13ce2126edccc0cbcacf3ebd5e7bfcc75567272
|
|
BLAKE2b-256 checksum How to use checksums |
c059884693e56a429b22105c6e56ff7ca04663724673bfedbaf4e3b89dacdced
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.
Transparency logRelease files / attest_protocol-0.2.0-py3-none-any.whl
| Download URL | attest_protocol-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9e35e3dfcd5e5bfe941b240f7ca81ac5e06d50e66baf09b9c85bb799a9f9a901
|
|
BLAKE2b-256 checksum How to use checksums |
7beee7ab4aca164523beea94e2a7b6040634e8a9e305aaf3781a5ee3ec866f8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.
Transparency log