Proofs
Cryptographic proofs provide tamper-evident records of agent actions. Daily and signature proofs using OpenTimestamps are available on all plans. RFC 3161 timestamping is available on Enterprise.
Daily Proofs
Daily proofs are generated once per day and contain a cryptographic digest of all agent actions within that 24-hour window. Use them for periodic audits and compliance reporting.
import asqav
# Initialize with your API key
asqav.init(api_key="sk_...")
# List daily proofs for an agent
proofs = Asqav.fetchApi(f"/agents/{agent_id}/proofs/daily")
for proof in proofs:
print(f"Date: {proof['date']}")
print(f"Actions: {proof['action_count']}")
print(f"Status: {proof['status']}")
print(f"Hash: {proof['digest']}")
Signature Proofs
Signature proofs are created for each individual signed action. They contain the full cryptographic proof that a specific action was performed by a specific agent at a specific time.
# Get proof for a specific signature
proof = Asqav.fetchApi(f"/signatures/{signature_id}/proof")
print(f"Signature ID: {proof['signature_id']}")
print(f"Agent: {proof['agent_id']}")
print(f"Action: {proof['action']}")
print(f"Timestamp: {proof['timestamp']}")
print(f"Proof hash: {proof['proof_hash']}")
print(f"Status: {proof['status']}")
Proof Status
Each proof goes through a verification lifecycle:
| Status | Description |
|---|---|
pending |
Proof has been generated but not yet verified |
verified |
Proof has been cryptographically verified and is intact |
failed |
Proof verification failed - data may have been tampered with |
Verifying Proofs
Verify a proof to confirm it has not been tampered with. Verification checks the cryptographic digest against the original action data.
# Verify a specific proof
result = Asqav.postApi(f"/proofs/{proof_id}/verify")
if result["verified"]:
print("Proof is valid and intact")
else:
print(f"Verification failed: {result['reason']}")
# Verify all daily proofs for a date range
results = Asqav.postApi("/proofs/verify-batch", {
"agent_id": agent_id,
"start_date": "2026-03-01",
"end_date": "2026-03-28"
})
print(f"Verified: {results['verified_count']}")
print(f"Failed: {results['failed_count']}")
Public verify endpoint
Anyone holding a signature_id can ask the public verify endpoint for a granular outcome. No auth required.
curl https://api.asqav.com/api/v1/verify/sig_qMkGicNs1vEoJRv-4Kz5Zw
The response carries a top-level verified boolean plus a verification_detail object with four sub-checks and a stable validation_label:
{
"verified": true,
"verification_detail": {
"signer_key_match": true,
"signature_valid": true,
"algorithm_match": true,
"agent_active": true,
"validation_label": "valid"
}
}
The validation_label vocabulary names the failure mode so a regulator or court reads the forensic story without your code:
| Label | Meaning |
|---|---|
valid | All four sub-checks pass. |
valid_commitment_not_rederivable | An attestation receipt. The commitment matches and is signed and anchored, but the underlying claim is not re-derivable by Asqav or any third party. Only the holder of the commitment key can open it. This is not a third-party re-derivable proof of the claim. |
invalid_signature | The signature does not verify against the canonical bytes. |
signature_expired | The record carried a valid_until and the verify call is past it. |
signer_key_changed | The agent's current public key does not match the key that signed this record. |
algorithm_mismatch | The signature's algorithm does not match the agent's declared algorithm. |
agent_inactive | The agent is suspended, decommissioned, or revoked. |
agent_unknown | No agent record matches the signature. |
Execution evidence
The response also carries a top-level execution_evidence object so a verifier can answer "did execution output get captured" without reading the payload. It is a projection of the stored receipt columns - it never re-signs and never changes the verified verdict.
{
"execution_evidence": {
"present": true,
"label": "result_bound",
"result_digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"result_bound": true,
"none_by_design": false
}
}
The label names what execution evidence, if any, the receipt bound. present is the top-line boolean; result_digest echoes the bound hash for offline re-check.
| Label | Meaning |
|---|---|
result_bound | A protectmcp:observation:result_bound receipt. result_digest binds the SHA-256 of the canonical tool-response bytes. |
digest_present | A result_digest is bound on a receipt that is not typed result-bound. |
none_by_design | A protectmcp:decision receipt. The decision/outcome boundary records the decision, never the execution outcome. |
absent | The receipt binds no execution result. |
Proof Chain
Proofs are chained together so that each proof references the hash of the previous proof. This creates an append-only integrity chain - if any proof in the sequence is modified, all subsequent proofs will fail verification. The chain ensures that actions cannot be retroactively inserted, removed, or reordered.
# Inspect the proof chain for an agent
chain = Asqav.fetchApi(f"/agents/{agent_id}/proofs/chain")
print(f"Chain length: {chain['length']}")
print(f"Integrity: {chain['integrity']}")
print(f"Latest hash: {chain['head_hash']}")
Per-agent and per-organization scope
The signature, key-access, and group-audit hash chains are scoped per-agent (signature, key access) or per-organization (group audit). A tamper or delete on one tenant's record does not cascade across other tenants. The verifier re-derives record_hash from canonical fields, so a row mutation that also rewrites its own hash is detected. Cross-tenant links surface as cross_agent rather than as broken links.
Orphan and integrity sweeper
An hourly scheduler job marks Action rows older than 600 seconds with no corresponding SignatureRecord as signature_status="orphaned", and walks the per-agent signature chain to log real tampers. Stuck or half-finished sign flows surface in the dashboard and via the rejected-attempts log instead of sitting silently.
Enterprise gets automatic proof verification as proofs are generated. The Free plan can verify proofs on demand using the API.