Chio/Docs

EconomyCost & Settlement

Pricing Models & SLAs

Signed manifests advertise prices. The kernel checks each call against its capability budget, and metered billing binds usage-priced calls to a quote.

The Four Pricing Models

The PricingModel enum in chio-manifest has four variants. The wire spelling is snake_case.

VariantWire nameBehavior
PricingModel::FlatflatOne fixed base price; no parameter sensitivity.
PricingModel::PerInvocationper_invocationSame fixed unit price every call; billing unit is invocation.
PricingModel::PerUnitper_unitPrice scales with a declared billing unit such as 1k_tokens, MB, or row.
PricingModel::HybridhybridFixed base plus a per-unit variable component.

Results-priced counterpart

The four models above price a call on its inputs. For a call priced on results instead, see Outcome-Based Pricing: the payment is held and captured in full only if the output satisfies a declared predicate, and otherwise released to zero.

All prices are denominated in minor currency units (cents for USD, the smallest denomination for other currencies), matching the MonetaryAmount type from chio-core-types::capability::scope.

chio-core-types/src/capability/scope.rs
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,
}

ToolPricing

Each ToolDefinition in a manifest may carry an optional ToolPricing block. The fields are flat:

chio-manifest/src/pricing.rs
#[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>,
}

Which fields are populated depends on the model:

Modelbase_priceunit_pricebilling_unit
flatSetAbsentAbsent or invocation
per_invocationAbsentSetinvocation
per_unitAbsentSetNames the scaling dimension
hybridSetSetNames the scaling dimension
tool-manifest-fragment.json
{
  "name": "summarize",
  "description": "Returns a model-generated summary",
  "input_schema": { "...": "..." },
  "pricing": {
    "pricing_model": "hybrid",
    "base_price":   { "units": 100, "currency": "USD" },
    "unit_price":   { "units": 5,   "currency": "USD" },
    "billing_unit": "1k_tokens"
  },
  "has_side_effects": false,
  "latency_hint": "moderate"
}

No SLA fields on ToolPricing

The shipped ToolPricing struct in chio-manifest does not include SLA guarantees, currency caps, or per-call ceilings. Those values live on the marketplace listing (ListingSla,ListingPricingHint) or on the capability grant (max_cost_per_invocation,max_total_cost) rather than the manifest pricing block.

SLA on Marketplace Listings

Service-level commitments live on the marketplace listing, signed by the operator and paired with a price hint. The struct is ListingSla in chio-listing::discovery:

chio-listing/src/discovery.rs
pub struct ListingSla {
    pub max_latency_ms: u64,
    /// Availability SLA in basis points. 10_000 = 100.00%.
    pub availability_bps: u32,
    pub throughput_rps: u64,
}

The signed pricing hint ListingPricingHint attaches one SLA, one price-per-call, and a recent-activity snapshot to a published listing:

chio-listing/src/discovery.rs
pub struct ListingPricingHint {
    pub schema: String, // chio.marketplace.listing-pricing-hint.v1
    pub listing_id: String,
    pub namespace: String,
    pub provider_operator_id: String,
    pub capability_scope: String,
    pub price_per_call: MonetaryAmount,
    pub sla: ListingSla,
    /// Rolling revocation rate over recent invocations, in basis points.
    pub revocation_rate_bps: u32,
    /// Number of receipts the provider has produced in the recent window.
    pub recent_receipts_volume: u64,
    pub issued_at: u64,
    pub expires_at: u64,
}

Validation rules from ListingPricingHint::validate and ListingSla::validate:

  • price_per_call.units > 0; a zero-unit price is rejected.
  • revocation_rate_bps MUST sit in [0, 10000].
  • expires_at > issued_at; past-expiry hints are stale and the listing falls out of the marketplace.
  • availability_bps MUST sit in (0, 10000].
  • max_latency_ms and throughput_rps MUST be greater than zero.

Reputation-Tier Pricing

chio-appraisal derives a marketplace invocation price from an advertised base price and the caller's reputation tier. The model is deterministic: equal inputs produce equal outputs, and the discount math is integer-only.

chio-appraisal/src/marketplace_pricing.rs
#[serde(rename_all = "snake_case")]
pub enum MarketplaceReputationTier {
    Tier0, // full sticker price, no discount
    Tier1,
    Tier2,
    Tier3, // largest discount
}

/// Discount per hundred, indexed by tier. A value of 5 means five percent.
pub const TIER_DISCOUNT_PER_HUNDRED: [u32; 4] = [0, 5, 10, 20];

Tier0 pays the full sticker price. Tier1, Tier2, and Tier3 take 5%, 10%, and 20% off respectively. A zero-priced base stays zero regardless of tier, and rounding is half-down by truncation to preserve minor-unit semantics.

