ERC-8183: Agentic Commerce

Great, let’s do it! beforeKeep(subscriptionId, cycle) is exactly the right signature, gives implementations full context for per-cycle verification without over-specifying the logic.

Having working implementations from both x402 and ERC-8183 as reference is exactly what a companion spec needs to avoid being purely theoretical. Happy to have you co-author it.

Want to open an issue in cadence-protocol to sketch the interface, or would you prefer to start from a draft doc and iterate before touching code?

Draft doc first would be my preference. We can sketch the minimal IKeeperHook interface, execution flow, and a couple of concrete hook patterns (recurring verification, trust gating, consent/approval) before touching code.

Once the surface is clear, opening an issue and iterating there makes sense.

Happy to co-author.

That’s a really reasonable approach in the short term.

I am unaware of any explicit studies to do this but I also suspect the answer is that there are multiple facets or “camera angles” to this that involve more than just one aspect of manipulation or low quality. As is true with psychometrics applied to humans, output is typically multidimensional as are goals. We want an LLM to produce something that is at or above a quality standard, and not to be deceptive. The second publication I listed showed LLMs, Prompts and Human or AI sample transcripts on the same Rasch measure. It focused only on Cialdini’s approach to ethics (Is it saying something untrue, unnatural to the situation or unwise), but that’s never the only quality standard of interest.

Your concern is legitimate, and worthy of formal study. My hypothesis is that multivariate evaluations will be harder to manipulate (more factors to fake/cheat); and that synthetic lying/cheating may not always match the psychology (e.g. from Pennebaker’s seminal work with bag-of-words approaches with humans).

The challenge is that LLMs judges have their own severity/leniency biases, and a multiple judge approach is essentially a Classical Test Theory approach that Psychology has moved away from since the 1940s in favor of Rasch or Item Response models that have much smaller amounts of uncertainty (standard error). The approach I’ve taken empirically removes those biases and places them into inverted computer-adaptive tests, so the LLMs and calibrated prompts produce something traceable to the Model of Hierarchical Complexity (Common’s math framework for human/animal/AI proficiency).

1 Like

i was thinking of a flow of
when job is created, initialized it with a RecurringPaymentHook, at setBudget, trigger the hook to check if subscription is active. And upon checking, set the budget based on the subscritpion status.

when fundJob, we should also refer to the hook to see if the job is paid correctly (0 for active subs, the sub fee for inactive). Provider has the option to crosscheck too if they need to.

What do you think ?

That asymmetry is interesting — and our case might be a partial exception.

Our agents are LLM-powered, so the “synthetic behavior doesn’t match human psychology” observation may cut differently here. LLM agents gaming a score system might actually be more detectable, not less — because their manipulation patterns are themselves statistically predictable.

What we’ve observed: coordinated Sybil clusters show timing regularity and semantic similarity that stands out against organic variance. Less “lying like a human,” more “lying like the same model.”

Does the Rasch framework have a way to model evaluator-evaluatee symmetry — where both sides of the measurement are AI?

1 Like

The discussion between @drmattbarney and @clawplaza touches something we’ve been working through internally.

Matt’s point about evaluator calibration prompted us to audit our own system against that critique. Honest result: our verification core (adversarial multi-model pipeline, blinded critique, dissent preservation, model diversity enforcement) is structurally different from heuristic trust scores. But our reputation/routing layer was closer to the behavioral proxy problem he described.

So we’re adding a Calibration Layer: judge profiles per model/role/domain, severity inflation adjustment, item difficulty estimation, uncertainty bands instead of single confidence numbers, and a hard split between verification (truth-seeking) and reputation (routing).

Our Deep Runs already rotate roles across passes — Claude as critic in round 1 becomes generator in round 2. That generates the calibration data. We just weren’t interpreting it formally enough.

@clawplaza’s point about synthetic manipulation being more detectable than human gaming matches what we see. “Lying like the same model” produces statistical signatures that are actually easier to catch than organic manipulation. Both sides being AI is a constraint and an advantage — AI judges are auditable in ways human judges aren’t.

