Chio/Docs

Metering Spec

The metering specification defines per-receipt cost attribution, cumulative budget enforcement, billing-compatible export, and operator query tools. Every tool invocation can carry cost metadata describing the resources consumed: compute time, data volume, monetary API cost, and custom dimensions.

Source

This page normatively reflects spec/METERING.md in the chio repository. Status: Normative. Version 1.0.

Implementation requirement

Implementations MUST support the cost dimensions, budget enforcement semantics, billing export formats, and query interface described here.

Cost Dimensions

Each receipt MAY carry zero or more cost dimensions. The following dimension types are defined:

CostDimension

VariantFieldsDescription
ComputeTimeduration_ms: u64Wall-clock compute time in milliseconds
DataVolumebytes_read: u64, bytes_written: u64Data volume transferred in bytes
ApiCostamount: MonetaryAmount, provider: stringMonetary cost charged by an upstream API
Customname: string, value: u64, unit: string?Extensibility dimension with a numeric value

MonetaryAmount

FieldTypeDescription
unitsu64Cost in minor currency units (e.g., cents for USD)
currencystringISO 4217 currency code (e.g., "USD", "EUR")

The Custom variant allows operators to track domain-specific metrics (e.g., token counts, request counts) without modifying the protocol.

CostMetadata

Per-receipt cost metadata. Serialized as JSON and stored in the receipt's metadata field under the "cost" key.

FieldTypeRequiredDescription
schemastringYesMUST be "chio.cost-metadata.v1"
receipt_idstringYesReceipt ID this cost belongs to
timestampu64YesUnix timestamp (seconds) of the receipt
session_idstringNoSession that produced this receipt
agent_idstringYesAgent that made the invocation
tool_serverstringYesTool server that handled the invocation
tool_namestringYesTool that was invoked
dimensionsCostDimension[]YesIndividual cost measurements
total_monetary_costMonetaryAmountNoAggregate monetary cost across ApiCost dimensions

Total Monetary Cost Computation

The total_monetary_cost field is computed by summing all ApiCost dimension amounts. Implementations MUST use saturating addition to prevent overflow.

When multiple ApiCost dimensions use different currencies, only amounts in the first currency encountered are summed. Cross-currency amounts require oracle conversion and are excluded from the automatic total. Implementations SHOULD document this behavior to operators.

When no ApiCost dimensions are present, total_monetary_cost MUST be null.


Budget Enforcement

Budget enforcement tracks cumulative spending and rejects invocations that would exceed configured limits. Enforcement is fail-closed: any error during budget evaluation MUST deny the request.

BudgetPolicy

FieldTypeRequiredDescription
max_totalMonetaryAmountYesMaximum total spending across all dimensions
max_per_sessionMonetaryAmountNoPer-session spending limit
max_per_agentMonetaryAmountNoPer-agent spending limit
max_per_toolmap[string, MonetaryAmount]NoPer-tool limits; key format "server:tool"
currencystringYesCurrency for budget enforcement

Enforcement Semantics

Budget checks evaluate in the following order. The first violation encountered MUST be returned:

  • Total budget: total_spent + cost > max_total.units
  • Per-session budget: session_spent + cost > max_per_session.units
  • Per-agent budget: agent_spent + cost > max_per_agent.units
  • Per-tool budget: tool_spent + cost > max_per_tool[key].units

All arithmetic MUST use saturating addition. Overflow MUST saturate to u64::MAX rather than wrapping.

A cost of zero MUST always pass budget checks regardless of current spending levels.

BudgetViolation

When a budget check fails, the enforcer MUST return a typed violation:

VariantFieldsDescription
Totallimit_units, current_units, requested_units, currencyTotal budget exceeded
Sessionsession_id, limit_units, current_units, requested_units, currencyPer-session budget exceeded
Agentagent_id, limit_units, current_units, requested_units, currencyPer-agent budget exceeded
Tooltool_key, limit_units, current_units, requested_units, currencyPer-tool budget exceeded

Recording

After a tool invocation succeeds and the receipt is signed, the enforcer records the cost against all applicable counters (total, session, agent, tool). Recording uses saturating addition.

The record operation does not enforce limits; it only updates tracking counters. Budget enforcement happens exclusively in the check operation before invocation.


Billing Export

Billing export transforms Chio cost metadata into flat, denormalized records suitable for ingestion by external billing systems.

BillingRecord

FieldTypeDescription
schemastringMUST be "chio.billing-export.v1"
receipt_idstringReceipt ID
timestampu64Unix timestamp (seconds)
timestamp_isostringISO 8601 timestamp in UTC (e.g., "2023-11-14T22:13:20Z")
session_idstringSession ID (nullable)
agent_idstringAgent that triggered the cost
tool_serverstringTool server
tool_namestringTool name
compute_time_msu64Total compute time in milliseconds
data_bytesu64Total data transferred in bytes
cost_unitsu64Monetary cost in minor units (nullable)
currencystringISO 4217 currency code (nullable)
providerstringUpstream provider (nullable)

All timestamps MUST use ISO 8601 format with UTC timezone and Z suffix. Implementations MUST fall back to "unix:<timestamp>" when the Unix timestamp cannot be converted to a calendar date.

BillingExport

A batch of billing records.

FieldTypeDescription
schemastringMUST be "chio.billing-export.v1"
exported_atu64Unix timestamp when the export was created
record_countu64Total number of records in this export
total_costMonetaryAmountAggregate cost (null if mixed currencies)
recordsBillingRecord[]The billing records

When records contain costs in multiple currencies, total_cost MUST be null rather than summing incompatible amounts.

Export Formats

Implementations MUST support JSON export. Implementations SHOULD support CSV export. CSV output MUST use the same field names as the JSON schema with one record per row and a header line.


Query Interface

The query interface supports cost aggregation across multiple dimensions.

CostQuery

All filter fields are optional. When omitted, the filter matches all records. Multiple filters are ANDed together.

FieldTypeDescription
session_idstringFilter by session ID
agent_idstringFilter by agent ID
tool_serverstringFilter by tool server
tool_namestringFilter by tool name
sinceu64Start of time range, inclusive (Unix seconds)
untilu64End of time range, exclusive (Unix seconds)
currencystringOnly include costs in this currency
limitusizeMaximum detailed records to return
group_byGroupByAggregation dimension

GroupBy

ValueDescription
noneNo grouping; return individual receipt costs
sessionGroup by session ID
agentGroup by agent ID
toolGroup by tool key ("server:tool_name")

CostQueryResult

FieldTypeDescription
summaryCostSummaryAggregate statistics across all matching records
groupsCostGroup[]Grouped rows (empty when group_by is none)
truncatedboolWhether the result was truncated due to limit

CostSummary

FieldTypeDescription
receipt_countu64Total matching receipts
total_compute_time_msu64Aggregate compute time
total_data_bytesu64Aggregate data volume
total_monetary_costMonetaryAmountAggregate cost (null if mixed currencies)
distinct_agentsu64Number of distinct agents
distinct_toolsu64Number of distinct tools

CostGroup

FieldTypeDescription
keystringGroup key (session ID, agent ID, or "server:tool")
receipt_countu64Receipts in this group
total_compute_time_msu64Compute time for this group
total_data_bytesu64Data volume for this group
total_monetary_costMonetaryAmountCost for this group (null if mixed currencies)

Limits

The maximum number of records returned by a single query MUST NOT exceed 500. When the matching set exceeds the limit, the result MUST set truncated to true and return only the first limit records. The operator-provided limit is capped at the system maximum of 500.