What is a receipt?
A receipt is a cryptographically signed, gateway-issued document that records the outcome of a policy guard request. It is the trust artifact of the AgentChain system — independently verifiable without a network call.Receipt lifecycle
Receipt fields
Verifier Note —executionTxHashis self-reported The EIP-712 ECDSA signature covers the receipt body at issue time, whenexecutionTxHash = bytes32(0). AfterreportExecution(), theexecutionTxHashfield is updated in the database but the original signature is not re-issued. Verifiers must use the originalreceiptHash(computed at issue time) for ECDSA verification — not a re-hashed post-execution body.
Deny Receipts are Signeddenyandapproval_requiredreceipts are signed with the same ECDSA key asallowreceipts. A signed deny receipt is a tamper-evident proof that the system evaluated and blocked the transaction. Thedecisionfield is included in the signed EIP-712 struct — it cannot be altered.
Signature scheme
Receipts are signed with EIP-712 (keccak256(0x1901 ‖ domainSeparator ‖ structHash)).
chainId in the domain separator binds the signature to a specific chain. A receipt signed for Base Sepolia (84532) cannot be replayed on Base mainnet (8453) — the domain hash will differ.
Local verification (no network)
@agentchain/core verifyReceiptSignature — pure ECDSA recover, no HTTP.
On-chain verification (trustless)
verifyWithAnchor performs two independent checks:
- ECDSA verify —
signerAddresscorrectly recovers fromreceiptHash+signature - On-chain check —
SignerAnchor.isAuthorized(signerAddress)returnstrue
anchorState is 'unavailable' and ECDSA verification alone is used. Never a silent pass.
Remote verification
SignerAnchor revocation status.
Fetch by ID
Report execution
AfterguardTransaction returns allow, call this after you send the transaction:
guardAndExecute calls this automatically.
decisionExpiresAt
The gateway sets decisionExpiresAt to issuedAt + 300s (configurable). If your execution logic takes more than 5 minutes, call guardTransaction again for a fresh receipt.
The SDK throws AgentChainExpiredDecision if decisionExpiresAt < now when guardAndExecute tries to send.
Policy revocation and the 5-minute window A receipt issued just before a policy is revoked remains valid for up to 300 seconds (5 minutes). This is by design — in-flight, already-authorized transactions must be allowed to complete. AfterdecisionExpiresAt,reportExecutionreturns410 DECISION_EXPIRED. The window cannot be shortened without breaking in-flight transactions.
Anchoring
When a policy hasanchoring = "receipt_hash_onchain", the gateway’s ReceiptAnchorJob batch-writes the receiptHash to ReceiptAnchor.sol on the declared chain. The receipt transitions from executed → anchored after 2 confirmations.
ReceiptAnchor on Base Sepolia: 0x1F98D953785047f25a4886D12D103F4D67F1D8B3