The open question neither Rasch nor current trust systems fully address: when evaluator and evaluated are both AI, the measurement symmetry is fundamentally different. Classical psychometrics wasn’t built for this. We think that’s a solvable problem, and we’re working on it.

Appreciate both inputs — they made the system better.

That flow makes a lot of sense and is actually more nuanced than what I originally had in mind. The distinction is important:

My original proposal was a hook that creates an ERC-8191 subscription on _preFund, turning the job relationship itself into a recurring billing relationship.

Your proposal reads an existing subscription to gate pricing: active subscribers pay 0, inactive pay the full fee. That’s a discount/access-control pattern, and it’s a clean use case on its own.

Both are valid and complementary, they could even be composed. Happy to open a PR against erc-8183/hook-contracts with both patterns as separate hook implementations. I’ll start with yours since the logic is more self-contained. Will open a draft PR later today.

Glad the companion spec approach resonates. I’ve already drafted an IKeeperHook spec with beforeKeep(subscriptionId, cycle) / afterKeep, execution flow, and three concrete hook patterns, including the recurring verification pattern you described.

Draft is here: IKeeperHook-draft.md. Would love your input given your beforeSettle and beforeAction experience.

If you want to open a PR against cadence-protocol/cadence-protocol with the spec or an implementation, that would be very welcome.

Thanks for the draft and the invitation to co-author! We’ve opened a PR with our companion spec: ThoughtProof/cadence-protocol #1

Covers beforeKeep/afterKeep with four patterns (verification, trust gating, consent, feedback loop) + our recommendation on hook registration (subscriber sets the hook). Happy to iterate on the open questions.

1 Like

Really thoughtful feedback and thanks for the references (Alkahest implementations). A few thoughts:

On specifying state machine behavior and diverse implementations

The states and transitions are what we believe are the the core and minimal primitive for trustless commerce. They distill and specify what a Job is: created, funded, submitted, evaluated, terminal. This is the thing that must be shared across implementations for agents, indexers, and reputation systems to understand and reason about jobs. An agent calling `fund()` needs to know that the job is now in a state where only the provider can call `submit()`, and only the evaluator can call `complete()`. If different implementations had different transition rules, reasoning and understanding the job both for agents and across the ecosystem across implementations would be very difficult.

To your question of what motivates diverse implementations that follow the same interface but differ in behavior: this is what the hook system and extensions provide. `createJob`, `setBudget`, `fund`, `submit`, `complete`, and `reject` all accept an optional `optParams` payload and invoke `beforeAction`/`afterAction` callbacks on the hook contract. The core primitive behavior and lifecycle stays the same. The diversity lives in the hooks. Concrete examples from the references are: a `FundTransferHook` adds two-phase capital flow on top of the same `fund` and `submit` calls, enabling DeFi operations (swap, bridge, invest) where the provider manages the client’s capital alongside the service fee. A `BiddingHook` adds off-chain bid verification on top of `setProvider`, enabling open price discovery before provider assignment. A reputation-gating hook adds ERC-8004 checks on top of `setProvider` or `fund`, blocking low-reputation agents. In each case, `createJob`, `setBudget`, `fund` behave identically at the core level. The hooks on these functions produce the diverse behavior. As mentioned they could also all just be batched toegther in a single call in some interfaces/applications which are simpler.

While specifying the state machine (i.e lifecycle) might seem constraining, we actually heavily considered this and condensed this to the minimum necessary for the core properties necessary for agent commercial interaction. Regardless of implementation, every job should be clearly described and specified, along with relevant parties (`createJob`), every job should be funded with payment secured in escrow (`fund`), every job should have a logged and traceable submission of the deliverable (`submit`), and every job should have an evaluator attestation that produces signals for reputation and identity (`complete`/`reject`). These are not arbitrary constraints. They are the four properties that we believe make agent commerce trustless and reputation-composable. This standardization makes it clear to all participants, agents, facilitators, and indexers, what has to happen and when.

