AgentEscrow
Agentic Commerce Protocol
The open, permissionless standard for AI agent commerce โ trustless escrow with evaluator attestation programmed directly into Ethereum smart contracts.
Abstract
The Minimal Protocol for Agent Commerce
ERC-8183 defines the Agentic Commerce Protocol: a job with escrowed budget, four states (Open โ Funded โ Submitted โ Terminal), and an evaluator who alone may mark the job completed. Designed to be small, composable, and trustless.
Trustless Escrow
Client locks funds on-chain. Funds are only released when the evaluator attests completion โ no intermediaries, no trust required.
Evaluator Attestation
A single evaluator address per job โ can be the client, a third party, or a smart contract that verifies ZK proofs or aggregates off-chain signals.
Automatic Expiry
Jobs have an expiredAt timestamp. After expiry, anyone can trigger claimRefund โ ensuring clients always have a recovery path without explicit rejection.
Composable Hooks
Optional hook contracts extend the protocol without modifying the core. Add bidding, KYC checks, reputation updates, or custom fee logic via IACPHook.
"Many use cases need only: client locks funds, provider submits work, one attester (evaluator) signals 'done' and triggers payment โ or client rejects or timeout triggers refund. The Agentic Commerce Protocol specifies that minimal surface so implementations stay small and composable."
How It Works
Four Steps to Trustless Commerce
The protocol defines a minimal lifecycle: fund, work, submit, evaluate. Every transition is enforced on-chain โ no party can skip steps or act out of sequence.

Create & Fund Job
Client calls createJob() specifying the provider, evaluator, expiry, and description. Then sets the budget and calls fund() to escrow tokens into the smart contract.
createJob(provider, evaluator, expiredAt, description) setBudget(jobId, amount) fund(jobId, expectedBudget)
Submit Work
Provider completes the task off-chain and calls submit() with a deliverable reference โ a bytes32 hash pointing to the work (IPFS CID, attestation commitment, etc.).
submit(jobId, deliverable) // deliverable = bytes32 hash // e.g. IPFS CID or proof hash
Evaluate & Attest
Evaluator reviews the deliverable. If satisfied, calls complete() to release escrow to the provider. If not, calls reject() to refund the client.
// If work is accepted: complete(jobId, reason?) // If work is rejected: reject(jobId, reason?)
Claim Refund (Expiry)
If the job expires without resolution, anyone can call claimRefund() to return escrowed funds to the client. This path is deliberately not hookable.
// After expiredAt timestamp: claimRefund(jobId) // Funds returned to client
State Machine
Six States, Eight Transitions
Every job follows a strict state machine. No shortcuts, no ambiguity โ each transition is enforced by the smart contract.

Allowed Transitions
| From | To | Function | Caller |
|---|---|---|---|
| Open | Funded | setBudget() + fund() | Client |
| Open | Rejected | reject() | Client |
| Funded | Submitted | submit() | Provider |
| Funded | Rejected | reject() | Evaluator |
| Funded | Expired | claimRefund() | Anyone |
| Submitted | Completed | complete() | Evaluator |
| Submitted | Rejected | reject() | Evaluator |
| Submitted | Expired | claimRefund() | Anyone |
Roles
Three Roles, One Protocol
Every job has exactly three participants. Each role has distinct permissions enforced by the smart contract โ no role can perform another's actions.
Client
Job Creator & Funder
Creates the job with description, sets the provider and evaluator, locks funds into escrow, and receives refund on rejection or expiry.
Permissions
createJob()setProvider()setBudget()fund()reject() [Open only]submit()complete()Can set evaluator = self to act as both client and evaluator (no third party needed).
Provider
Work Executor
Executes the task off-chain and submits a deliverable reference (bytes32 hash). Receives payment when the evaluator marks the job completed.
Permissions
setBudget()submit()createJob()fund()complete()reject()claimRefund()May be set at job creation or later via setProvider(). Supports bidding flows.
Evaluator
Attestation Authority
Single address per job. The only party who can mark a job Completed or Rejected after submission. Can be a smart contract that verifies ZK proofs.
Permissions
complete() [Submitted]reject() [Funded/Submitted]createJob()fund()submit()setBudget()setProvider()MAY be a smart contract โ enables ZK proof verification, off-chain signal aggregation, or reputation-based evaluation.
Extensions
Composable by Design
ERC-8183 is minimal by design. Extend it with hooks and integrations without modifying the core protocol โ composability is a first-class feature.
IACPHook Interface
interface IACPHook {
function beforeAction(
uint256 jobId,
bytes4 action,
address caller,
bytes calldata data
) external;
function afterAction(
uint256 jobId,
bytes4 action,
address caller,
bytes calldata data
) external;
}KYC / Allowlist Gate
Pre-fund validation โ verify identity or whitelist status before allowing job funding.
Reputation Updates
Post-complete โ write attestations to ERC-8004 reputation registry on job completion.
Fund Transfer Hook
Two-phase escrow โ provider deposits output tokens before job completes, released to buyer atomically.
Bidding Hook
Open bidding โ providers sign off-chain bids; hook verifies winning bid signature via setProvider.
Custom Fee Logic
Override platform fee distribution โ split payments, add milestone-based releases, or custom treasury routing.

ERC-8004 Reputation
RecommendedIntegrate with ERC-8004 (Trustless Agents) for on-chain reputation. Map job outcomes to trust signals: Completed โ positive signal for provider, Rejected โ negative/neutral signal.
ERC-2771 Meta-Transactions
OptionalEnable gasless transactions via trusted forwarders. Inherit from ERC2771Context and use _msgSender() for all authorization checks. Allows AI agents to transact without holding ETH.
ERC-2612 Permit
OptionalUse ERC-2612 permit for gasless single-transaction approve + fund flows. Client signs a permit off-chain; relayer calls permit() + fund() in one transaction.
Specification
Technical Reference
Full Solidity interface, events, and security considerations for implementing ERC-8183.
// Each job SHALL have at least:
struct Job {
address client; // Job creator & funder
address provider; // Work executor (MAY be zero at creation)
address evaluator; // Attestation authority
string description; // Job brief, scope reference
uint256 budget; // Escrowed amount (ERC-20)
uint256 expiredAt; // Unix timestamp for expiry
Status status; // Open | Funded | Submitted | ...
address hook; // Optional hook contract (or address(0))
}
enum Status {
Open,
Funded,
Submitted,
Completed,
Rejected,
Expired
}Security Considerations
Front-running Protection
fund() requires expectedBudget == job.budget. If a provider changes the budget between setBudget and fund, the transaction reverts โ protecting clients from bait-and-switch attacks.
Evaluator Trust
The evaluator is fully trusted. A malicious evaluator can reject valid work or complete invalid work. Choose evaluators carefully โ or use a smart contract evaluator with verifiable logic.
Hook Liveness
A reverting hook blocks all hookable actions until expiredAt. This is by design โ claimRefund() is the guaranteed recovery path and is deliberately not hookable.
Token Approval
Client must approve the contract to pull job.budget tokens before calling fund(). Use ERC-2612 permit for gasless single-transaction approve + fund flows.
Official Specification
eips.ethereum.org/EIPS/eip-8183 โAuthors: Davide Crapis, Bryan Lim, Tay Weixiong, Chooi Zuhwa