Skip to main content
Intelliger
Verifiable Agent Evidence

Offline Verification of AI Agent Receipts

Verify AI agent receipts without trusting the producer database by checking schema, canonical payload, issuer keys, signatures, request binding and evidence limits.

Independent verifier checking a portable AI agent receipt without the issuer database
Intelliger
9 minute read · Cryptography and security review required

Offline verification of an AI agent receipt checks a portable record without calling the producer's live transaction database. The verifier validates schema, canonical payload, issuer trust, key status, signature and request binding. External facts such as settlement or delivery remain only as strong as their named evidence sources.

AI Agent Audit Trails explains why receipts and logs have different jobs. The verifier contract below is deliberately narrower: what can be checked from a portable package, and what must remain unknown.

Return findings, not one green badge

type Finding = {
  check: string;
  result: 'pass' | 'fail' | 'unknown';
  detail: string;
};

type VerificationReport = {
  receiptId: string;
  integrity: 'valid' | 'invalid' | 'unknown';
  findings: Finding[];
  unresolvedEvidence: string[];
};

An unknown issuer or unavailable historical key is unknown, not valid. A bad signature is invalid. A valid signature does not turn unresolved outcome evidence into a pass.

Verify in a fixed order

  1. Parse under strict size and recursion limits.
  2. Validate the declared schema version.
  3. Resolve issuer and allowed verification method under a trust policy.
  4. Check key status at the receipt time, including rotation and compromise rules.
  5. Recreate the canonical signing payload.
  6. Verify the signature.
  7. Recompute the request, authority, policy and approval digests when source objects are supplied.
  8. Report missing external evidence separately.

RFC 8785 defines JSON canonicalization suitable for repeatable hashing when used within a complete profile.

Publish tamper fixtures

FixtureExpected result
untouched known receiptsignature pass
amount changedsignature fail or request digest fail
unknown issuerunknown trust result
key revoked after eventresult follows declared historical policy
missing settlement evidenceintegrity may pass, outcome remains unknown
unsupported schema versionexplicit unsupported result

Cross-language fixtures matter because number, Unicode and key ordering differences can break otherwise correct implementations.

Make trust policy explicit

Signature verification answers a mathematical question. Trust requires more: which issuers are accepted, which algorithms and key sizes are allowed, how historical compromise is handled, and whether a verifier may fetch metadata from the network. Package or pin trust material for offline use instead of silently making a remote lookup.

The verifier should reject algorithm confusion, duplicate JSON keys, unbounded nesting, unknown critical fields and a receipt whose declared issuer does not match the verification method. Apply resource and memory limits before signature work.

Display assurance by claim. Integrity may be valid while authority evidence is missing and outcome evidence is unknown. A single green "verified" badge hides this distinction and invites readers to infer event truth.

Version fixtures with the schema and signature profile. Keep earlier fixture sets so key rotation or a library update cannot break historical verification unnoticed.

Use the audit trail architecture for issuance and blockchain proof versus receipt for assurance boundaries. The OATI public lookup and Receipt documentation expose developer-preview verification paths.

OATI's public conformance work does not amount to completed independent cryptographic review or proof that a deployment has no enforcement bypass. State those limits anywhere a verification result is shown.

Verifier review decisions

Strict offline verification should use packaged or pretrusted issuer metadata, keys, schemas and revocation evidence. A network-enabled mode may resolve references but changes the threat and reproducibility model. Label the mode and record each fetched resource, digest and trust decision. Do not silently contact URLs controlled by the receipt issuer.

Historical key policy needs effective, rotation and compromise times. A key retired normally may remain acceptable for earlier receipts. A compromise may invalidate or downgrade a period according to policy. The verifier must report which rule it applied instead of treating every currently revoked key the same.

Canonicalization creates repeatable bytes under a selected profile. It does not validate schema, business meaning or source truth. Parse under strict size and depth limits, reject duplicate keys, validate types and bounds, then canonicalize. Keep cross-language fixtures for numbers, Unicode and field handling.

Define critical extensions. An unknown critical field should produce unsupported or invalid, not a partial green result. Preserve noncritical signed fields according to the profile. Never discard an unknown field and verify a different payload from the one the issuer signed.

A QR code may carry a receipt or a digest and retrieval reference. It is not independent verification if it only opens the issuer's current website. The verifier still needs the payload, trust material, signature profile and source evidence. Offer a portable package for investigations that cannot depend on issuer availability.

Test valid, altered, ambiguous and resource-exhaustion fixtures across implementations. Compare structured findings rather than one boolean. Fuzz parsers and obtain independent cryptographic review for a production profile. Display assurance per claim: integrity may pass while authority or outcome remains unknown.

Package the verifier's own identity. Record implementation name and version, fixture or policy bundle, verification time and whether network access was permitted. Two tools can produce different findings because one knows an issuer or schema the other does not. Without that context, a later reviewer may treat an environmental difference as cryptographic disagreement.

Protect the verification report from becoming a stronger claim than the receipt. If provider evidence is absent, say that outcome is unresolved even when signature and request binding pass. If historical revocation data is incomplete, preserve unknown. The disciplined result is sometimes less satisfying than a green badge, but it is more useful during an audit or dispute.

Give operators a machine-readable report and a plain explanation of failed checks. The explanation should come from stable verifier codes, not a model asked to interpret arbitrary cryptographic errors. Keep the raw finding, affected field and trust-policy rule available so another implementation can reproduce the result.

Version the report schema separately from the receipt. Verifier findings and trust policies evolve even when the signed input does not. Preserve both versions so an old report can be interpreted without rerunning it under today's rules.