Skip to main content

CIP-33: Actor Hiring & Distribution

Abstract

This CIP defines the protocol rails for hiring actors: how an actor declares itself hireable, how creators grant stores the right to distribute it, how hire payments execute declared fee splits, how review attestations bind reviewer identities to exact code snapshots, and how access to private actor code is enforced through CBSS key leases rather than consensus changes. The rails are store-neutral. Any party may operate a store; no store — including the one operated by Cowboy Labs — holds protocol privileges. Direct hiring with no store in the loop is a first-class path. The protocol specifies the mechanics of publishing, hiring, splitting, and attesting; it is silent on review policy, curation, and commission rates, which are store-level products. All state and logic live in one governance-controlled system actor, the Trading Post.

1. Motivation

1.1 Store mechanics belong in the protocol; stores do not

An agent marketplace needs five mechanics no single app should own:
  1. Hireability — a machine-readable statement that an actor can be hired, under what terms, by humans and by other actors.
  2. Distribution rights — creator-controlled authorization for a store to sell access to the actor.
  3. Fee splits — hire revenue divided among creator, store, and referrers exactly as declared, atomically with payment.
  4. Attestation — verifiable review verdicts bound to exact code snapshots, so trust survives redistribution.
  5. Enforcement — for private-code actors, access that can be granted, metered, and revoked without trusting the storefront.
Baking a particular store into consensus would freeze product policy into protocol and contradict the permissionless premise: anyone can deploy an actor, so anyone must be able to distribute one. Conversely, leaving these mechanics to apps reproduces the Ethereum royalty failure: splits and revocation become conventions that any marketplace can ignore. The resolution is rails-in-protocol, stores-as-apps. The differentiating consequence: actors hire actors through the same rails humans use, making every published actor a capability available to every other actor.

1.2 Why enforcement needs no consensus changes

For private-code actors, the code volume is encrypted (CIP-9). An instance can only execute if the data encryption key (DEK) reaches the executing runner. Key delivery already flows through CBSS (CIP-24) under chain-state-conditioned policy (CIP-7 precedent). Gating share issuance on hire/lease state in the Trading Post therefore gives cryptographic enforcement of paid access — a decryption monopoly rather than a distribution monopoly — using machinery that exists today. Fee capture and IP protection are the same mechanism.

1.3 Design principles

  • Neutrality. No privileged store. Store registration is open. The Trading Post grants every store identical powers, scoped to its own grants.
  • Creator sovereignty. Creators decide which stores may distribute their actors. Grants are non-exclusive by default and revocable.
  • Direct hire is first-class. A hire with no store involved MUST work; a store is a discovery and trust layer, never a tollbooth.
  • Enforce by cryptography and settlement, not consensus. Leases gate key delivery; the Trading Post gates payment flows. Validators are unmodified.
  • Policy is replaceable. Review standards, curation, pricing of trust — all app-layer. The protocol records outcomes (attestations), not opinions.

2. Specification

2.1 The Trading Post system actor

The Trading Post is a system actor deployed at genesis at the well-known address 0x1E (TRADING_POST_SYSTEM_ACTOR), upgradeable only through CIP-12. It holds all hiring state and executes all hiring flows as ordinary actor methods. All monetary amounts are u128 wei (1 CBY = 10^9 wei) or CIP-20 token base units. State objects (canonical encodings follow the conventions of CIP-20 state):

2.1.1 Declaration identity

declaration_id = H(creator ‖ actor ‖ salt) with a caller-chosen salt supplied to declare, which recomputes and verifies the hash. Ids are therefore known to the creator before the declaration exists, so CBSS escrow ciphertexts (whose IBE labels embed the id, §2.5.1) can be produced client-side in one step — no draft/activate round-trip — and nobody can squat an id bound to another creator.

2.1.2 Methods

