Outcome-Based Pricing
Charge a fixed price only when the delivered bytes pass the provider's signed predicate, and nothing when they fail.
On this page
A provider can sell a result instead of an attempt. It signs one price against one deterministic predicate, and the caller pays that price only when the bytes it received pass the predicate.
The kernel holds the full price before dispatch, evaluates the predicate over the exact delivered output, and captures or releases the hold once delivery is proven. Each call settles at exactly the signed price or at zero, with no attempt fee and no prepayment.
Bytes that pass every assertion pay the full price
The receiver acknowledged the delivery and the predicate returned Passed over the exact bytes it holds. The assessment is FullPrice: the kernel captures the held outcomePrice once, and attribution follows the output's provenance class.
A provider signs one price against one predicate
The provider signs two records separately. chio.outcome.pricing.v1 binds one predicate, by id and digest, to one outcomePrice and one failure mode. OutcomeFailureModeV1 has a single variant, zero_charge, so a pricing record can declare no other behavior on a failure.
The caller asks for that price on a governed request. Its metered billing context uses the billing unit verified_outcome and carries a typed VerifiedOutcomeRequestV1 extension, which names the listing, provider binding, pricing, predicate, optional SLA, and receiver binding by id and digest, never by body. Before any money moves, the kernel’s validate_verified_outcome_request requires:
- the unit and the extension together, in both directions: the unit requires the extension, and any other billing unit that carries the extension is denied;
- the settlement mode
MeteredSettlementMode::HoldCapture,hold_captureon the wire; quoted_unitsequal to one, andmax_billed_unitsequal to one when the caller sets it;- an extension whose own
validatepasses.
A request that fails any of these is refused with GovernedTransactionDenied before a hold exists.
Read more in Pricing models, which covers the metered models and the HoldCapture settlement mode.
The kernel holds the price before dispatch and settles after delivery
Verified-outcome calls settle through a payment rail that supports a reversible hold: authorize reserves funds without settling them, capture settles the full amount once, and release removes the reservation without a charge. Rails plug in as optional modules. The hold is what stops spend before dispatch.
- Eligibility. The kernel resolves every referenced record by exact digest and signs
chio.outcome.eligibility.v1with the delivery acknowledgement deadline, the rail capture deadline, and the receiver binding. - Hold. It authorizes an unsettled hold for exactly
outcomePriceand records it before dispatch. - Evaluation. After the tool returns and the output guards run once, the kernel freezes the final bytes and evaluates the predicate over the JSON parsed from those same bytes. Nothing may change the output after evaluation.
- Delivery. The receiver stages the bytes, signs its acknowledgement, and only then exposes them to the agent.
- Settlement. The kernel captures or releases the hold as the disposition requires, then signs one receipt that binds the charge, every digest, the verdict, and the rail reference.
Capture always follows the receiver’s acknowledgement, so the caller pays only for bytes it durably holds. A lost acknowledgement or an unresolved delivery state freezes the hold until recovery resolves it, and only resolved delivery evidence releases it.
Read more in Reconciliation, which covers the authorize, capture, and release lifecycle.
The predicate is a short AND-list over the delivered JSON
chio.outcome.predicate.v1 carries between one and 256 assertions, and every one must hold. Each has one RFC 6901 JSON Pointer of at most 2048 characters, where the empty pointer selects the whole document, and exactly one comparator, tagged by kind. Two assertions with the same canonical bytes are rejected.
{
"schema": "chio.outcome.predicate.v1",
"predicateId": "<64-hex, derived over the body without predicateId>",
"providerId": "<the provider this record was signed for>",
"assertions": [
{ "pointer": "/status", "comparator": { "kind": "eq", "value": "complete" } },
{ "pointer": "/findings/0/id", "comparator": { "kind": "exists" } },
{ "pointer": "/rows_reviewed", "comparator": { "kind": "gte", "value": 1000 } }
],
"issuedAtUnixMs": 1752192000000,
"expiresAtUnixMs": 1752278400000
}| Comparator | Operand | Comparison |
|---|---|---|
exists | None | Any selected value passes; a missing target fails |
eq, ne | Attached JSON value | RFC 8785 canonical bytes |
lt, lte, gt, gte | Attached JSON integer | Checked integer conversion of both operands |
On the wire an assertion is { "pointer": ..., "comparator": { "kind": ..., "value": ... } }, and exists has no value member. The published schema states the three shapes as a oneOf and bounds an ordered operand to the I-JSON safe integer range. The comparator set holds no JSONPath, regex, WASM, floating-point comparison, user code, or model judgment, so two evaluators reach the same verdict on the same bytes.
evaluate_outcome_predicate takes the predicate and the output bytes and returns a verdict, the output digest, the predicate id, and the predicate envelope digest. The verdict is Passed, Failed { assertion_index, reason }, or Unevaluable { reason }, and a failure names its deciding assertion by index.
Two keys sign delivery, so the charged bytes are the bytes received
An anchor signs the chio.outcome.delivery-checkpoint.v1 records, and a receiver signs the terminal record. OutcomeReceiverBindingV1 hashes the anchor’s identity, key, and epoch together with the receiver’s into one receiverBindingDigest. The eligibility record carries that digest, so the pair of keys that may speak for a delivery is fixed before the call runs.
A checkpoint chain is exactly two records: pending at sequence one, then acknowledged or cancelled. An acknowledged record carries a blob digest equal to the output digest. The receiver builds its chio.outcome.delivery-acknowledgement.v1 from that checkpoint: it copies the acceptance time from the anchor’s trusted clock, so acceptance cannot be backdated, and requires finalOutputDigest to equal durableBlobDigest.
chio.outcome.delivery-nonacceptance.v1 is the matching record for a canceled checkpoint. Two kernel-signed records classify what happened to the bytes: chio.outcome.output-provenance.v1 sets a provenanceClass of provider or caller_policy, and chio.outcome.contractual-zero.v1 records a zero charge that never opened a delivery slot.
Read more in Delivery checkpoint rules.
The evidence decides the amount and who carries a zero
assess_outcome_price takes the delivery evidence, the verified pricing record, and the kernel-signed eligibility record, and returns an OutcomePriceAssessmentV1. It first checks that eligibility and pricing agree on the pricing id and digest, the provider, the predicate id and digest, the SLA digest, and the price. Then the delivery evidence picks the disposition the figure draws: FullPrice, ZeroPrice, or Indeterminate.
Evidence also decides attribution. An acknowledged delivery takes provider or caller_policy from its provenance class, so a guard block or a byte-changing redaction attaches to the caller’s policy. A canceled delivery is platform. A pre-delivery zero splits on its reason: output_blocked is caller_policy, and output_mutation_after_evaluation is platform.
An Unknown delivery returns Indeterminate with no verdict or attribution. Its assessed amount of zero neither settles nor waives the obligation; the hold stays frozen until the delivery evidence is recovered. On the kernel side, a resolved outcome carries one SettlementDispositionV1, Capture { amount }, ContractualZeroCharge { currency }, or NotApplicable, and the receipt’s chio.outcome.verdict.v1 projection binds it to the evidence that produced it.
Read more in Assessment by delivery evidence.
An SLA commitment turns failure rates into checkable evidence
A provider may sign one further record. chio.outcome.sla.v1 states the failure rate it commits to, max_failure_bps, over a fixed window with a minimum sample count. The pricing record references it by slaDigest, the eligibility record carries the same digest, and the assessment refuses to proceed when the two disagree. The anchor and the window fix the cadence: validation rejects an anchor later than effectiveAtUnixMs and a window that would overflow past the anchor.
A breach is proven with chio.outcome.sla-breach.v1. It covers the exact closed interval the anchor and cadence define, so a submitter cannot choose a favorable subrange, and it carries a complete range proof over every receipt in that interval. Only provider-attributable requests enter the rate; caller-policy and platform outcomes stay counted in their own partitions.
breach when
provider_failure_count × 10,000 > max_failure_bps × provider_attributable_count
and provider_attributable_count >= minimum_sample_countOne provider failure in three attributable requests breaches a 3,333 bps maximum; one in four does not breach an exact 2,500 bps maximum. A breach artifact is evidence submitted to governance and moves no funds.
A passed verdict proves the predicate held
Passed means the delivered JSON satisfied the predicate the provider signed, within the comparator set: JSON Pointer targets, canonical-byte equality, and integer ordering. Factual correctness and objective value rest on how well the buyer’s chosen predicate captures them. The receipt records what the kernel decided and charged; the mediation boundary covers what any receipt can establish about the world.
Outcome records and rules
Search for slaDigest, missing_target, or Indeterminate.
Pricing record
The signed price. Its id is a domain-separated SHA-256 over the canonical body with pricingId removed.
// schema: chio.outcome.pricing.v1 (id preimage: chio.outcome.pricing.id.v1)
pub struct OutcomePricingBodyV1 {
schema: String,
pricing_id: String, // sha256 over the body with pricingId removed
provider_id: String,
predicate_id: String, // 64-hex; the predicate's own derived id
predicate_digest: String, // 64-hex
outcome_price: MonetaryAmount,
failure_mode: OutcomeFailureModeV1, // ZeroCharge, the only variant
sla_digest: Option<String>, // omitted when absent
issued_at_unix_ms: u64,
expires_at_unix_ms: u64, // > issued_at_unix_ms
}Request extension
The unsigned projection a caller attaches to MeteredBillingContext. It names records by id and digest and never carries their bodies.
// schema: chio.outcome.request.v1 (unsigned projection, camelCase on the wire)
pub struct VerifiedOutcomeRequestV1 {
pub schema: String,
pub listing_id: String, // trimmed text, <= 2048 chars
pub listing_digest: String, // every remaining value is 64-hex
pub provider_binding_digest: String,
pub pricing_id: String,
pub pricing_digest: String,
pub predicate_id: String,
pub predicate_digest: String,
pub sla_digest: Option<String>,
pub receiver_binding_digest: String,
}Verdict reasons
Failed,assertion_mismatch: the pointer selected a value and the comparator rejected it.Failed,missing_target: the pointer selected nothing, for any comparator includingexists.Unevaluable,target_not_integer: an ordered comparator found a non-integer on either side.Unevaluable,invalid_output_json: the bytes are not UTF-8, not JSON, or not RFC 8785 canonical.delivery_cancelled,output_blocked, andoutput_mutation_after_evaluationcome from outside the evaluator: the price assessment sets them from the delivery evidence it is handed.
Delivery checkpoint rules
The first record is pending at sequence one, with no predecessor and no blob fields. advance builds the second, acknowledged or cancelled, only from a pending predecessor: it refuses a trusted clock that moves backwards, bumps the sequence by checked addition, and sets predecessorDigest to the previous envelope digest.
Authentication re-checks all of that against the record it already holds and requires every identity, binding, and digest field to stay unchanged across the transition. An acknowledged record carries a blob reference and a blob digest equal to the output digest. A canceled record carries no blob, a blob-absence proof digest, and a cancellation fence digest.
OutcomeDeliveryAcknowledgementBodyV1::from_receiver_assertion refuses a checkpoint whose state is not acknowledged, or whose request id, eligibility digest, and receiver binding differ from the eligibility record. It copies deliveryAcceptedAtUnixMs from the checkpoint’s trusted clock high-water mark.
Provenance and contractual-zero records
The output-provenance record binds the provider output digest, the final output digest, the post-guard policy and evidence digests, and an optional redaction proof. The contractual-zero record carries a reason of output_blocked or output_mutation_after_evaluation and a proof that no delivery slot was opened.
Assessment by delivery evidence
| Delivery evidence | Disposition | Verdict recorded | Attribution |
|---|---|---|---|
Acknowledged, evaluation Passed | FullPrice | Passed | From the provenance class |
Acknowledged, any other evaluation | ZeroPrice | The evaluation as it stands | From the provenance class |
Cancelled | ZeroPrice | Unevaluable { delivery_ | platform |
NotAttempted | ZeroPrice | Unevaluable with the contractual- | caller_policy or platform |
Unknown | Indeterminate | None | None |
Settlement disposition and verdict record
SettlementDispositionV1 rides with the evaluation id, the resolved output blob reference, the post-guard decision digest, and the pricing verdict digest, so the amount and the evidence that produced it move together.
chio.outcome.verdict.v1 binds the request id, the listing id and digest, the provider id and provider-binding digest, the pricing id and digest, the predicate id and digest, the quote digest, the eligibility digest, and the provider acceptance digest. It then binds the tagged deliveryDisposition with whichever acknowledgement, nonacceptance, or contractual-zero digest applies, the deliveredOutputDigest, the verdict with its optional reasonCode and assertionIndex, the slaAttribution, the chargedAmount, and the railAuthorizationRef.
SLA commitment
// schema: chio.outcome.sla.v1 (id preimage: chio.outcome.sla.id.v1)
pub struct OutcomeSlaBodyV1 {
schema: String,
sla_id: String, // sha256 over the body with slaId removed
provider_id: String,
listing_digest: String,
max_failure_bps: u16, // <= 10_000
minimum_sample_count: u64, // > 0
window_seconds: u64, // > 0
window_anchor_unix_ms: u64, // > 0, and <= effective_at_unix_ms
effective_at_unix_ms: u64,
expires_at_unix_ms: u64, // > effective_at_unix_ms
}The chio-outcome family
The family holds 11 schema files under spec/schemas/chio-outcome/v1/, of which the registry lists 9. The other 2 describe unsigned projections: spec/PROTOCOL.md states that chio.outcome.request.v1 and chio.outcome.verdict.v1 are not signed-artifact schemas. Every registered kind uses the outcome_ prefix and is introduced by verified-outcome-pricing-v1.
| File | Title | Registry id |
|---|---|---|
request. | Chio Verified Outcome Request V1 | unregistered |
predicate. | Chio Outcome Predicate V1 | chio. |
pricing. | Chio Outcome Pricing V1 | chio. |
sla.schema.json | Chio Outcome SLA V1 | chio. |
eligibility. | Chio Outcome Eligibility V1 | chio. |
delivery- | Chio Outcome Delivery Checkpoint V1 | chio. |
delivery- | Chio Outcome Delivery Acknowledgement V1 | chio. |
delivery- | Chio Outcome Delivery Nonacceptance V1 | chio. |
output- | Chio Outcome Output Provenance V1 | chio. |
contractual- | Chio Outcome Contractual Zero V1 | chio. |
verdict. | Chio Outcome Verdict V1 | unregistered |
Encoding and source
Every signed body is RFC 8785 canonical JSON with deny_unknown_fields, camelCase keys, and a versioned schema id. Each body carries its own id, a domain-separated SHA-256 over the canonical body with that id omitted, so a body already carrying its id is never re-hashed. Every time value is Unix milliseconds, and its field name says so.
The artifacts, the evaluator, and the assessment are pure code in crates/economy/chio-listing/src/outcome/. The schema-id constants and the request extension live in chio-core-types, and chio-kernel owns the request-side checks and the settlement disposition.