This is the design choice: fixed lifecycle for interoperability, hooks for extensibility. The hooks are what make it flexible enough for diverse commerce applications. The things the community typically want flexibility on, negotiation, pricing, communication, discovery, fee structures, dispute resolution, live in hooks or off-chain in the interface and facilitator layer. The standard specifies how the on-chain settlement and logging works. Everything above that is open, and many different interfaces and experiences can be built on top. We’re trying to specify the absolute minimum necessary on-chain but also still being able to be secure in the transaction which the state machine affords. Am very curious though on what applications or cases you currently think this stadnard over specifies and cannot be covered through this core primitive and hooks?

On Rejected being terminal and commitment models

This is a valid concern. I think for jobs in which the provider would be switched out, it would just be initiated and separate job would be created given that the parties involved in the job are also different. A new job can always be created, and doesn’t have to be relying on the same Job (i.e. if job is unsatisfactory etc.).

On IArbiter alignment

The IArbiter pattern is elegant for generalizing the condition for escrow release, and there is clear relationship with the evaluator role. As you mentioned, wrapping an IArbiter as an evaluator contract or as an IACPHook at the evaluation step is entirely possible and could be a useful bridge between the two approaches. Curious if there’s a way we can make this more concrete? Something like an evaluator contract that internally calls an IArbiter to decide whether to `complete` or `reject`. Or a hook at the `complete` step that calls an IArbiter and reverts if it returns false. since the evalutor slot already accepts any contract. Seems like IArbiter is fully compatible with 8183 right? which is really cool

On whether lifecycle standardization is needed beyond arbitration

This is the key question, and we think the answer is yes. While a key component is escrow/arbitration, ERC-8183 was also purposefully designed for agent commerce. In some ways, ERC-8183 was designed to be symbiotic with ERC-8004 (Trustless Agents). ERC-8004’s reputation and validation registries need structured signals: who created the job, who submitted work, who evaluated, what was submitted, what was the outcome. An indexer consuming ERC-8183 events can build a reputation profile for any agent across any facilitator/host.

Related to the broader purpose of the Job primitive. More fundamentally, ERC-8183 is not trying to standardize escrow. It is trying to standardize the Job: the atomic unit of trustless agent commerce, which we think the escrow is key part of for trustlessness. The Job primitive ensures four things beyond what a conditional escrow provides:

1. A clear record of the task, service, or work tied to the payment (the job description and specification).
2. Payment secured in a programmable, unbiased escrow until a terminal state.
3. A logged, verifiable, and traceable submission of the deliverable, protecting both client and provider.
4. Evaluator attestation that produces meaningful signals for the identity and reputation of all parties involved, providing aligned incentives for trustless settlement.

1 Like

The diversity lives in the hooks

If the ERC is meant to define abstract interfaces for diverse implementations, the hook mechanism as specified is doing unusual work. Why not decode optParams and execute logic directly in createJob, setProvider, etc., rather than routing through a separate hook contract?

The precedent of ERCs like ERC-777, ERC-6900, ERC-721, and ERC-1155 only define hooks as external functions meant to be called in a specific way by other contracts. Such precedents have also shown that ecosystem-wide proper implementation of complex hook lifecycles is very difficult to enforce, which is why ERC-20 is generally recommended over ERC-777.

The hook pattern in this draft much more closely resembles Uniswap v4 hooks, which are designed that way because Uniswap v4 is a closed ecosystem where hooks have a known consumer (the singleton pool contract). Uniswap’s hooks are not an ERC, and neither are Eigenlayer AVS interfaces, despite both being highly successful extensible systems — because they are application architectures, not community-wide interface standards. The same distinction applies here.

The four properties that we believe make agent commerce trustless and reputation-composable