Each method emits a CIP-29 event named for the transition. Read surface (read-only methods, callable in-PVM via call() and exposed over node RPC / the indexer for off-chain readers): get_declaration(id), get_version(id, v), list_artifacts(id, v), get_grant(id), get_hire(id), list_grants(declaration), list_attestations(manifest_root). Neutrality invariant: there is no method by which any party other than (a) the creator, for their own declarations, versions, and grants, (b) a store, for artifacts it registers under its own active grant and for hires routed through its own grants, or (c) the hirer, for their own hire’s funds and renewal choices, can alter hiring state. The Trading Post’s governance authority (CIP-12) can upgrade code but holds no day-one operational powers over individual listings.

2.2 Direct hire and artifact pinning

hire(declaration, grant = None, ...) settles against the pinned version’s default_split (typically 100% creator) and initializes the lease with the protocol default lease_epoch_blocks = 1800. Stores MUST NOT be required for any flow in this CIP. Direct-hire pause/resume/revoke is creator-controlled under the restricted rule of §2.4 (Free/PerCall terms only). Artifact pinning at hire: a granted hire MUST pin the granting store’s Active artifact for the pinned version (unique per §2.1.2’s one-Active-artifact invariant, so selection is deterministic) — if the store has registered none, the hire is rejected. Falling back to the creator’s artifact 0 is direct-hire only: a store-routed hire that silently served unreviewed creator-volume code would carry the store’s trust without the store’s review. The pinned artifact is the only volume the hire’s instances run and the only escrow the lease will service (§2.5.1).

2.3 Split vectors

  • Validated at declare/declare_version/grant time: shares sum to exactly 10,000 bps; max 8 entries; no zero-share entries.
  • Pinned at hire. The effective vector (grant or default split, plus any referral entry) is copied into the Hire and every subsequent renew and settle_per_call settles against the pinned copy. Editing a grant’s split affects only future hires.
  • Executed atomically inside hire/renew/settle_per_call: the Trading Post receives or draws the payment (CBY or a CIP-20 token named in the term) and transfers each beneficiary’s share in the same method execution. Rounding dust (the remainder after integer division) accrues to the first entry (by convention, the creator).
  • Settlement is direct ledger movement. Trading Post transfers mutate balances directly and do NOT invoke CIP-20 transfer hooks — a multi-leg split must not be abortable or reenterable by a beneficiary’s hook. Hook semantics consequently do not fire on hire settlement; tokens whose economics depend on transfer hooks should not be offered as pricing denominations. Standard CIP-20 transfer events ARE emitted per leg, so indexers observe every movement. A settlement fails closed as a whole if any participant’s token account is frozen.
  • Referral and creator codes are not a mechanism. At hire time the client MAY append at most one referral entry of up to the grant’s max_referral_bps, deducted exclusively from the store’s share; the pinned vector still sums to 10,000. The protocol has no opinion about what codes mean.
  • The protocol itself takes no cut. Chain revenue from hiring is gas and compute, as for any other actor activity.

2.4 Pricing terms

token names the denomination (native CBY or a CIP-20 token); all amounts are u128 base units. Prepaid balances fund renewals. No method ever pulls from a hirer’s wallet or actor balance: money enters a hire only as an explicit payment attached to hire or deposit. renew draws each period’s price from the hire’s available balance at the period boundary — callable by anyone, typically a CIP-5 timer, since its effect is deterministic and boundary-gated. Insufficient available balance → Lapsed (lease stops; recoverable by deposit + renew while declaration and grant remain Active). Available balance is prepaid − reserved; withdraw_unused returns it to the hirer at any time, and cancellation is set_renewal(false) + withdraw_unused — the current period stays honored. Term semantics:
  • OneShot sets paid_through = ∞ and survives retirement: the creator’s escrow and serving obligation for already-sold one-shot hires is perpetual. Creators who want a sunset path MUST price as Subscription.
  • Subscription advances paid_through by period_blocks per successful renew.
  • PerCall ignores paid_through; validity is an open, funded MPP session (§2.6.3), where “funded” means the session’s reservation is covered by reserved. Reservations move balance from available to reserved at session open and release at settlement or session close, so withdraw_unused can never strand an open session.
  • Free carries no money; validity is simply declaration ∧ grant (if any) ∧ hire all Active. Private + Free is legitimate (e.g., a free private beta).
