Chio/Docs

Pricing Models & SLAs

Tools advertise prices in their signed manifests. Authorities issue budgets on capability tokens. The kernel runs at dispatch time and decides whether the budget covers the next call at the advertised price. For tools that need pre-execution reservation or post-execution settlement, a metered billing block on the governed transaction intent ties the call to a quote with an explicit settlement posture.

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.

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.

chio-core-types/src/capability.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.

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 an explicit settlement posture.

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

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 namePosture
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.rs
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 surface.

  • 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": {
    "settlement_mode": "hold_capture",
    "quote": {
      "quote_id": "q-2026-04-28-991",
      "provider": "metering.example",
      "billing_unit": "1k_tokens",
      "quoted_units": 8,
      "quoted_cost": { "units": 40, "currency": "USD" },
      "issued_at": 1714287000,
      "expires_at": 1714287600
    },
    "max_billed_units": 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 posture is hold_capture: an escrow hold lands before the tool runs and settles by capture or release based on observed usage.

crates/chio-core-types/src/capability.rs
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": {
    "settlement_mode": "hold_capture",
    "quote": {
      "quote_id": "quote_vanguard_soc2_001",
      "provider": "did:chio:c87a...",
      "billing_unit": "evidence-row",
      "quoted_units": 1000,
      "quoted_cost": { "units": 100, "currency": "USD" },
      "issued_at": 1745870400,
      "expires_at": 1745870700
    },
    "max_billed_units": 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.

Pricing Models & SLAs · Chio Docs