Work Agreements and Funding
Commit both parties to exact signed bytes, back the agreement with an exclusive allocation, and let a supplier subcontract only from prefunded money.
On this page
A work agreement fixes what a buyer pays for before any work starts. Both parties sign one canonical body, a funding allocation on a rail commits money to exactly that body, and a supplier that wants help signs a permit for one exact child agreement. Every record is named by a digest of its bytes, so a receiver that holds the digest can check that nobody changed the terms after signing.
The example continues from Verifiable Work: you buy an authentication inventory of the pricing service’s OpenAPI document from your partner for USD 28.00, and your partner may buy one part of it from a specialist.
Each identifier commits to the records before it
Four digests and one signature carry the agreement from its signed body to the money. Each is computed over bytes that include the identifiers above it.
The allocation names one claim on one escrow
The escrow computes Keccak-256 over the ABI encoding of the chain ID, its own address, and the complete Terms, which carry the agreement digest as bytes32. The SHA-256 digest enters as bytes, never rehashed as hex text.
Follow the arrows into the verifier’s signature. A change to any byte of the agreement changes its digest, the Terms that embed it, the allocation id, and every record after them, so the escrow can check a decision against the funded terms without trusting either party’s copy. Each hash is fixed by the protocol: a SHA-256 digest used as bytes32 is neither rehashed as hex text nor replaced with Keccak-256.
Both parties sign one canonical body
Prepare the agreement at your owner work service. It freezes the terms, signs with your key, and collects your partner’s signature over the identical canonical body through your partner’s owner service.
import { readFileSync } from "node:fs";
import { WorkClient } from "@chio-protocol/process";
const work = await WorkClient.open("./work");
const prepared = await work.prepare({
schema: "chio.work.preparation.v1",
program_id: "pricing-openapi-auth",
command_id: "auth-agree-1",
proposal: {
Agreement: {
commitment: JSON.parse(readFileSync("auth-draft.json", "utf8")),
funding_profile_id: "work-claim-escrow",
terms_reference: "terms/openapi-auth.json",
},
},
});
console.log(prepared.describe());preparation auth-agree-1 Prepared
agreement 7e1d…c04a SHA-256 of the RFC 8785 body
buyer did:chio:z6Mkf3…Qp9 signed
provider did:chio:z6MkpA7…c2T signed through kernel.halden.example/cosign
verifier verify.corbel.example pinned 0x9f62…3ad5
checker openapi-explicit-auth-v1 c7a1…02be
amount USD 28.00 to 0x7d0c…12f4
deadlines submitBy 2026-10-14T18:00Z challengeUntil 2026-10-15T18:00Z
resolveBy 2026-10-16T18:00Z refundAfter 2026-10-17T18:00Zimport json
from chio_process import WorkClient
work = WorkClient.open("./work")
with open("auth-draft.json") as f:
draft = json.load(f)
prepared = work.prepare({
"schema": "chio.work.preparation.v1",
"program_id": "pricing-openapi-auth",
"command_id": "auth-agree-1",
"proposal": {"Agreement": {
"commitment": draft,
"funding_profile_id": "work-claim-escrow",
"terms_reference": "terms/openapi-auth.json",
}},
})
print(prepared.describe())preparation auth-agree-1 Prepared
agreement 7e1d…c04a SHA-256 of the RFC 8785 body
buyer did:chio:z6Mkf3…Qp9 signed
provider did:chio:z6MkpA7…c2T signed through kernel.halden.example/cosign
verifier verify.corbel.example pinned 0x9f62…3ad5
checker openapi-explicit-auth-v1 c7a1…02be
amount USD 28.00 to 0x7d0c…12f4
deadlines submitBy 2026-10-14T18:00Z challengeUntil 2026-10-15T18:00Z
resolveBy 2026-10-16T18:00Z refundAfter 2026-10-17T18:00Zuse chio_runtime::work::{WorkClient, WorkCommitmentV1, WorkPreparationV1};
let work = WorkClient::open("./work").await?;
let draft = WorkCommitmentV1::from_file("auth-draft.json")?;
let proposal = WorkPreparationV1::agreement("pricing-openapi-auth", "auth-agree-1", draft)
.funding_profile("work-claim-escrow")
.terms("terms/openapi-auth.json");
let prepared = work.prepare(proposal).await?;
println!("{}", prepared.describe());preparation auth-agree-1 Prepared
agreement 7e1d…c04a SHA-256 of the RFC 8785 body
buyer did:chio:z6Mkf3…Qp9 signed
provider did:chio:z6MkpA7…c2T signed through kernel.halden.example/cosign
verifier verify.corbel.example pinned 0x9f62…3ad5
checker openapi-explicit-auth-v1 c7a1…02be
amount USD 28.00 to 0x7d0c…12f4
deadlines submitBy 2026-10-14T18:00Z challengeUntil 2026-10-15T18:00Z
resolveBy 2026-10-16T18:00Z refundAfter 2026-10-17T18:00Zchio work prepare --state ./work auth-agree-1.jsonpreparation auth-agree-1 Prepared
agreement 7e1d…c04a SHA-256 of the RFC 8785 body
buyer did:chio:z6Mkf3…Qp9 signed
provider did:chio:z6MkpA7…c2T signed through kernel.halden.example/cosign
verifier verify.corbel.example pinned 0x9f62…3ad5
checker openapi-explicit-auth-v1 c7a1…02be
amount USD 28.00 to 0x7d0c…12f4
deadlines submitBy 2026-10-14T18:00Z challengeUntil 2026-10-15T18:00Z
resolveBy 2026-10-16T18:00Z refundAfter 2026-10-17T18:00ZThe agreement names the buyer, provider, verifier, and custodian keys, which must all differ; the input and checker digests; the rail; the four deadlines, which must be strictly ordered; and the custody policy, which retains the evidence for at least 30 days past the refund deadline. Amounts are canonical decimal strings in minor units, positive and at most 253 − 1, and the parser refuses duplicate keys, unsafe integers, and unknown fields or versions.
Your configured pins select every accepted signer, so a signed envelope cannot introduce a key of its own. Preparing an agreement authorizes no reserve and no transfer; funding is a separate step at the rail.
Funding locks one exclusive allocation before dispatch
Fund the agreement. The escrow derives the allocation id from the chain, its own address, and the complete terms, then moves exactly the agreed amount from the payer.
chio work fund --state ./work auth-agree-1allocation 0x8c1f…40d2 keccak256(chainId 8453, escrow 0x3b9e…a71c, terms) state Funded USD 28.00 moved from 0x41a3…9be0 to the escrow token USDC 0x8335…2913, amount 28000000 reserve work-claim-escrow agreement 7e1d…c04a commitment auth-commitment.json funding reference attached
The escrow accepts funding only from the payer named in the terms, with an allowlisted token and verifier, a positive amount, and deadlines still in the future. Each payer funds an agreement digest once, so the same terms cannot back two allocations, and another payer cannot occupy your digest to block your purchase. The funded commitment now carries a WorkFundingRefV1:
{
"handle": {
"program_id": "pricing-openapi-auth",
"slot_id": "auth-inventory",
"allocation_hash": "b41e…07ac",
"receiver_kernel_id": "9b07…d31c",
"request_id": "req-01c4…7a90"
},
"dispatch_permit": { "slot_id": "auth-inventory", "signer": "9b07…d31c", "signature": "5f2c…e019" },
"profile_ref": {
"owner": "did:chio:z6MkpA7…c2T",
"entry": "openapi-explicit-auth-v1",
"generation": "e2c0…5a17"
},
"invocation_custody_ref": "custody-01c4…7a93",
"graph_ref": "0d6b…99e4",
"funding": {
"rail": "work-claim-escrow",
"agreement_digest": "7e1d…c04a",
"reserve_ref": "0x8c1f…40d2"
}
}WorkCommitmentV1 links the work handle, your partner’s signed dispatch permit, the resolved profile, the custody reference for the exact invocation, and the task graph. The funding reference names the rail, the agreement digest, and the reserve, and proves nothing by itself: before payable work starts, your partner’s kernel reads the allocation on the rail and checks its exact binding, and dispatch stays closed while funding is pending or unverifiable.
A subcontract needs a permit for one exact child agreement
Your partner’s kernel, never its buying agent, signs a procurement permit. It binds your agreement and complete request to one child agreement, one delegated agent, one specialist, a price ceiling, and an expiry.
{
"parentAgreementSha256": "7e1d…c04a",
"parentRequestSha256": "a3f9…6d21",
"childAgreementSha256": "4b62…e8f0",
"delegate": "e91d…44b0",
"specialist": "c3a8…5f20",
"priceCeiling": 600,
"currency": "USD",
"expiresAt": 1792087200
}The specialist’s kernel checks the permit with the promisor key it selected locally, before it quotes, accepts, or dispatches paid work. A missing permit, a changed job or price, or a signature from the agent instead of the kernel ends in subcontract permit does not authorize this exact child procurement, and the promisor key never becomes a trusted capability issuer. Repeating a valid quote returns the same single-use capability, so it cannot buy the work twice.
The child’s job id is child- followed by your agreement digest, its deadline is yours, and its ceiling cannot exceed your partner’s. A child cannot subcontract onward, and no descendant can widen the disclosure, task families, or authority of the agreement above it. The first composition profile allows one level of subcontracting and at most four children.
Child obligations are prefunded
Expected parent revenue is not collateral. Your partner may admit a payable child only against an allocation it funded from money it holds now, and that allocation stays locked while the child’s claim can still be earned.
Suppose you reserve USD 30.00: at most USD 28.00 for your partner’s accepted result, USD 1.00 for verification, and USD 1.00 for settlement. Your partner separately reserves USD 10.00: USD 6.00 for the specialist, USD 2.00 for a second specialist, and USD 2.00 for the children’s verification and settlement.
| Outcome | You pay for service | Partner’s child obligations | Unsuccessful production |
|---|---|---|---|
| Your result and both children accepted | USD 28.00 | USD 8.00 plus fees | Your partner, from its margin |
| Specialist accepted, partner fails before delivery | USD 0.00 | USD 6.00 plus incurred fees | Your partner’s prefunded reserve |
| Both children accepted, your result rejected | USD 0.00 | USD 8.00 plus incurred fees | Your partner, within its exposure |
| Specialist’s outcome unknown | Decided by your terms | USD 6.00 locked until resolved | As the timeout terms name |
| Partner ignores a valid child result | Decided by your outcome | Specialist claims without it | Your partner, unable to erase the claim |
Fees can stay payable when the service payment is zero, and the view shows both. Count a supply chain’s spending per funding source: your USD 28.00 to your partner and your partner’s USD 6.00 to the specialist are two transfers, and adding both to your budget double-counts money that circulates. Your own kernel caps what you authorize across sources and sessions, reserving the worst case before each cost-bearing call; Authoritative Spend describes that hold ledger.