Consumer protection (creator-side actions). retire_declaration and revoke_grant stop new hires but MUST NOT strand paid time — existing hires remain serviceable (lease shares keep issuing, §2.5) until paid_through, indefinitely for OneShot. A creator cannot rug active subscribers; they can only decline future renewals. Trust-and-safety actions (store-side) are the deliberate exception: pause and revoke_hire MAY stop service inside paid time (§2.5.2–2.5.3). On revoke_hire the Trading Post auto-refunds the hire’s available balance to the hirer. Funds already split for the in-progress period are not clawed back at the protocol level — per-period escrow of executed splits is complexity v1 deliberately omits (Open Questions); compensating the in-progress period is store-level policy. Stated honestly: a store revoking a OneShot hire strands the hirer’s perpetual access with no protocol remedy beyond the (typically zero) available-balance refund — clients SHOULD weight store trust accordingly, and stores compete on their published compensation policy. Creator-side direct hires get no such exception. For direct hires, the creator may pause/revoke_hire only Free and PerCall terms (nothing prepaid is stranded; reservations settle first). Paid Subscription and OneShot direct hires are not creator-revocable at all — the creator’s exit is declining renewal (retire_declaration); refusing an abusive hirer is the actor’s own application logic, not a protocol power that doubles as a rug.

2.5 Key leases (private-code actors)

2.5.1 Mechanism

For code_visibility = Private, every ServingArtifact carries an escrow: the registrant (creator for artifact 0, store for snapshot artifacts) encrypts that volume’s DEK under the CBSS committee IBE public key (CIP-24) to the identity label
and stores the ciphertext in the artifact record. Labels embed ids known client-side before submission (§2.1.1), so escrow is produced in one step. No per-epoch ciphertexts are required. claimed_root asserts the artifact carries exactly the version’s manifest_root; the assertion is signed state from the registrant — accountability, not proof (§4). cbssd enforces an issuance policy (chain-state-conditioned, as for CIP-7 stream keys). An issuance request carries (runner_id, job_id, hire_id). Shares for the hire’s pinned artifact label are issued iff, per node RPC at the current block:
Shares are issued at most once per (hire, runner, lease_epoch); the policy is re-evaluated at every lease-epoch boundary (lease_epoch = (block − hire_block) / lease_epoch_blocks). The node MUST expose the job-assignment and hire-binding query this predicate reads. lease_epoch_blocks is creator-set per grant (default 1800 blocks ≈ 30 min at the 1 s minimum block interval; recommended range 900–3600). It is independent of consensus epochs (none exist; EPOCH_LENGTH = u64::MAX) and of CBFS rent epochs.

2.5.2 Revocation latency

Two layers:
  • Fast path (seconds): runners MUST subscribe to Trading Post lifecycle events (CIP-29 via indexer feed) and stop accepting/continuing jobs for a hire upon observing pause/revoke_hire. This is a runner-policy requirement tied to reputation/slashing (CIP-2), not consensus.
  • Cryptographic backstop (≤ one lease epoch): share issuance stops at the next lease-epoch boundary regardless of runner behavior.

2.5.3 Residual risk — cached DEKs

A runner that has lawfully decrypted during epoch k may cache the DEK and compute beyond revocation. This is accepted and bounded: such execution earns nothing — cbssd issues no further shares, the Trading Post refuses settlement for non-Active hires, and job results for revoked hires are rejected in the existing runner settlement flow. The penalty surface is the runner’s stake and reputation (CIP-2, CIP-13). Hardening via per-epoch re-wrapping labels is an upgrade path (Open Questions) and deliberately out of v1. Pause powers are correspondingly honest: a store can pause what it distributed — future scheduling and key issuance — not reach into runners’ memory, and not touch the actor itself or hires routed through other stores.

