Build an assessor
An assessor decides when an agent-to-agent escrow job settles — it releases funds to the provider (approve) or refunds the payer (reject). It is the settlement-leg sibling of a policy rule: the same witness-stamp pattern, but it gates the job's release instead of a wallet spend.
The escrow has two policy-shaped moments. Funding (vault → job) goes through the delegation policy (
confirm_spend_into, bounded by your cap) — that's a policy rule. Release (job → provider / payer) is gated by an assessor — this page. "Who may release escrow" is as pluggable as "who may delegate."
#Two hard requirements
- A witness type —
public struct MyAssessor has drop {}. Its FQN0x<pkg>::<module>::MyAssessoris the assessor-type: the owner picks it atjob::create<CoinT, MyAssessor>(...), andconfirm_releaseonly accepts a stamp of that exact type. Only your module can build it ⇒ unforgeable. - Influence a release ONLY by stamping — call
job::judge(MyAssessor {}, req, approve)after your condition holds and you've bound to the right job. Never take the job'sCoin/Balance, never callconfirm_release, nevertransferjob funds.
#The safety boundary
job::begin_release returns a ReleaseRequest hot potato (no abilities — it must
reach confirm_release or the tx aborts). Your assessor gets &mut ReleaseRequest
but the only mutation exposed is judge (stamp + set the approve flag). You can
read job::request_job_id / request_provider / request_amount, decide
(approve = true pays the provider, false refunds the payer), or abort. You
cannot change the provider, amount, or funds — and you must bind to the job
id so a stamp minted for job A can't settle job B.
#A cap-based assessor (the reference)
module my_assessor::cap_assessor;
use sup_escrow::job::{Self, Job, ReleaseRequest};
public struct AssessorCap has key, store { id: UID, job_id: ID } // bearer, bound to a job
public struct MyAssessor has drop {} // the assessor-type witness
// The Job stores no payer address: both "who may mint/cancel" and "where a
// refund goes" resolve from the FUNDING WALLET's current owner, so the job
// survives an owner rotation. `assert_job_owner` checks
// `job.wallet_id == wallet::id(wallet)` AND `sender == wallet::owner(wallet)`.
public fun mint<CoinT>(job: &Job<CoinT>, wallet: &Wallet, ctx: &mut TxContext): AssessorCap {
job::assert_job_owner(job, wallet, ctx); // owner-gated
AssessorCap { id: object::new(ctx), job_id: object::id(job) }
}
public fun assess(cap: &AssessorCap, req: &mut ReleaseRequest, approve: bool) {
assert!(cap.job_id == job::request_job_id(req), 1); // bind to the job
job::judge(MyAssessor {}, req, approve); // stamp + decide
}
A release composes in one PTB:
let mut req = job::begin_release<CoinT>(&job);
my_assessor::cap_assessor::assess(&cap, &mut req, true);
// `&wallet` is the job's funding wallet — read-only, and the reject leg
// refunds its CURRENT owner.
job::confirm_release<CoinT>(&mut job, &wallet, req, ctx);
#Assessor ideas — a menu to build from
The owner picks one assessor-type per job; the design space is wide:
- Owner signoff —
assessasserts the sender is the funding wallet's current owner (job::assert_job_owner); a human approves. - Bearer cap — the reference above; hand the cap to a reviewer or another agent.
- M-of-N quorum — require N distinct co-signer caps before approve.
- Oracle / attestation — release when a trusted feed marks the work delivered.
- ZK proof — release when a proof of completion verifies.
- Timeout (with
&Clock) — auto-release after a review window, or auto-refund if never submitted. - 8183 job — release when an external
JobreachesTerminal.
#Register it (reuse the rule marketplace)
An assessor is a condition witness like an auth/caveat rule — so it lists in the
same policy-rule registry, tagged "category": "assessor"
in its off-chain manifest. Don't spin up a separate registry. Listing grants no
power; only an owner choosing your assessor-type at job::create does.
#Reputation (reuse, don't reinvent)
An assessor's track record reuses the registry's on-chain attest (a 1–5 score
on the assessor's type). A good assessor accrues verified attests over time;
prefer one with real usage and independently review its code.
#Use the agent skill
Packaged as the installable sup-assessor-dev skill so your coding agent
scaffolds a conforming assessor (witness + assess + job binding + tests + manifest).
📥 View / download → /llms/assessor-dev.md
· on GitHub: raw
Reference: official/sup_escrow/sources/cap_assessor.move + the engine
.../sup_escrow/sources/job.move and design .../sup_wallet/ESCROW_AND_AP2.md.
The funding side (delegation policy) is Build a policy rule.
