Python SDK
The IDProva Python SDK provides native Rust performance through PyO3 bindings. All cryptographic operations run in Rust — Python gets a safe, typed API with zero-copy where possible.
Installation
Section titled “Installation”pip install idprovaRequirements: Python 3.9+. Pre-built wheels for Linux (manylinux), macOS (x86 + ARM), and Windows.
Quick Start
Section titled “Quick Start”-
Create an agent identity
from idprova import AgentIdentityidentity = AgentIdentity.create("my-agent", domain="example.com")print(identity.did) # did:idprova:example.com:my-agent -
Issue a delegation token
dat = identity.issue_dat("did:idprova:example.com:sub-agent",["mcp:tool:read", "mcp:resource:docs:write"],expires_in_seconds=3600,)print(dat.to_compact()) # JWS compact serialization -
Verify the token
verified = dat.verify_signature(identity.public_key_bytes)dat.validate_timing() # raises if expiredprint(f"Scopes: {dat.scope}")
Core Classes
Section titled “Core Classes”AgentIdentity
Section titled “AgentIdentity”High-level convenience class — the easiest way to get started.
from idprova import AgentIdentity
# Create with auto-generated Ed25519 keypairidentity = AgentIdentity.create( "my-agent", domain="example.com", # default: "local.dev" controller="did:idprova:example.com:alice", # optional)
# Access componentsaid = identity.aid() # AID documentkeypair = identity.keypair() # Ed25519 KeyPairdid = identity.did # "did:idprova:example.com:my-agent"
# Issue delegation tokensdat = identity.issue_dat( "did:idprova:example.com:sub-agent", ["mcp:tool:*:read"], expires_in_seconds=3600,)KeyPair
Section titled “KeyPair”Ed25519 key pair for signing and verification. Private keys are held in Rust memory and never exposed to Python.
from idprova import KeyPair
# Generate a new keypairkp = KeyPair.generate()
# Sign and verifysig = kp.sign(b"hello world")assert kp.verify(b"hello world", sig)
# Access public keyprint(kp.public_key_multibase) # z6Mk... (base58btc)print(len(kp.public_key_bytes)) # 32
# Restore from saved secret (32 bytes)kp2 = KeyPair.from_secret_bytes(secret_bytes)AID & AIDBuilder
Section titled “AID & AIDBuilder”Create W3C DID Documents with agent metadata.
from idprova import AIDBuilder, KeyPair
kp = KeyPair.generate()
builder = AIDBuilder()builder.id("did:idprova:example.com:my-agent")builder.controller("did:idprova:example.com:alice")builder.name("My Agent")builder.description("A research assistant agent")builder.model("anthropic/claude-sonnet-4-5")builder.runtime("python/3.12")builder.trust_level("L0")builder.add_ed25519_key(kp)
aid = builder.build()
# Serialize / deserializejson_str = aid.to_json()aid2 = AID.from_json(json_str)aid2.validate() # raises on invalid structureDAT (Delegation Attestation Token)
Section titled “DAT (Delegation Attestation Token)”Signed, scoped, time-bounded permission tokens.
from idprova import DAT, KeyPair
issuer_kp = KeyPair.generate()
dat = DAT.issue( issuer_did="did:idprova:example.com:alice", subject_did="did:idprova:example.com:my-agent", scope=["mcp:tool:filesystem:read", "mcp:tool:filesystem:write"], expires_in_seconds=86400, # 24 hours signing_key=issuer_kp, max_actions=1000, # optional constraint require_receipt=True, # optional: require audit receipts)
# Serialize to JWS compact formatcompact = dat.to_compact()
# Parse and verifydat2 = DAT.from_compact(compact)dat2.verify_signature(issuer_kp.public_key_bytes)dat2.validate_timing()
# Inspect claimsprint(dat2.issuer) # did:idprova:example.com:aliceprint(dat2.subject) # did:idprova:example.com:my-agentprint(dat2.scope) # ["mcp:tool:filesystem:read", ...]print(dat2.jti) # unique token IDprint(dat2.is_expired) # Falseprint(dat2.expires_at) # Unix timestampPermission scope validation with wildcard support.
from idprova import Scope
parent = Scope("mcp:tool:filesystem:*")child = Scope("mcp:tool:filesystem:read")
assert parent.covers(child) # True — wildcard matchesassert not child.covers(parent) # False — can't escalateTrustLevel
Section titled “TrustLevel”Trust level comparison and validation.
from idprova import TrustLevel
l1 = TrustLevel("L1")l2 = TrustLevel("L2")
assert l2.meets_minimum(l1) # True — L2 >= L1assert not l1.meets_minimum(l2) # False — L1 < L2print(l1.description) # Human-readable descriptionReceiptLog
Section titled “ReceiptLog”Append-only, hash-chained audit log.
from idprova import ReceiptLog
log = ReceiptLog()print(log.last_hash) # "genesis"print(log.next_sequence) # 0print(len(log)) # 0
# Verify chain integritylog.verify_integrity() # raises if tampered
# Serializejson_str = log.to_json()Type Safety
Section titled “Type Safety”The SDK ships with PEP 561 type stubs (.pyi files). All classes have full type annotations for IDE autocompletion and mypy/pyright checking.
# mypy and pyright will catch type errors:dat = DAT.issue( issuer_did="did:idprova:example.com:alice", subject_did="did:idprova:example.com:agent", scope=["mcp:tool:read"], expires_in_seconds="not a number", # Type error! signing_key=kp,)Security Notes
Section titled “Security Notes”- Private keys never leave Rust memory — Python only holds opaque references
DAT.from_compact()rejects tokens withalg: "none"(SEC-3 algorithm confusion)- All cryptographic operations use audited
ed25519-dalekvia Rust - The SDK is compiled with
opt-level=3for production performance
Next Steps
Section titled “Next Steps”- Quick Start — End-to-end walkthrough with CLI
- Concepts: Delegation — Understand scope grammar and chains
- Core API Reference — Full Rust type reference