Chio/Docs
LOGIN · JOIN

Pricing Models

See how a provider's price, a grant's spending ceilings, and a bound quote combine to admit or refuse one priced call.

Concept chio@5f63e6e

On this page

An agent can buy computation at a provider's price and still spend only what its grant allows. The provider states the price, the grant states the ceiling, and the kernel admits a priced call only where the two meet.

Each responsibility has its own object. Manifest pricing advertises what a tool costs, the capability's budget fields bound what an agent may commit, a governed intent binds one quote to one request, and the receipt records the financial outcome. The running example is the fixer invoking /models/default through the models server, which bills by the thousand tokens and quotes 40 cents for one call against the USD 2.00 grant.

Three grant fields bound what an agent may spend on priced calls

Three fields on a ToolGrant carry spending authority. The issuer sets them, separately from the provider's manifest and the request's quote.

Price and authorityChoose an outcome.
priceceilingdispatchqquoteκgrantKkernelreserve USD 0.40dtoolrefusedno dispatchρReceiptamount, settlement statepriceceilingdispatchqquoteκgrantKkernelreserve USD 0.40dtoolrefusedno dispatchρReceiptamount, settlement state

A 40-cent quote clears a 40-cent ceiling

The provider quotes 8 units at 5 cents per thousand tokens: 40 cents. The grant allows at most 40 cents per call and USD 10.00 in total. The kernel reserves the 40 cents, a MustPrepay adapter prepays them before dispatch, and the receipt records the amount and the settlement state. Pricing models.

One priced call: a provider quote and a grant's spending ceilings meeting at the kernel. The amounts follow the 40-cent example and are illustrative; billing units and reconciliation are left out.

max_cost_per_invocation is the per-call ceiling the kernel uses for budget admission and authorized exposure. max_total_cost is the cumulative ceiling across the grant's invocations, and max_invocations limits the count. All three are optional; configure both monetary ceilings for a bounded priced-call workflow.

A MustPrepay quote above either applicable ceiling is refused before dispatch, and the kernel signs a deny receipt that carries the reason. The ceilings bound calls admitted through the kernel and its accounting path.

Read more in Budgets and metering, which covers reservation, delegation, and remaining-budget behavior.

A 40-cent quote clears a 40-cent ceiling

The models server advertises 5 cents per thousand-token unit and quotes eight units for the fixer's next call: 8 × 5 = 40 cents. The fragments below are pieces of the manifest, the grant, and the governed intent, in their wire field names.

pricing-fragment.jsontool-grant-limits-fragment.jsongoverned-intent-fragment.json
{
  "pricing_model": "per_unit",
  "unit_price": { "units": 5, "currency": "USD" },
  "billing_unit": "1k_tokens"
}
  1. Advertise. The manifest prices the tool per_unit at 5 USD minor units per 1k_tokens.
  2. Bound. The fixer's grant permits at most 40 cents per call and USD 2.00 across its 50 invocations, so the fifth 40-cent call exhausts it whatever the count allows. A per-call ceiling equal to the quote keeps the reserved exposure at 40 cents; a larger ceiling reserves a larger amount.
  3. Quote. The billing integration supplies a quote ID, the provider identity, an issuance time, and an expiry, with a quoted quantity of 8 and a quoted cost of 40 USD minor units. Assemble the request from the provider's values.
  4. Bind. Add the complete quote under metered_billing.quote before binding the intent into the request. The intent amount, the quoted cost, and the per-call ceiling are all 40 cents. maxBilledUnits is an explicit reconciliation bound; the monetary limits and the payment authorization govern admission.
  5. Inspect. With a valid request, enough remaining authority, and a working MustPrepay adapter, the 40 cents is prepaid before dispatch. Read the receipt's decision and settlement metadata afterward.

The receipt's settlement metadata, never the tool result, says whether payment settled. The captured approval example shows an allowed priced call and the refusal that follows when the payment adapter is absent.

The receipt keeps quoted, observed, and recorded cost apart

Each value comes from a different party at a different moment.

ValueSourceWhat it establishes
Quoted costMeteredBillingQuote.quoted_costThe estimate bound to the intent before execution
Observed costTool-server cost reportProvider-reported usage, as reliable as its metering
Recorded costfinancial.cost_chargedThe amount this execution path recorded