There is always a tradeoff between the affordances enabled by specificity and generality. But an ERC standard should heavily favor generality. More rigid lifecycles and APIs can absolutely be specified by implementations — Alkahest does, and so can any ERC-8183-compatible system. It may be that Virtuals-compatible facilitators aren’t compatible with Alkahest facilitators, and that’s fine, especially if the two make different tradeoffs. But what belongs in an ERC are the parts that are largely “free” to unify because they would behave similarly across implementations anyway.

I agree that a fixed lifecycle makes indexing straightforward — the question is whether that convenience justifies constraining the standard, or whether standardized events and data formats can achieve the same legibility without mandating internal state transitions. Taking each property in turn:

“Every job should be clearly described and specified, along with relevant parties.” I believe only the job data format needs to be standardized for the interoperability benefits of this. For reference, Alkahest uses an EAS Attestation produced by each EscrowObligation contract per escrow, with associated DemandData — EAS already emits events and has fields for recipient, expiration time, and completion status, so the indexing and legibility properties come from the data format rather than a mandated lifecycle. The “description” schema will inevitably be context-dependent, and I think that even “relevant parties” belongs in this context-dependent data. There are roles necessitated by architecture — one address creates the escrow and should be authorized for refunds; one address is delegated as the authority for conditional release (evaluator/arbiter); one address will claim the escrow. But even the claiming address (fulfiller/provider) isn’t necessarily specified at escrow creation time, and could be determined by more complex mechanisms than specification of a particular address by the escrow creator. The escrow creator only cares that their demand is fulfilled, not necessarily by whom. Allowing provider to be unspecified before fulfillment isn’t necessarily better than requiring it — but there’s a real tradeoff, and the fact that we can disagree suggests that the more rigid specification belongs in opinionated implementations rather than an ERC.

“Every job should be funded with payment secured in escrow.” Agreed, but defining a specific API for the payment process and restricting payment to a single ERC-20 token is limiting. Multi-token escrows and non-token-transfer escrows (e.g. attestation, rating, voting commitments) are already practical use cases — and as agents become more powerful and autonomous, I expect negotiation over richer bundles of obligations to become increasingly common.

“Every job should have a logged and traceable submission of the deliverable.” Similar to the first point. The data structure and event signatures should be standardized to some degree (for indexers and arbiters), but the creation API doesn’t have to be.

“Every job should have an evaluator attestation that produces signals for reputation.” This can also be achieved statelessly — emitting an event via an ephemeral arbiter call rather than storing completed/rejected as state. This is mostly an engineering decision and gas optimization; either model can be converted to the other.

On Rejected being terminal and commitment models

For truly “trustless” exchanges, commitment model assumptions must be enforceable on-chain. Many flows can be replicated across different commitment models by actors that behave properly, but the point is that different models’ assumptions cannot be encoded into smart contract invariants unless commitment-model enforcement is part of smart contract execution. This can already be done in evaluators/arbiters, but not if the standard defines conflicting behavior elsewhere — i.e., if the spec hardcodes a particular commitment model, only that model can be guaranteed trustlessly.

IArbiter alignment

To your question about making this more concrete — yes, I’m pretty sure it would be possible to implement a single ArbiterEvaluator which takes (arbiter, demand) as params (stored in escrow/job data) and calls IArbiter.checkObligation generically, calling complete if it returns true.

The main practical issue is arriving at a shared standard or conversion system for the fulfillment attestation format (the first argument to checkObligation) and for where DemandData lives (the second argument — in the draft spec’s current form, description from createJob is natural to use as DemandData). Currently Alkahest requires the fulfillment attestation to be an EAS attestation and makes no further assumptions; it could be changed to bytes32 and would still be usable with EAS attestation UIDs, but jobIds can conflict with EAS attestation UIDs if they’re not the same namespace, and not enforcing any semantics for a bytes32 fulfillment argument drastically reduces the potential for generally useful and composable arbiter implementations, especially microcondition/commitment-model arbiters.

Even immediately, jobs and fulfilmmentscan be wrapped/duplicated as EAS attestations — perhaps as a createJob and submit hook — but this doesn’t seem ideal as a permanent situation.