Settlement-facing callers use compute_checked_marketplace_invocation_price, which validates the MarketplaceBasePrice and MarketplacePricingContext before applying the discount and returns a MarketplaceInvocationPrice. The unchecked compute_marketplace_invocation_price helper remains for callers that already validate their inputs. The discount is layered on top of the advertised ToolPricing; the manifest price is the sticker, the tier is the caller's standing.


Metered Billing on the Governed Intent

For tools where the cost depends on something the kernel cannot see ahead of time (token counts, transferred bytes, outbound third-party fees), the agent attaches a MeteredBillingContext to its GovernedTransactionIntent. This binds the call to a quote from a billing or metering provider with a stated settlement configuration.

chio-core-types/src/capability/governance.rs
#[serde(rename_all = "snake_case")]
pub struct GovernedTransactionIntent {
    pub id: String,
    pub server_id: String,
    pub tool_name: String,
    pub purpose: String,
    pub max_amount: Option<MonetaryAmount>,
    pub commerce: Option<GovernedCommerceContext>,
    pub metered_billing: Option<MeteredBillingContext>,
    pub runtime_attestation: Option<RuntimeAttestationEvidence>,
    pub call_chain: Option<GovernedCallChainContext>,
    pub autonomy: Option<GovernedAutonomyContext>,
    pub context: Option<serde_json::Value>,
}

// Note the casing switch: MeteredBillingContext renames its own fields
// to camelCase, so the block nested under the snake_case metered_billing
// key serializes as settlementMode / maxBilledUnits.
#[serde(rename_all = "camelCase")]
pub struct MeteredBillingContext {
    pub settlement_mode: MeteredSettlementMode,
    pub quote: MeteredBillingQuote,
    /// Optional explicit upper bound on billable units for the request.
    pub max_billed_units: Option<u64>,
}

MeteredSettlementMode

VariantWire nameConfiguration
MustPrepaymust_prepayAction MUST NOT execute unless the quoted amount is prepaid.
HoldCapturehold_captureAction MAY execute against a hold and settle later via capture or release.
AllowThenSettleallow_then_settleAction MAY execute first and settle later with truthful pending state.

MeteredBillingQuote

chio-core-types/src/capability/governance.rs
#[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 (e.g. 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.
    pub expires_at: Option<u64>,
}

impl MeteredBillingQuote {
    pub fn is_valid_at(&self, now: u64) -> bool {
        now >= self.issued_at
            && self.expires_at.is_none_or(|expires_at| now < expires_at)
    }
}

Quote Validity Windows