Read the recorded cost with settlement_status, payment_reference, and any cost breakdown. In the captured compute example, the quote and the final prepayment are USD 1.00 while the tool reports USD 0.75, and the receipt retains the USD 1.00 settled prepayment.

On a cost overrun, the recorded amount can exceed the retained budget exposure while settlement is marked failed, so the field name alone proves no transfer. Reconciliation compares the three values and flags each discrepancy.

A quote outside its window, ceiling, or currency stops before dispatch

Admission reads the quote and the grant together, before the tool runs. Four conditions refuse the call.

  • Window. A quote is valid when issued_at <= now and, if it carries an expiry, now < expires_at. A future-dated or expired quote is refused.
  • Ceiling. A MustPrepay quote above the per-call or cumulative ceiling is refused.
  • Currency. The quote currency must match the governed intent's amount and the charge currency, so a USD grant paired with an EUR quote is refused. This check fetches no exchange rate.
  • Payment. A MustPrepay call with no payment adapter is refused before dispatch, because no adapter can establish the prepayment.

Currency conversion happens on a separate path, after execution. When a tool reports cost in another currency, a configured oracle converts it into the grant currency and the conversion evidence is recorded in financial.oracle_evidence. If conversion fails, settlement is marked failed and the authorized exposure stays retained, because the call has already run.

Read more in the oracle integration, which covers feed evidence and freshness checks.

The intent names a payment posture; the receipt records the outcome

A governed intent carries one of three settlement modes. must_prepay prepays the quoted amount before dispatch through a payment adapter, which records its settlement result. hold_capture runs against a hold that is then captured or released. allow_then_settle runs first and settles later, so read its pending or final evidence before treating the obligation as paid.

The rail that executes a mode plugs in as an optional module; x402, ACP, and other rails run outside the kernel. Holds and grant ceilings prevent spend before dispatch, and the rail's settlement outcome is observed and recorded on the receipt.

Read more in Settlement rails, and in Outcome-based pricing for a delivery condition that decides whether a held payment is captured or released.

Pricing and billing reference

Pricing models

Tool manifests advertise one of four models. The billing unit names how the provider measures usage; the provider's cost report carries the measured usage after the call, and reconciliation compares it with the quote.

Wire modelPrice fieldsMeaning
flat
base_price
A fixed base price
per_invocation
unit_price; invocation
A fixed unit price for each call
per_unit
unit_price; billing_unit
A price per declared unit, such as 1k_tokens, MB, or row
hybrid
base_price + unit_price; billing_unit
A fixed base plus a usage component

Prices use integer minor currency units: 100 USD units is USD 1.00.

crates/core/chio-core-types/src/capability/scope.rs80-91rust
/// A monetary amount with currency denomination.
///
/// Uses minor-unit integers to avoid floating-point precision issues.
/// For USD, 1 dollar = 100 units (cents). For JPY, 1 yen = 1 unit.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MonetaryAmount {
    /// Amount in the currency's smallest unit (e.g. cents for USD).
    pub units: u64,
    /// ISO 4217 currency code. Examples: "USD", "EUR", "JPY".
    pub currency: String,
}

Manifest pricing fields

A ToolDefinition may carry an optional ToolPricing block. The Rust variants are Flat, PerInvocation, PerUnit, and Hybrid; their wire names use snake_case.

crates/platform/chio-manifest/src/lib.rs146-157rust
/// Optional pricing metadata advertised by a tool server.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ToolPricing {
    pub pricing_model: PricingModel,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub base_price: Option<MonetaryAmount>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub unit_price: Option<MonetaryAmount>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub billing_unit: Option<String>,
}
hybrid-pricing-fragment.jsonjson
{
  "pricing": {
    "pricing_model": "hybrid",
    "base_price": { "units": 100, "currency": "USD" },
    "unit_price": { "units": 5, "currency": "USD" },
    "billing_unit": "1k_tokens"
  }
}

This fragment advertises a USD 1.00 base plus 5 cents per thousand-token unit. Spending ceilings belong on the capability, and service-level hints belong on the listing.

Listing prices and service levels

A signed listing pricing hint pairs a price per call with an advertised service level and a recent-activity snapshot. A buyer uses it to select a provider, and the seller's signature attributes its claims to that seller.

