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.

python
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.

python
# 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.

python
# 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.

bash
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:

json
{
  "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:

LabelMeaning
validAll four sub-checks pass.
valid_commitment_not_rederivableAn 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_signatureThe signature does not verify against the canonical bytes.
signature_expiredThe record carried a valid_until and the verify call is past it.
signer_key_changedThe agent's current public key does not match the key that signed this record.
algorithm_mismatchThe signature's algorithm does not match the agent's declared algorithm.
agent_inactiveThe agent is suspended, decommissioned, or revoked.
agent_unknownNo 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.

json
{
  "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.

LabelMeaning
result_boundA protectmcp:observation:result_bound receipt. result_digest binds the SHA-256 of the canonical tool-response bytes.
digest_presentA result_digest is bound on a receipt that is not typed result-bound.
none_by_designA protectmcp:decision receipt. The decision/outcome boundary records the decision, never the execution outcome.
absentThe 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.

python
# 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.

Tip

Enterprise gets automatic proof verification as proofs are generated. The Free plan can verify proofs on demand using the API.