The kernel calls is_valid_at(now) before applying the quote. Quotes with no expires_at remain valid indefinitely (subject to the issuing provider's revocation), but a quote with an expiry that has passed is rejected and the agent must obtain a fresh quote.


Three Cost Layers

Pricing decisions flow through three distinct values. They live in different places and serve different roles.

LayerSourceRole
Quoted costMeteredBillingQuote.quoted_costPre-execution estimate from the metering provider, bound to the intent.
Observed costTool server post-execution metering payloadWhat the tool actually consumed (token count, bytes, etc.) translated to monetary units.
Charged costReceipt metadata, capped by capability budgetWhat the kernel actually deducted, after applying budget caps and max_billed_units.

These three values are reconciled after settlement. See Reconciliation for the full flow.


Budget Caps on the Capability Grant

The capability grant carries the runtime ceiling. Two fields on ToolGrant bound how much a single grant can spend.

FieldTypeEffect
max_cost_per_invocationOption<MonetaryAmount>Per-call ceiling. Rejected if a quote or receipt charges more.
max_total_costOption<MonetaryAmount>Aggregate ceiling across all invocations under this grant.
max_invocationsOption<u32>Maximum number of invocations under this grant.

Where the kernel actually enforces

Manifest pricing is operator input, not enforcement. The kernel enforces capability caps. Set max_cost_per_invocation consistent with the advertised price plus a local safety margin, so a tool server that quietly raises its price loses the call instead of overrunning the budget.

Cross-Currency Settlement

When the budget is denominated in one currency and the quote in another, the kernel needs an exchange rate. Chio sources rates from oracle integrations and records the source on the receipt. See Chainlink integration for the supported feed interface.

  • The agent or authority requests a conversion at intent time. The kernel records the source feed, the round id, and the rate used.
  • Receipts carry an oracle_evidence field naming the feed and the conversion that was applied. Auditors can re-verify against the same feed at the same round.
  • A stale or unreachable feed fails closed; the kernel refuses to invent a rate.

Worked Example: Per-Unit Pricing with a Quote

A summarization tool charges 5 cents per 1,000 tokens. The operator publishes the manifest, an authority issues a capability with a USD 5.00 ceiling, and the agent requests a quote before the call.

1. Publish the Pricing Block

manifest-pricing-fragment.json
{
  "name": "summarize",
  "description": "Returns a model-generated summary",
  "input_schema": { "...": "..." },
  "pricing": {
    "pricing_model": "per_unit",
    "unit_price":   { "units": 5, "currency": "USD" },
    "billing_unit": "1k_tokens"
  },
  "has_side_effects": false,
  "latency_hint": "moderate"
}

2. Issue a Capability with a Ceiling

capability-grant.json
{
  "tool_grant": {
    "server_id": "srv-summary",
    "tool_name": "summarize",
    "operations": ["invoke"],
    "max_invocations": 50,
    "max_cost_per_invocation": { "units": 500, "currency": "USD" },
    "max_total_cost":          { "units": 50000, "currency": "USD" }
  }
}

3. Obtain a Quote

Before invoking, the agent asks its metering provider for a pre-execution quote. The provider issues a stable MeteredBillingQuote with quoted_units = 8 (eight thousand-token blocks) and quoted_cost = USD 0.40.

4. Bind the Quote to the Intent

governed-intent.json
{
  "id": "intent-2026-04-28-001",
  "server_id": "srv-summary",
  "tool_name": "summarize",
  "purpose": "draft summary for ticket #3120",
  "max_amount": { "units": 500, "currency": "USD" },
  "metered_billing": {
    "settlementMode": "hold_capture",
    "quote": {
      "quoteId": "q-2026-04-28-991",
      "provider": "metering.example",
      "billingUnit": "1k_tokens",
      "quotedUnits": 8,
      "quotedCost": { "units": 40, "currency": "USD" },
      "issuedAt": 1714287000,
      "expiresAt": 1714287600
    },
    "maxBilledUnits": 12
  }
}

5. Dispatch and Settle

The kernel verifies the quote validity window, confirms the capability ceiling covers the quote, places a hold for USD 0.40, dispatches the call, and signs a receipt. Post-execution the metering provider observes nine thousand-token blocks; the tool reports observed cost USD 0.45. The kernel captures up to max_billed_units = 12, in this case the actual nine units, and records the charged cost on the receipt.

rendering…
Agent obtains a metered billing quote, binds it to the governed transaction intent, kernel verifies validity and capability ceiling, places hold, dispatches the call, captures actual usage on settlement.

Failure Modes

  • Stale quote: quote expires_at has passed before dispatch. Kernel refuses; agent obtains a fresh quote.
  • Quoted cost exceeds capability ceiling: rejected at intent verification with a budget error.
  • Observed cost exceeds max_billed_units: the kernel charges the cap, marks the receipt with overrun metadata, and pauses further dispatch under the same grant until reconciliation.
  • Currency mismatch with no oracle: a USD budget against an EUR quote without a configured rate source fails closed.
  • Provider unknown: a quote signed by a metering provider absent from the authority's trusted set is rejected.

In the Procurement Tour

This is station 3 of the Procurement Tour: buyer wraps Vanguard's quote in a GovernedTransactionIntent with a metered-billing block.

Picks up from previous station. The buyer kernel has admitted Vanguard's signed manifest for the soc2-review tool and has its advertised ToolPricing in hand.

Lattice issues an MCP request_quote for 1000 evidence rows. Vanguard returns a quote bound to a five-minute validity window. The buyer kernel pins it as a MeteredBillingContext on the governed intent. The settlement configuration is hold_capture: an escrow hold lands before the tool runs and settles by capture or release based on observed usage.

chio-core-types/src/capability/governance.rs
#[serde(rename_all = "snake_case")]
pub enum MeteredSettlementMode {
    MustPrepay,
    HoldCapture,
    AllowThenSettle,
}
lattice-soc2-review.governed-intent.json
{
  "id": "intent-soc2-review-001",
  "server_id": "vanguard-security",
  "tool_name": "soc2-review",
  "purpose": "SOC 2 evidence review for Q2 release window",
  "max_amount": { "units": 110, "currency": "USD" },
  "metered_billing": {
    "settlementMode": "hold_capture",
    "quote": {
      "quoteId": "quote_vanguard_soc2_001",
      "provider": "did:chio:c87a...",
      "billingUnit": "evidence-row",
      "quotedUnits": 1000,
      "quotedCost": { "units": 100, "currency": "USD" },
      "issuedAt": 1745870400,
      "expiresAt": 1745870700
    },
    "maxBilledUnits": 1100
  }
}

The buyer kernel computes binding_hash() over the intent. That hash anchors the next station's federation resolution, the dispatch, and both sides of the receipt pair.

Continue at next station, where the buyer kernel resolves Vanguard as a pinned federation peer before issuing the call.