acdp — Python SDK
Python bindings for ACDP (acdp-py)
Thin PyO3 binding over the acdp Rust
library. Implements the producer- and consumer-side crypto for the Agent
Context Distribution Protocol — v0.1.0 core plus the v0.2.0 Trust &
Hardening surface (RFC-ACDP-0001 through 0015). HTTP is intentionally left
to the caller — pair this with httpx / requests for transport.
Package version tracks the binding release line (currently 0.8.0).
Install
pip install acdp # from PyPIInstall (development)
pip install maturin
maturin develop # editable install into the active venv
pytest tests/ # in-process unit tests, no HTTPBuild a wheel
maturin build --release # produces target/wheels/acdp-*.whl
pip install target/wheels/acdp-*.whlVerification surface
Beyond build_publish_request / build_supersede_request (Ed25519 and
P-256 producers) and the verify_content_hash / verify_signature
basics, AcdpVerifier exposes the full 0.2.0 surface:
verify_body_offline/verify_publish_request_offline— offlinedid:keyverification (no network).verify_receipt/verify_lineage_head_receipt— registry receipts (RFC-ACDP-0010/0011).verify_log_checkpoint/verify_log_inclusion/verify_log_consistency— transparency log (RFC-ACDP-0012).verify_lifecycle_event— lifecycle/retraction (RFC-ACDP-0013).parse_key_revocation/classify_under_revocation— key revocation (RFC-ACDP-0014).build_witness_cosignature/verify_witness_cosignature/evaluate_witness_quorum— witness cosigning (RFC-ACDP-0015).
AcdpDid, AcdpDidDocument, AcdpCanonicalizer, AcdpMerkle, and
AcdpSsrfPolicy are also exported.
Quickstart
import json, acdp
producer = acdp.AcdpProducer.generate(
"did:web:agents.example.com:my-agent",
"did:web:agents.example.com:my-agent#key-1",
)
raw = producer.build_publish_request(
title="Q1 snapshot",
context_type="data_snapshot",
summary="Quarter-end inventory",
)
request = json.loads(raw)
# POST `raw` (the JSON string) to the registry's /v1/contexts endpoint
# with your HTTP client of choice. On retrieve, validate the response:
body = ... # response.json()["body"]
acdp.AcdpVerifier.verify_content_hash(json.dumps(body), body["content_hash"])
acdp.AcdpVerifier.verify_signature(
pub_key_b64, # resolved from the producer's did:web doc
body["signature"]["value"],
body["content_hash"],
)Design rules
- JSON across the FFI boundary. Every method accepts and returns JSON strings — never a Rust type, never a Python dataclass. The wheel stays at ~500 lines of glue.
- Crypto in Rust, HTTP in Python. Key generation, JCS + SHA-256
hashing, Ed25519 signing, and signature verification all happen in
the underlying
acdpcrate. The Python side handles transport, retries, and observability. AcdpProducerstores a 32-byte seed. The RustSigningKeyisZeroizeOnDropand notClone, so the binding rebuilds the signing key from the seed on each call.- Golden vector parity.
test_golden_content_hashpins the Python-sidecontent_hashandsignature.valueagainst the spec'ssig-001fixture — the same constants the Rust suite asserts. A drift on either side is a protocol break.
Layout
bindings/acdp-py/
├── Cargo.toml # standalone [workspace]; depends on `acdp` via path
├── pyproject.toml # maturin build backend
├── README.md # this file
├── src/
│ ├── lib.rs # #[pymodule] entry point
│ ├── producer.rs # AcdpProducer: build/sign publish requests
│ ├── verifier.rs # AcdpVerifier: content_hash + signature verify
│ └── helpers.rs # visibility / context_type string parsers
└── tests/
└── test_producer.py