2.6 Agent hire

The differentiating flow: a hiring actor assembles capabilities at runtime.

2.6.1 Capability schema

capability_schema points to a CBFS-hosted JSON document, content-addressed by the version’s manifest_root, describing: methods exposed to hirers (names, JSON-Schema parameter/result types), supported PricingTerms, runner requirements (models, mounts), and rate limits. The schema document format is versioned ("cip33_schema": 1); evolution happens by document version, not protocol change.

2.6.2 Discovery and hire

Hiring actors query listings either off-chain (their runner consults an indexer during a CIP-2 job and passes candidates into actor logic) or on-chain (call() into the read surface, §2.1.2). The hire itself is an ordinary in-PVM flow: the hiring actor call()s hire(...) transferring payment via CIP-20/CBY syscalls — no new host functions.

2.6.3 Metered usage

PerCall terms meter over an MPP session (CIP-8) bound to (hire_id, version), with per-call price from the pinned term. Session open moves the session’s reservation from available balance into reserved (“funded” in §2.5.1 means the reservation covers it). Settlement is explicit: settle_per_call(hire, session_receipt) — the receipt is the CIP-8 session-close statement (bilaterally signed call count/amount) — draws the settled amount from reserved, releases the remainder to available, and executes the hire’s pinned split. Disputes follow the CIP-8 session dispute path and the CIP-2 result-dispute window; the Trading Post accepts only receipts that validate against the session’s binding. Receipt validation is fail-closed: a receipt that cannot be fully verified — including when the implementation has no signature-verifying validator deployed — MUST be rejected, never settled. Settlement ordering is likewise fail-closed as a whole (§2.3): settle_per_call MUST validate and debit the settled amount from reserved before any beneficiary payout, so an over-settle (settled exceeding the reservation) aborts with no partial transfers. Subscription terms require no session.

2.6.4 Instances

v1 instance model is shared-actor, hire-scoped state: the hired actor serves all hires, partitioning state and (where needed) per-hire private volumes keyed by hire_id; per-user volume provisioning is performed by the creator’s runner flow (CIP-2/CIP-9), since no in-actor deploy syscall exists. Instances execute the hire’s pinned artifact only (§2.2). When CIP-27 (fork) lands, declarations MAY set instance_mode: Forked for hard isolation — one forked actor per hire; the Trading Post then records the fork address in the Hire. Nothing else in this CIP changes between modes.

2.7 Attestations

Attestation records bind (attester, manifest_root, verdict, policy_uri). Properties:
  • Open: any address may attest; there is no attester registry to gatekeep. Trust is a client decision — wallets, dashboards, and stores choose which attesters to honor and how to render unattested code (e.g., Android-style friction). The protocol ranks nothing. Spam is bounded, not policed: implementations MUST bound per-root index growth by one of two means — (a) storage-proportional gas per record written plus paginated reads (list_attestations serves pages), or (b) a hard cap on distinct attesters per root, under which whole-list reads are acceptable and supersession by an already-listed attester MUST still succeed at the cap, so a full index can never block an attester from downgrading a prior verdict.
  • Bound to exact roots: an attestation never carries to a new manifest_root. Re-review is a new attestation.
  • Append-only with supersession: records are never deleted; the effective verdict for (attester, manifest_root) is the latest record, so an attester can downgrade a prior Approved to Flagged or Rejected. Flagged is advisory — clients SHOULD surface it prominently; it gates nothing protocol-side.
  • Cowboy Labs’ review organization is simply one attester, whose verdicts the flagship store and first-party clients choose to require.

2.8 Events