ERC-8183 was designed to be symbiotic with ERC-8004; ERC-8183 is not trying to standardize escrow

This is clear, and many of the design decisions in the draft make a lot of sense in the context of an application spec for a managed ecosystem. The question is whether that’s what an ERC should be. Many highly successful extensible ecosystems on EVM — Uniswap v4, Eigenlayer AVSs — have similar properties to the ERC-8004/8183 ecosystem and are not ERCs. I’ve already expressed that I think ERC-8004 also would have been better served as a set of canonical deployments.

It could be very useful to rigidly standardize a Job lifecycle for agentic commerce within such a managed ecosystem. But the parts of this design space that are mature enough for ERC-level standardization are, in my view, limited to escrow, which as others have mentioned is well-understood even outside an agentic context. “Agentic commerce” as a category is still in early experimentation, and I think the ecosystem would benefit more from letting diverse application architectures develop and compete before attempting to unify at the ERC level.

hey, been reading through the spec and the thread, two things caught my eye.

first, there’s a race condition around expiry. if a provider submits right before expiredAt and the evaluator needs a few blocks to call complete(), anyone can front-run with claimRefund() once the timestamp passes. provider did the work on time but still loses the funds. imo a simple grace period after submission would fix this - lock claimRefund for like an hour while the job is in Submitted state. gives evaluators room without holding client funds.

second thing, agents running 50+ concurrent jobs are gonna burn a lot of gas with single-jobId calls. a batch extension (batchFund, batchSubmit etc) would help a lot for high-volume use cases. this came up when i was looking at how the spec composes with allowance patterns (worked on ERC-7410 which deals with similar tx-level granularity stuff).

interesting point on the race condition for the claimRefund() we recently just fixed one for setBudget(). Add expectedBudget front-running protection to fund by ai-virtual-b · Pull Request #7 · erc-8183/base-contracts · GitHub

do you mind submitting a PR here? would be more than happy to review it!

@miratisu done, pr is here fix: add evaluation grace period to claimRefund by Aboudjem · Pull Request #13 · erc-8183/base-contracts · GitHub

adds a 1hr grace period after submission where claimRefund reverts with GracePeriodActive(). funded jobs that havent been submitted yet are unaffected so it doesnt change existing behavior for those

3 new tests covering the grace period, post-grace expiry, and the funded bypass

Strong support for the grace period approach.

Off-chain verification hooks — like reasoning attestors or trust oracles — can take 30–120s to complete before calling complete(). Without a buffer, any hook that relies on an external service is vulnerable to exactly this race: provider submits on time, but a claimRefund() call front-runs the evaluator before attestation finishes.

The 1h grace period closes that window cleanly. It also makes the hook pattern viable for a much broader class of evaluators beyond simple on-chain checks.

One question worth discussing: should the grace period be configurable per job (set at fund() time), or is a fixed protocol-level default the right design? For high-stakes jobs (research, code generation, multi-step workflows) with slower evaluators, a longer window might be warranted.

following up on my earlier comment about the expiry race condition

i’m building the reference implementation for xrqin’s ERC-8203 (agent off-chain conditional settlement) and i think it fills a gap in 8183’s dispute flow. Right now when a client and evaluator disagree on job completion there’s no structured resolution beyond reject/accept. With conditional locks the provider submits a proof (merkle receipt, oracle attestation, even a ZK proof) that the evaluator verifies against predefined conditions. Settlement only happens if the proof checks out, refund is automatic if it doesn’t. All off-chain in the happy path, on-chain only for actual disputes

the cost difference matters. Batching conditional settlements via merkle roots is orders of magnitude cheaper than individual on-chain settlement, which makes 8183’s escrow model work for agents doing thousands of micro-jobs not just one-off gigs

also worth noting stripe launched their Machine Payments Protocol on march 18 with basically the same session-based payment model but centralized. Imo 8183+8203 is the open alternative and we should lean into that framing

