Chio/Docs
LOGIN · JOIN

Outcome-Based Pricing

Charge a fixed price only when the delivered bytes pass the provider's signed predicate, and nothing when they fail.

Concept chio@5f63e6e

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.

Verified-outcome assessmentChoose an outcome.
pricetestprovepassedqsigned priceπpredicateρdelivery evidenceKkernelholds outcomePriceρFullPricecapture the holdρZeroPricerelease the holdBIndeterminatehold frozenDeniedbefore any holdpricetestproveqpriceπpredicateρdeliveryKkernelholds outcomePriceρFullPricecapture the holdρZeroPricerelease the holdBIndeterminatehold frozenDeniedbefore any hold

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.

One verified-outcome call: the provider's signed price and predicate, the delivery evidence, and the disposition the kernel derives before it captures or releases the hold. Rail mechanics, the SLA commitment, and receipt fields are left out.

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_capture on the wire;
  • quoted_units equal to one, and max_billed_units equal to one when the caller sets it;
  • an extension whose own validate passes.

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.

  1. Eligibility. The kernel resolves every referenced record by exact digest and signs chio.outcome.eligibility.v1 with the delivery acknowledgement deadline, the rail capture deadline, and the receiver binding.
  2. Hold. It authorizes an unsettled hold for exactly outcomePrice and records it before dispatch.
  3. 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.
  4. Delivery. The receiver stages the bytes, signs its acknowledgement, and only then exposes them to the agent.
  5. 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.

predicate.jsonjson
{
  "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
}
ComparatorOperandComparison
existsNoneAny selected value passes; a missing target fails
eq, neAttached JSON valueRFC 8785 canonical bytes
lt, lte, gt, gteAttached JSON integerChecked 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 ruletext
breach when
  provider_failure_count × 10,000 > max_failure_bps × provider_attributable_count
  and provider_attributable_count >= minimum_sample_count

One 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

Pricing record

The signed price. Its id is a domain-separated SHA-256 over the canonical body with pricingId removed.

OutcomePricingBodyV1rust
// 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.

VerifiedOutcomeRequestV1rust
// 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 including exists.
  • 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, and output_mutation_after_evaluation come 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 evidenceDispositionVerdict recordedAttribution
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_cancelled }
platform
NotAttempted
ZeroPrice
Unevaluable with the contractual-zero reason
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

OutcomeSlaBodyV1rust
// 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.

FileTitleRegistry id
request.schema.json
Chio Verified Outcome Request V1
unregistered
predicate.schema.json
Chio Outcome Predicate V1
chio.outcome.predicate.v1
pricing.schema.json
Chio Outcome Pricing V1
chio.outcome.pricing.v1
sla.schema.json
Chio Outcome SLA V1
chio.outcome.sla.v1
eligibility.schema.json
Chio Outcome Eligibility V1
chio.outcome.eligibility.v1
delivery-checkpoint.schema.json
Chio Outcome Delivery Checkpoint V1
chio.outcome.delivery-checkpoint.v1
delivery-acknowledgement.schema.json
Chio Outcome Delivery Acknowledgement V1
chio.outcome.delivery-acknowledgement.v1
delivery-nonacceptance.schema.json
Chio Outcome Delivery Nonacceptance V1
chio.outcome.delivery-nonacceptance.v1
output-provenance.schema.json
Chio Outcome Output Provenance V1
chio.outcome.output-provenance.v1
contractual-zero.schema.json
Chio Outcome Contractual Zero V1
chio.outcome.contractual-zero.v1
verdict.schema.json
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.

Next: price a call by its quantity