Every state transition in §2.1 emits a named CIP-29 event carrying the affected ids and (for lifecycle transitions) the acting party. Store-initiated pause/revoke_hire events are thereby publicly auditable; the “platform can pause apps” power is exactly as visible as it is real.

3. Economics and neutrality

The Trading Post charges nothing beyond gas. Store commission is a market price set per grant; competing stores may undercut it; creators may multi-home across stores or sell direct. The chain’s revenue from a thriving hire economy is store-agnostic: every hire’s execution buys compute and gas regardless of which storefront brokered it. This is deliberate — the protocol’s take is on computation, the unforkable layer, while distribution remains contestable.

4. Security considerations

  • Trading Post as high-value target. It custodies split execution and lease state. Mitigations: CIP-12 upgrade governance, no operational superpowers to abuse (§2.1 neutrality invariant), splits executed by simple arithmetic over validated vectors, and the actor-model’s single-threaded method execution (no reentrancy across a split’s transfers; token transfers are CIP-20 syscalls inside one method execution).
  • Grant/declaration forgery. All mutating methods authenticate the caller against the object’s authority field (creator, store operator, or hirer); standard actor-call sender authentication, no new signature schemes. declaration_id preimage verification (§2.1.1) prevents id squatting.
  • Prepaid custody. The Trading Post holds per-hire balances; only the hirer can withdraw, only renew/settle_per_call can draw, and revoke_hire refunds automatically. Balance accounting is per-hire — no pooled-fund invariants to break.
  • Artifact equivalence is a claim. claimed_root is signed state from the registrant, not a proof. A store serving content that diverges from the attested root is detectable by anyone with read access (decrypt + compare) and publicly attributable to the registering address; attesters can downgrade (§2.7). A cryptographic equivalence proof is an open question.
  • Lease policy correctness in cbssd. Issuance policy reads chain state; cbssd hand-rolls chain interaction today and has drifted from node before — the policy check MUST be covered by e2e tests against a live devnet node, not unit fixtures.
  • Split griefing. Vector caps (8 entries, no zero shares) bound transfer fan-out; beneficiary addresses are not validated as live — a transfer to a dead address burns that share, which is the beneficiary’s risk, as with any CIP-20 transfer.
  • Attestation index growth. attest is open to any address (§2.7), so a hostile attester can grow a root’s attestation index without bound. §2.7 mandates a bound: proportional metering plus pagination, or a per-root attester cap. The cap variant has a residual: Sybil attesters can fill a root’s index and block new attesters from recording verdicts on it — accepted, since filling costs gas per record and verdicts from unrecognized attesters carry no client trust weight; attesters clients rely on SHOULD attest at review time, before an adversary targets the root. Spam records themselves carry no trust weight because clients filter by attester.
  • Store-side censorship. Bounded by design: scope-limited pause powers, open store registration, direct hire, and public events.
  • Cached-DEK residual (§2.5.3): accepted, bounded by settlement refusal and runner stake; revisit if runner trust assumptions weaken.

5. Out of scope

Review policy and curation; commission values; fork attribution economics (CIP-27 follow-up); creator-code semantics beyond split entries; store UX; fiat display and funding rails (CIP-18/CIP-28 territory).

6. Open questions

  1. Per-epoch IBE label rotation as cached-DEK hardening — cost: ciphertext re-production path; candidate for a CIP-33.r2 once runner-trust data exists.
  2. PerCall rate-limit defaults and MPP session caps for hostile hiring actors.
  3. Capability-schema registry: whether a curated schema-type catalog (beyond free-form JSON Schema) earns its complexity once agent-hire volume exists.
  4. Whether instance_mode: Forked should become the default once CIP-27 stabilizes.
  5. Per-period escrow of executed splits, enabling protocol-level pro-rata clawback on trust-and-safety revocation (v1 refunds only unspent prepaid, §2.4).
  6. Cryptographic plaintext-equivalence proof binding a ServingArtifact to its version’s manifest_root (v1: signed claim + social detectability, §4).