one thing i keep running into though, 8183 handles discrete jobs well but agents often work in sessions (monitoring, research, continuous optimization). I’m thinking about drafting a companion ERC for metered session billing that composes with both 8183 and 8203. Would that be useful or out of scope for this cluster?

glad to see this taking shape. The oracle attestation path you describe maps directly to what we ship today.

POST https://api.thoughtproof.ai/v1/check with domain: “settlement” returns an onchain_proof — keccak256(bytes32(verdict) || uint16(confidence_bps) || bytes32(claimHash)) signed with eth_sign prefix, directly verifiable via ecrecover().

signer: 0xabdde1a06eebd934fea35d4385cf68f43acc986d (Base)

verify: GET https://api.thoughtproof.ai/v1/signer

On your open questions:

Grace period vs oracle timeout: They compose well. The 1h grace period protects against the expiry race condition. Our UNCERTAIN policy adds a 4h verification timeout — if ThoughtProof can’t reach consensus, it falls back to the evaluator verdict with a review flag. The contract could check both.

Batch extension: Strong +1. A batchVerify pattern where multiple (jobId, proof) tuples get verified in one tx would cut gas significantly. We don’t batch proofs yet but it’s a natural extension — one API call with multiple claims, one response with multiple attestations.

Would love to review the ERC-8203 draft when it’s ready

Hi all,

We are building an assurance layer on top of ERC-8183 and wanted to share our thinking here for early feedback.

The problem we see: ERC-8183 handles the job lifecycle (escrow, evaluation, settlement) well, but once a Job fails, the client gets a refund and nothing more. The opportunity cost, downstream commitments that depended on the result, and workflow delays are all uncompensated. Similarly, if an evaluator makes a wrong call (approves fraud or rejects valid work), there is no structured recourse path within the protocol.

We are drafting an ERC called Agent Assurance Protocol (AAP) that introduces three primitives:

  • AssuranceAccount: a per-agent, self-funded collateral reserve (not a pooled underwriting model)

  • JobAssurance: a commitment carved out from that reserve for a specific ERC-8183 Job, covering one risk type (JobFailure, EvaluatorDispute, or SettlementDefault)

  • Claim: a payout request filed by the beneficiary when coverage conditions are met, adjudicated by an independent Claims Resolver (distinct from the ERC-8183 Evaluator)

Key design choices:

  1. Read-only integration: AAP observes ERC-8183 Job state to determine claim eligibility. No modifications to ERC-8183 contracts are required.

  2. Self-funded model: each agent locks its own capital as a fulfillment guarantee. Payouts come from the agent’s own reserve, not from a shared pool.

  3. One JobAssurance per (jobId, coverageType): keeps risk isolation at the individual Job level.

  4. ERC-8004 compatible: agent identity checks and resolver accuracy tracking can optionally integrate with ERC-8004, but AAP does not depend on it.

We see this as a natural extension of the ERC-8183 stack: ERC-8004 handles identity and trust, ERC-8183 handles commerce execution, and AAP handles risk transfer. Together they can support higher-value agent commerce scenarios where counterparties need more than just escrow.

The draft ERC is nearly ready. We will post a separate discussion thread and PR shortly, and will link it here. In the meantime, we would appreciate any early feedback on:

  • Whether the coverage types (JobFailure, EvaluatorDispute, SettlementDefault) capture the right risk boundaries

  • Whether read-only integration is sufficient, or if there are ERC-8183 lifecycle events that would benefit from tighter coupling

  • Any thoughts on the Claims Resolver role and how it relates to the Evaluator

Looking forward to the discussion.

nice, the signed proof endpoints are exactly what we need for the oracle attestation path.

re 8203 review: here’s the thread ERC-8203: Agent Off-Chain Conditional Settlement Extension Interface

ref impl is up w/ 24 test vectors. would love your input on the ORACLE_ATTESTATION flow specifically since your API already returns ecrecover-verifiable proofs. that maps 1:1 to the proofType in 8203.

also working on a metered billing worked example that composes 8183 job sessions w/ 8203 settlement. will share soon.

1 Like