A Proof Packet is a per-action evidence bundle for a controlled action. It collects the DelegationReceipt, signed Runtime Gate DecisionReceipt, signed ExecutionReceipt, optional HumanApprovalReceipt, and optional remediation context into one JSON-serializable object.
Use a Proof Packet after controlled_action(...) returns status="executed"
or when you need to preserve the evidence around a blocked decision. For
approval flows, include the signed HumanApprovalReceipt before treating the
packet as fully verifiable approval evidence. A customer, auditor, or partner
can verify the packet offline with trusted backend signer DID(s).
See Approval Routing for the approve/deny and resume
path that produces the HumanApprovalReceipt.
Proof Packets are different from the audit-chain walkthrough in
examples/proof_pack/. A Proof Packet is one
controlled-action evidence bundle. The audit-chain walkthrough verifies
tamper resistance of audit events across a trail.
def build_proof_packet(
self,
delegation_receipt: dict,
outcome: ControlledActionOutcome,
decision_receipt_jcs: str | None = None,
approval_receipt_jcs: str | None = None,
remediation_case: dict | None = None,
remediation_refs: list[dict] | None = None,
) -> ProofPacketParameters:
| Parameter | Meaning |
|---|---|
delegation_receipt |
Signed DelegationReceipt authorizing the agent's action scope. |
outcome |
ControlledActionOutcome returned by controlled_action(...) or execute_after_approval(...). |
decision_receipt_jcs |
Exact signed Runtime Gate DecisionReceipt JSON text. Recommended for full verification. |
approval_receipt_jcs |
Exact signed HumanApprovalReceipt JSON text, when approval was required. |
remediation_case |
Optional remediation/dispute context. |
remediation_refs |
Optional evidence references associated with remediation. |
Fetch the signed Runtime Gate receipt with agent.get_decision_receipt(audit_id)
after controlled_action(...) returns. Pass the exact returned string as
decision_receipt_jcs; do not parse and re-serialize it.
The helper does not fetch remote resources or modify signed receipt text. Keep
the exact *_receipt_jcs strings returned by the SDK/API.
build_proof_packet(...) returns a ProofPacket object. Call
packet.to_dict() before JSON serialization.
| Field | Meaning |
|---|---|
agent_did |
Agent DID that requested the controlled action. |
base_url |
API base URL used by the SDK identity. |
sdk_version |
Installed SDK version that built the packet. |
generated_at |
UTC timestamp when the local packet was assembled. |
delegation_receipt |
Signed DelegationReceipt dictionary. |
outcome_status |
executed, approval_required, or blocked. |
audit_id |
Runtime Gate audit id when available. |
decision_receipt_jcs |
Exact signed DecisionReceipt JSON text. |
decision_receipt |
Parsed convenience copy of the DecisionReceipt. |
execution_receipt_jcs |
Exact signed ExecutionReceipt JSON text. |
execution_receipt |
Parsed convenience copy of the ExecutionReceipt. |
approval |
Parsed approval request metadata when available. |
approval_receipt_jcs |
Exact signed HumanApprovalReceipt JSON text. |
approval_receipt |
Parsed convenience copy of the approval receipt. |
remediation_case |
Optional remediation case metadata. |
remediation_refs |
Optional remediation evidence references. |
Hash linkage lives inside the signed receipt bodies. The verifier recomputes and compares those links, including DelegationReceipt hash, DecisionReceipt hash, approval hash, and execution linkage when present.
import json
from pathlib import Path
path = Path("proof-packet.json")
path.write_text(json.dumps(packet.to_dict(), indent=2), encoding="utf-8")
loaded = json.loads(path.read_text(encoding="utf-8"))Proof Packets are evidence artifacts, not private keys. Store them with normal
evidence-retention controls. For local files containing customer metadata, use
private storage or owner-only file permissions such as 0600. Do not store
private keys, API tokens, cloud credentials, or passphrases with a packet.
from agentveil import verify_proof_packet
verified = verify_proof_packet(
loaded,
trusted_decision_signer_dids={decision_signer_did},
trusted_execution_signer_dids={execution_signer_did},
trusted_human_approval_signer_dids={approval_signer_did},
)Signature:
def verify_proof_packet(
packet: object,
trusted_backend_signer_dids: Iterable[str] | None = None,
*,
trusted_decision_signer_dids: Iterable[str] | None = None,
trusted_execution_signer_dids: Iterable[str] | None = None,
trusted_human_approval_signer_dids: Iterable[str] | None = None,
) -> dictFor deployments that intentionally use one backend signer for all AVP-issued
receipt types, pass trusted_backend_signer_dids={...} instead.
On success, the verifier returns:
| Key | Meaning |
|---|---|
valid |
Always True on success. |
decision_receipt |
Verified DecisionReceipt metadata, including signer DID and digest. |
approval_receipt |
Verified approval receipt metadata or None. |
execution_receipt |
Verified ExecutionReceipt metadata or None. |
delegation_receipt_hash |
Recomputed canonical DelegationReceipt hash. |
verify_proof_packet(...) raises ProofVerificationError when the packet is
malformed, a signature is invalid, a signer DID is not trusted, required
receipts are missing, or cross-receipt hashes/action fields do not match. It
verifies historical evidence; it does not require a currently unexpired
DelegationReceipt window. ProofVerificationError is a ValueError subclass;
read the reason with str(exc).
| Pattern | Flow | Notes |
|---|---|---|
| Single action proof export | controlled_action(...) -> build_proof_packet(...) -> save JSON |
Keep the exact signed receipt strings. |
| Batch proof export | Build one packet per controlled action, then store an array of packet dictionaries | Do not merge signed receipt strings across actions. |
| Auditor verification | Load JSON -> verify_proof_packet(...) -> inspect valid, signer DIDs, and digests |
The auditor must know the trusted backend signer DID(s). |
| Long-term archival | Store packet JSON with audit-chain reference and release metadata | Retain raw signed receipts exactly as emitted. |
Catch ProofVerificationError separately from API exceptions:
try:
verified = verify_proof_packet(packet, trusted_backend_signer_dids={trusted_did})
except ProofVerificationError as exc:
print(str(exc))Common causes include:
| Failure | Recovery |
|---|---|
| Missing DecisionReceipt or ExecutionReceipt | Export the full proof artifacts from the controlled-action flow. |
| Approval path without signed approval receipt | Follow Approval Routing, then include the HumanApprovalReceipt before verification. |
| Untrusted signer DID | Use the correct AVP backend signer DID for the environment. |
| Signature invalid | Treat the packet as tampered or corrupted. Re-export from source artifacts. |
| Hash linkage mismatch | Treat the packet as assembled from mismatched action artifacts. |
| DelegationReceipt invalid | Obtain the original signed DelegationReceipt from the principal. |
- Customer Integration for the full controlled-action flow.
- DelegationReceipt Guide for delegation issuance and offline verification.
- Registration & Verification for agent identity setup.
- Error Handling for SDK exception and verifier error patterns.