crates/economy/chio-listing/src/discovery.rs113-121rust
/// Service-level advertisement paired with a pricing hint.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ListingSla {
    pub max_latency_ms: u64,
    /// Availability SLA expressed in basis points. `10_000` means 100.00%.
    pub availability_bps: u32,
    pub throughput_rps: u64,
}
crates/economy/chio-listing/src/discovery.rs48-74rust
pub struct ListingPricingHint {
    pub schema: String,
    /// Listing this hint applies to.
    pub listing_id: String,
    /// Namespace of the listing (must match the listing body).
    pub namespace: String,
    /// Provider / operator advertising the price (must match the listing
    /// publisher).
    pub provider_operator_id: String,
    /// Capability scope prefix covered by this hint (e.g.
    /// `"tools:search"` or `"tools:search:*"`). Queries filter against this.
    pub capability_scope: String,
    /// Fixed price charged per invocation under the advertised scope.
    pub price_per_call: MonetaryAmount,
    /// Advertised SLA for invocations under this hint.
    pub sla: ListingSla,
    /// Rolling revocation rate over recent invocations, in basis points.
    /// `0` means "no revocations in the window"; `10_000` means "100%".
    pub revocation_rate_bps: u32,
    /// Number of receipts the provider has produced in the recent window.
    pub recent_receipts_volume: u64,
    /// Unix seconds when the hint was issued.
    pub issued_at: u64,
    /// Unix seconds when the hint expires. Past expiry, the hint is stale
    /// and the listing falls out of the marketplace.
    pub expires_at: u64,
}

The schema is chio.marketplace.listing-pricing-hint.v1. Validation requires a positive price, an expiry after issuance, a revocation rate in [0, 10000] basis points, availability in (0, 10000], and positive latency and throughput values. Discovery checks freshness when it decides whether a hint is usable.

Reputation-tier price calculation

The appraisal helper computes a deterministic invocation price from a supplied base price and a tenant reputation tier. Tier 0 pays the base; tiers 1, 2, and 3 receive 5%, 10%, and 20% discounts. Integer division truncates fractional minor units, so 101 units at tier 1 becomes 95 units.

crates/economy/chio-appraisal/src/marketplace_pricing.rs50-60rust
pub enum MarketplaceReputationTier {
    /// Default tier. Highest invocation price (no discount).
    #[default]
    Tier0,
    /// Trusted publisher tier with a small discount.
    Tier1,
    /// High-trust tier.
    Tier2,
    /// Highest-trust tier with the largest discount.
    Tier3,
}
crates/economy/chio-appraisal/src/marketplace_pricing.rs155-162rust
/// Discount table consumed by [`compute_marketplace_invocation_price`].
///
/// The table is intentionally small and deterministic. Tier0 pays the
/// full sticker price (no discount). Higher tiers receive monotonic
/// discounts. Discounts are expressed as units per hundred so the
/// resolution is one percent: a value of `5` means a five-percent
/// discount applied via integer arithmetic.
pub const TIER_DISCOUNT_PER_HUNDRED: [u32; 4] = [0, 5, 10, 20];

compute_checked_marketplace_invocation_price validates a nonempty, unpadded tenant ID and an uppercase three-letter currency. Its caller supplies the tier and establishes the tier's provenance. The helper is storage independent, and a zero base stays zero.

Governed intent binding

A governed intent carries the purpose, target, requested amount, and optional metered billing context for an economically sensitive action. Binding the quote into it keeps the quoted terms attached to the request being authorized: the intent's binding hash connects the quoted amount, unit, time window, and settlement mode to authorization and to later evidence.

