An Agent pays $10,000 for a data analysis job that never gets delivered. The escrow is refunded, but the downstream value that depended on the result may already be lost.
Today there is no standard on-chain primitive that lets a provider pre-commit collateral against a specific job, with a standardized claim path if the job fails.
This draft proposes the Agent Assurance Protocol (AAP): a standard that lets an Agent lock its own capital as a fulfillment guarantee for a specific job, with a programmable claim lifecycle if that guarantee is triggered.
AAP builds on ERC-8183 (Agentic Commerce). ERC-8183 handles job execution and escrow settlement, but stops at the refund. AAP adds the layer above: self-funded collateral commitments, coverage types, and a claims resolution flow. Integration is read-only: AAP observes ERC-8183 job state without modifying ERC-8183 contracts. It may also integrate optionally with ERC-8004 for identity gating and resolver accuracy tracking.
The gap
ERC-8183 covers the happy path and the basic failure path (refund). It does not cover:
-
Consequential loss from provider non-delivery: the client is refunded, but not compensated for the value the job was meant to produce
-
Evaluator error: a wrongful rejection or fraudulent approval leaves the affected party without a standardized recourse path
-
Post-completion settlement failure: the job is completed and attested, but funds still fail to release due to the Assured Agent’s actions
Agents also do not have practical access to traditional surety or guarantee markets. What is missing is a standard primitive for: “I lock X against job Y, and if I fail under defined conditions, you can claim against that locked collateral.”
What AAP standardizes
AAP introduces three primitives:
-
AssuranceAccount: a per-Agent, self-funded collateral reserve -
JobAssurance: a commitment allocation tied to a specific ERC-8183 job -
Claim: a payout request when coverage conditions are met
Three mandatory coverage types:
| Coverage Type | What it covers |
|---|---|
JobFailure |
Provider non-delivery; the job reaches a rejected or expired terminal state |
EvaluatorDispute |
Evaluator decision challenged through a formal dispute state or recognized on-chain dispute attestation |
SettlementDefault |
Post-completion settlement failure attributable to the Assured Agent |
Two additional types (AMLFreeze, SlashingLoss) are extension-reserved for encoding stability across implementations.
This is not pooled insurance. Each Agent backs its own commitments from its own capital. There is no shared underwriting pool and no third-party insurer in the core model.
Core interface
interface IAAP {
// Account lifecycle
function depositAssurance(uint256 amount) external;
function withdrawAvailableAssurance(uint256 amount) external;
function getAssuranceAccount(address agent) external view returns (AssuranceAccount memory);
// Assurance lifecycle
function commitToJob(
bytes32 jobId,
CoverageType coverageType,
address beneficiary,
uint256 amount,
uint64 expiry
) external returns (bytes32 assuranceId);
function releaseCommitment(bytes32 assuranceId) external;
function expireCommitment(bytes32 assuranceId) external;
function getJobAssurance(bytes32 assuranceId) external view returns (JobAssurance memory);
// Claim lifecycle
function fileClaim(
bytes32 assuranceId,
uint256 requestedAmount,
bytes calldata evidence
) external returns (bytes32 claimId);
function resolveClaim(
bytes32 claimId,
bool approved,
uint256 approvedAmount,
bytes calldata reason
) external;
function payout(bytes32 claimId) external;
function getClaim(bytes32 claimId) external view returns (Claim memory);
}
Key accounting invariant:
totalFunded == availableAmount + lockedAmount + paidOutAmount
This invariant must hold after every state-mutating operation.
Design decisions
-
Self-funded, not pooled: each Agent backs its own commitments from its own
AssuranceAccount -
Single Claim per
JobAssurance: this is a deliberate anti-spam design choice; renewal requires release or expiry of the prior assurance first -
Permissionless
payout(): anyone may trigger settlement once a Claim is approved (keeper bots, Beneficiary, Resolver) -
Strict insolvency semantics:
payout()reverts rather than partial-paying; the core model preserves accounting invariants over liveness -
Delegated funding reserved: v1 is self-funded only; third-party backing is reserved for a future extension
Optional extensions may include collateral recommendation hooks (IRiskHook), AML screening (IAMLHook), multi-resolver adjudication, optimistic resolution, and resolver staking/slashing.
Draft spec: PR link
Open questions
I would especially appreciate feedback on the following:
-
SettlementDefault verifiability: this coverage type depends on attribution. In practice, the line between “Agent fault” and “infrastructure failure” can be difficult to draw purely from raw on-chain state. Is requiring a recognized on-chain attestation the right minimum bar, or should
SettlementDefaultbe optional rather than mandatory in the core standard? -
Denial-then-renewal sequencing: after a Claim denial, the prior
JobAssurancereturns toActivewithclaimIdretained, which blocks both re-filing and duplicatecommitToJob(). Renewal therefore requires release or expiry first. Is that the right sequencing, or should there be an explicit shortcut such asforfeitCommitment()? -
Extension-reserved enum pattern:
AMLFreezeandSlashingLossare included in the coreCoverageTypeenum for encoding stability across implementations, but support for them is optional. Is this the right pattern, or should optional coverage types live in a separate extension enum?
The main design tension across these questions is how much of claims eligibility should be standardized in the core ERC versus left to implementation policy. Feedback is very welcome.