Proof Packet Guide

May 8, 2026 ยท View on GitHub

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.

Build

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,
) -> ProofPacket

Parameters:

ParameterMeaning
delegation_receiptSigned DelegationReceipt authorizing the agent's action scope.
outcomeControlledActionOutcome returned by controlled_action(...) or execute_after_approval(...).
decision_receipt_jcsExact signed Runtime Gate DecisionReceipt JSON text. Recommended for full verification.
approval_receipt_jcsExact signed HumanApprovalReceipt JSON text, when approval was required.
remediation_caseOptional remediation/dispute context.
remediation_refsOptional 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.

Packet Structure

build_proof_packet(...) returns a ProofPacket object. Call packet.to_dict() before JSON serialization.

FieldMeaning
agent_didAgent DID that requested the controlled action.
base_urlAPI base URL used by the SDK identity.
sdk_versionInstalled SDK version that built the packet.
generated_atUTC timestamp when the local packet was assembled.
delegation_receiptSigned DelegationReceipt dictionary.
outcome_statusexecuted, approval_required, or blocked.
audit_idRuntime Gate audit id when available.
decision_receipt_jcsExact signed DecisionReceipt JSON text.
decision_receiptParsed convenience copy of the DecisionReceipt.
execution_receipt_jcsExact signed ExecutionReceipt JSON text.
execution_receiptParsed convenience copy of the ExecutionReceipt.
approvalParsed approval request metadata when available.
approval_receipt_jcsExact signed HumanApprovalReceipt JSON text.
approval_receiptParsed convenience copy of the approval receipt.
remediation_caseOptional remediation case metadata.
remediation_refsOptional 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.

Save And Reload

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.

Verify

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,
) -> dict

For deployments that intentionally use one backend signer for all AVP-issued receipt types, pass trusted_backend_signer_dids={...} instead.

On success, the verifier returns:

KeyMeaning
validAlways True on success.
decision_receiptVerified DecisionReceipt metadata, including signer DID and digest.
approval_receiptVerified approval receipt metadata or None.
execution_receiptVerified ExecutionReceipt metadata or None.
delegation_receipt_hashRecomputed 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).

Common Patterns

PatternFlowNotes
Single action proof exportcontrolled_action(...) -> build_proof_packet(...) -> save JSONKeep the exact signed receipt strings.
Batch proof exportBuild one packet per controlled action, then store an array of packet dictionariesDo not merge signed receipt strings across actions.
Auditor verificationLoad JSON -> verify_proof_packet(...) -> inspect valid, signer DIDs, and digestsThe auditor must know the trusted backend signer DID(s).
Long-term archivalStore packet JSON with audit-chain reference and release metadataRetain raw signed receipts exactly as emitted.

Error Handling

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:

FailureRecovery
Missing DecisionReceipt or ExecutionReceiptExport the full proof artifacts from the controlled-action flow.
Approval path without signed approval receiptFollow Approval Routing, then include the HumanApprovalReceipt before verification.
Untrusted signer DIDUse the correct AVP backend signer DID for the environment.
Signature invalidTreat the packet as tampered or corrupted. Re-export from source artifacts.
Hash linkage mismatchTreat the packet as assembled from mismatched action artifacts.
DelegationReceipt invalidObtain the original signed DelegationReceipt from the principal.