crates/core/chio-core-types/src/capability/governance.rs868-906rust
/// Canonical intent attached to a governed transaction request.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct GovernedTransactionIntent {
    /// Unique intent identifier (UUIDv7 recommended).
    pub id: String,
    /// Target tool server for this governed action.
    pub server_id: String,
    /// Target tool name for this governed action.
    pub tool_name: String,
    /// Human or policy-readable purpose for the governed action.
    pub purpose: String,
    /// Optional maximum amount explicitly approved for this intent.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub max_amount: Option<MonetaryAmount>,
    /// Optional commerce approval context for seller-scoped payment rails.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub commerce: Option<GovernedCommerceContext>,
    /// Optional metered-billing quote and settlement context for non-rail tools.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metered_billing: Option<MeteredBillingContext>,
    /// Optional runtime attestation evidence bound to this governed request.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub runtime_attestation: Option<RuntimeAttestationEvidence>,
    /// Optional delegated call-chain context for upstream transaction provenance.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub call_chain: Option<GovernedCallChainContext>,
    /// Optional explicit autonomy tier and delegation-bond attachment.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub autonomy: Option<GovernedAutonomyContext>,
    /// Optional structured context for downstream policy or operator inspection.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub context: Option<serde_json::Value>,
    /// Typed governed-action body. Tool invocation remains the wire-compatible default.
    #[serde(
        default,
        skip_serializing_if = "GovernedTransactionIntentBody::is_tool_invocation"
    )]
    pub body: GovernedTransactionIntentBody,
}
crates/core/chio-core-types/src/capability/governance.rs166-179rust
/// Generic metered-billing context attached to a governed request.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MeteredBillingContext {
    /// Settlement posture expected for this metered tool action.
    pub settlement_mode: MeteredSettlementMode,
    /// Pre-execution quote bound to the governed request.
    pub quote: MeteredBillingQuote,
    /// Optional explicit upper bound on billable units for the request.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub max_billed_units: Option<u64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub verified_outcome: Option<VerifiedOutcomeRequestV1>,
}

The outer fields use snake_case, including metered_billing and max_amount. The nested context uses camelCase: settlementMode, maxBilledUnits, and verifiedOutcome. The last field binds an optional results-priced request.

Settlement modes

ModeBefore dispatchAfter dispatch
must_prepay
Quoted amount prepaid through a payment adapter
Adapter records the settlement result
hold_capture
Execution runs against a hold
Hold captured or released
allow_then_settle
Execution runs unpaid
Pending or final settlement evidence

MeteredBillingQuote

crates/core/chio-core-types/src/capability/governance.rs76-95rust
/// Stable quote describing pre-execution metered billing expectations.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MeteredBillingQuote {
    /// Stable quote identifier from the billing or metering authority.
    pub quote_id: String,
    /// Billing or metering provider that issued the quote.
    pub provider: String,
    /// Billing unit used to interpret `quoted_units` (for example `1k_tokens`).
    pub billing_unit: String,
    /// Quoted number of billable units for the pre-execution estimate.
    pub quoted_units: u64,
    /// Quoted monetary amount for the estimate.
    pub quoted_cost: MonetaryAmount,
    /// Unix timestamp (seconds) when the quote was issued.
    pub issued_at: u64,
    /// Optional Unix timestamp (seconds) when the quote expires.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub expires_at: Option<u64>,
}

The quote identifies a provider, billing unit, quantity, monetary estimate, and time window. The struct carries no signature: its provider string is attribution data, and validating its fields authenticates no provider. Establish provider trust through the integration that delivered the quote.

Quote validity and unit bounds

Admission checks nonempty quote, provider, and billing-unit identifiers; positive quoted units; and a valid time window. A quote is valid when issued_at <= now and, if an expiry exists, now < expires_at. An omitted expiry adds no upper time bound in this check.

crates/core/chio-core-types/src/capability/governance.rs97-102rust
impl MeteredBillingQuote {
    #[must_use]
    pub fn is_valid_at(&self, now: u64) -> bool {
        now >= self.issued_at && self.expires_at.is_none_or(|expires_at| now < expires_at)
    }
}

maxBilledUnits, when supplied, must be positive and at least the quoted quantity. It is recorded for usage reconciliation, which flags observed usage above it. The tool's spend is bounded by the monetary ceilings, which stop a call before dispatch; this unit bound neither stops a running tool, caps its bill, nor pauses the grant.

Refusal and settlement failure conditions

ConditionBehaviorNext action
Quote future-dated or expired
Admission refuses the window
Obtain a current quote
MustPrepay quote exceeds authority
Admission refuses the per-call or cumulative excess
Reduce the request or obtain a new grant
Quote currency differs from grant or intent
Metered-context validation refuses the mismatch
Obtain a quote in the authorized currency
MustPrepay adapter absent
Prepayment cannot be established; the call is denied
Configure the payment path
Observed usage exceeds maxBilledUnits
Reconciliation flags the excess usage
Compare metering evidence and apply a policy response
Observed cost exceeds authorized exposure
Exposure retained; settlement marked failed
Reconcile before treating it as a settled charge

Next: price your own tools