Zanii Python SDK — verifiable identity and proof-of-action for AI agents
Project description
zanii
Verifiable identity and proof-of-action for AI agents. Give every agent a
cryptographic identity (did:key), scope what it's allowed to do with signed
delegation certificates, and emit a tamper-proof, hash-chained receipt for every
action it takes — anchored in an RFC 6962 Merkle transparency log. Anyone can
verify what an agent did, offline, without trusting the server that stored it.
Full protocol parity with the TypeScript SDK (@zanii/core / @zanii/sdk) —
cross-language test vectors guarantee byte-identical hashes and signatures. The
only runtime dependency is cryptography.
pip install zanii
Quickstart
from zanii import ZaniiAgent, fetch_and_verify_proof
from zanii.core import generate_keypair, create_cert
# 1. Identities. The owner delegates a scoped, expiring capability to the agent.
owner = generate_keypair()
agent = generate_keypair()
cert = create_cert(
issuer=owner.did,
subject=agent.did,
scopes=["crm.*"], # this agent may only act within crm.*
exp="2027-01-01T00:00:00Z",
issuer_private_key=owner.private_key,
)
# 2. Instrument the agent. Every action is signed and hash-chained locally,
# then batched to the log.
zanii = ZaniiAgent(
server_url="https://ledger.zanii.agency",
agent_did=agent.did,
agent_private_key=agent.private_key,
delegation=[cert],
# api_key="zk_live_...", # required when the log enforces write auth
)
receipt, receipt_hash = zanii.record(target="crm.lookup", payload={"email": "a@b.co"})
zanii.flush() # ship queued receipts to the log
# 3. Anyone can verify that proof — offline, zero trust in the server.
proof = fetch_and_verify_proof("https://ledger.zanii.agency", receipt_hash)
assert proof.ok
wrap_tool instruments an existing function so every call (sync or async) is
recorded automatically — result on success, error on failure:
lookup = zanii.wrap_tool("crm.lookup", crm.find) # crm.find is your own function
lookup("a@b.co") # transparently receipted
zanii.core — pure verification, no network
Import from zanii.core when you only build or verify proofs and never touch the
network (an auditor, a third-party verifier, an offline signer). Everything there
is deterministic and does no I/O; the network client lives on the top-level
zanii package.
from zanii.core import verify_audit_bundle
# A self-contained audit bundle (GET /v1/export/{agent_did}) is verified with no
# trusted party: signatures, delegation scope, Merkle inclusion, the per-agent
# hash chain, and on-chain anchor consistency.
report = verify_audit_bundle(bundle)
assert report.ok, [c for c in report.checks if not c["ok"]]
Fully typed — ships py.typed (PEP 561), so your type-checker sees every
signature.
MCP proxy
Front any MCP server so every tool call is receipted — no changes to the agent or the upstream server. Install the extra:
pip install "zanii[mcp]"
Wrap a connected upstream ClientSession with a ZaniiAgent; serve the result
in place of the real server. Tool lists pass through unchanged; each call is
recorded as mcp.<tool> — result on success, error on failure.
from zanii import ZaniiAgent
from zanii.mcp_proxy import create_zanii_proxy
proxy = create_zanii_proxy(upstream_session, ZaniiAgent(...))
Or run it standalone over stdio, wrapping an upstream stdio MCP server:
ZANII_SERVER=https://ledger.zanii.agency ZANII_IDENTITY=./identity.json \
python -m zanii.mcp_proxy -- npx some-mcp-server --its-args
Agent runtime — deterministic rails
The SDK above records proofs. zanii.runtime (optional) is the layer that governs
the action itself: the model proposes, tested code disposes. It enforces
the accountability rules that sit above the ledger — scoped authority, "no external
receipt → no claim of success", a fixed status vocabulary, manifest validation, and
a human confirmation gate for irreversible actions.
pip install "zanii[runtime]" # pure logic, no extra deps — ships with base zanii too
from zanii import ZaniiAgent
from zanii.runtime import Runtime, Tool, ToolResult
def send_email(to, subject):
provider_id = mail.send(to, subject) # your real integration
return ToolResult(ok=True, receipt_id=provider_id) # the provider's receipt
rt = Runtime(ZaniiAgent(...), [
Tool("email.send", scope="email.*", run=send_email, irreversible=True),
])
d = rt.propose("email.send", {"to": "a@b.co", "subject": "Hi"}, intent="follow up")
# → irreversible ⇒ d.status == "awaiting_confirmation"; nothing sent yet
d = rt.confirm(d.confirmation_id) # owner says yes (bound to this exact action)
# → d.status == "sent" (a provider receipt was returned) and it's recorded on the ledger
Status is earned: no receipt_id ⇒ attempted (never sent); a matched
read-back ⇒ confirmed; a thrown tool ⇒ failed. Out-of-scope or unknown tools are
rejected before anything runs; low confidence returns clarify instead of guessing.
Links
- Docs & concepts — https://ledger.zanii.agency/docs
- Live transparency log — https://ledger.zanii.agency
More optional modules
Everything below ships inside this one zanii package — no extra install unless a
module needs a third-party dep (those are opt-in extras, shown as zanii[…]). Import
only what a task needs.
Test, observe, receive:
zanii.webhooks— verifyX-Zanii-Signatureand dispatch typed webhook events:create_webhook_receiver(secret, on={...}). Stdlib only.zanii.testing—fake_ledger()+make_identity/make_cert/make_receiptfixtures. Unit-test agents offline (no server, real Merkle proofs).zanii.monitor— independent append-only + anchor watchdog.check_once(server), or thezanii-monitorCLI.zanii.witness— independent co-signer: verify append-only, then counter-sign (create_witness(kp).cosign(sth, …),verify_cosignature).zanii.otel(pip install "zanii[otel]") —with_tracing(agent)makes everyrecordan OpenTelemetry span.
Agent-framework adapters (receipt a whole run via the framework's own hook):
zanii.langchain(zanii[langchain]) —zanii_callbacks(agent)receipts every tool call in a LangChain or LangGraph run.zanii.openai_agents(zanii[openai-agents]) —ZaniiRunHooks(agent)for the OpenAI Agents SDK.zanii.crewai(zanii[crewai]) —instrument_crew(crew, agent)for CrewAI.zanii.connectors—wrap_toolbox/run_tool_callsfor raw OpenAI/Anthropic tool calls.
Compliance & privacy:
zanii.compliance—build_compliance_report(bundle, controls=…)→ an auditor report.zanii.retention— GDPR Art. 17 deletion attestations (build_retention_attestation).zanii.redact— selective disclosure:commit/disclose/verify_disclosure.
Discovery, payments & identity:
zanii.a2a_directory— resolve an agent DID to its verified history for A2A / agent cards.resolve_agent(did),resolve_and_verify(did)(pulls + verifies the audit bundle offline),agent_did_from_card.zanii.x402— bind a payment receipt to its on-chain settlement.verify_settlement,build_x402_payment, zero-depjson_rpc_tx_fetcherfor any EVM chain.zanii.erc8004— build/resolve/verify ERC-8004 agent registration files wired to Zanii proof endpoints.build_registration_file,to_data_uri,resolve_registration,verify_resolved_agent.
Keys, money, embeds, CLI:
zanii.kms— seal agent keys at rest (seal_identity/open_identity, scrypt + AES-256-GCM).zanii.policy— pre-action allow/deny/require_approval (create_policy_engine).zanii.payments— correct money for payment receipts (build_payment, integer minor units).zanii.embed— "Verified by Zanii" badge builders (agent_badge,badge_svg).zaniiconsole script — the CLI:zanii keygen,zanii delegate,zanii verify <hash>, …
Changelog
- 0.7.0 — discovery & commerce:
zanii.a2a_directory(resolve a DID to its verified history),zanii.x402(verify a payment receipt's on-chain settlement),zanii.erc8004(register/resolve/verify ERC-8004 agent identities). - 0.6.0 — accountability fixes: salted payload commitments by default (
record()— privacy/PDPL;salted_payload_hash/verify_payload, opt out withsalt=False); owner-signed confirmations (zanii.core.create_confirmation;Runtime(owner_did=…)requires a signed owner approval); receipt provenance (runtime_hash/model_id/manifest_hash) +Runtime(intent_receipts=True)two-phase; infrastructure co-signatures (create_cosignature, segregation of duties) andzanii.compliance.reconcile(omission catcher). - 0.5.1 — docs: this page now lists every bundled module + extra (no code change).
- 0.5.0 — framework adapters
zanii.langchain/zanii.openai_agents/zanii.crewai(extraszanii[langchain,openai-agents,crewai]), pluszanii.retentionandzanii.redact. - 0.4.0 —
zanii.cli(+ thezaniiconsole script),zanii.compliance,zanii.kms,zanii.witness,zanii.policy,zanii.payments,zanii.embed,zanii.connectors, andzanii.otel(zanii[otel]). - 0.3.0 — added
zanii.webhooks,zanii.testing, andzanii.monitor(+zanii-monitorCLI). - 0.2.0 — added
zanii.runtime(deterministic agent rails). - 0.1.0 — initial release: the client SDK, the pure
zanii.coreverification namespace,verify_audit_bundle,py.typed, and thezanii.mcp_proxy(pip install "zanii[mcp]").
License
Apache-2.0.
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 zanii-0.7.0.tar.gz.
File metadata
- Download URL: zanii-0.7.0.tar.gz
- Upload date:
- Size: 73.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e18b18cae2e0d956a7e811115e9bf10ba370b2ddfeb22b67f6749eee5c96e61
|
|
| MD5 |
4a5ab1fdaac07ad0c8ece5212e02d7d5
|
|
| BLAKE2b-256 |
b660f0bd12383ac34a87565f7b9056fbe8eb95d0ee0ce12f5482d38fd28e4ecf
|
File details
Details for the file zanii-0.7.0-py3-none-any.whl.
File metadata
- Download URL: zanii-0.7.0-py3-none-any.whl
- Upload date:
- Size: 65.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38864b603827b6fa7456df7fa2d814a58e63f3d7c6ec489542ef978d5982e6e1
|
|
| MD5 |
b61f1f5d1a1f230ae9511af1a6e2b30c
|
|
| BLAKE2b-256 |
d414d805d9205952796995db86418b28a479ad878373ed4497307ca580be9b4c
|