LearnAnatomy of a Governed Call
Budgets & Metering
A capability token can limit both the tools an agent may call and the amount it may spend.
A budget travels with the token through delegation. Each charge records its path to the root budget holder, making the token a spending authorization. Autonomous Commerce introduces that identity. Each charge described here is recorded as a priced, signed receipt; Receipts covers the receipt format.
MonetaryAmount
MonetaryAmount represents money as minor-unit integers with an ISO 4217 currency code:
pub struct MonetaryAmount {
/// Value in the currency's minor unit (e.g., cents for USD).
pub units: u64,
/// ISO 4217 currency code (e.g., "USD", "EUR", "USDC").
pub currency: String,
}Monetary values use u64minor units. Budget calculations do not use floating-point values.
The meaning of one unit depends on the currency:
| Currency | 1 unit equals | Minor units per major unit |
|---|---|---|
USD | 1 cent | 100 |
EUR | 1 cent | 100 |
GBP | 1 penny | 100 |
JPY | 1 yen | 1 |
USDC / USDT | 1 micro-dollar | 106 |
BTC | 1 satoshi | 108 |
ETH | 1 wei | 1018 |
Integer amounts
u64 micro-USDC. BTC uses 108 satoshis. EUR is 2 decimals. Floating-point numbers do not appear in the budget path.Three-tier budget model
Each ToolGrant in a capability token carries up to three independent budget constraints: per-invocation (max_cost_per_invocation), per-grant total (max_total_cost), and an invocation count cap (max_invocations). All three are optional and can be combined freely:
The kernel enforces all three limits atomically before the tool runs. If any limit would be exceeded, the call is denied and a receipt is produced with the attempted cost recorded.
grants:
- server_id: srv-ai-inference
tool_name: generate_text
operations: [invoke]
# Per-call cap: no single call can cost more than $0.50
max_cost_per_invocation:
units: 50
currency: USD
# Aggregate cap: total spend cannot exceed $10.00
max_total_cost:
units: 1000
currency: USD
# Call count cap: maximum 200 invocations
max_invocations: 200Independent limits
max_invocations creates a free-tier with a call count limit. Setting only max_total_cost creates a pay-per-use budget with no per-call cap.Budget enforcement flow
The budget lifecycle has four operations: authorize, capture, release, and reconcile. The kernel reserves cost before dispatch, captures the tool's reported cost on success, and reconciles the reservation afterward. If a call is denied after authorization or does not run, it releases the reserved amount. The phases below show the success path.
Phase 1: authorize
Before the tool executes, the kernel calls check_and_increment_budget(). This function atomically:
- Increments the invocation count and checks it against
max_invocations - Debits the worst-case cost (
max_cost_per_invocation) from the running total and checks it againstmax_total_cost
If either check fails, the kernel denies the call before tool code runs. Authorization reserves the maximum max_cost_per_invocation before the tool runs.
Phase 2: capture
The tool executes. On success the kernel captures the actual cost the tool reports via ToolInvocationCost; if the call fails, the hold is released and nothing is charged:
pub struct ToolInvocationCost {
/// Actual cost in minor units.
pub units: u64,
/// ISO 4217 currency code.
pub currency: String,
/// Optional cost breakdown as an arbitrary JSON value (tool-defined keys).
pub breakdown: Option<serde_json::Value>,
}The breakdown field allows tools to itemize costs: for example, separating compute, I/O, and network charges. Keys are tool-defined and the shape is opaque JSON, which the kernel copies through into the financial receipt for auditability.
Phase 3: reconcile
After the tool returns, the kernel calls finalize_budgeted_tool_output_with_cost_and_metadata() to reconcile the authorized amount with the actual cost. It takes the request, the tool output, the elapsed time, the timestamp, the matched grant index, and a FinalizeToolOutputCostContext (the charge result, the reported cost, the payment authorization, and the cap). When there was no budget charge to reconcile, an unbudgeted call, it falls back to the plain finalize_tool_output_with_metadata path. When there was, it settles the difference:
- Actual < charged: the difference is credited back to the budget
- Actual > charged: a cost overrun has occurred;
settlement_statusis set toFailedand the overrun is recorded in the receipt - Actual = charged: exact match, no adjustment needed
Guard failure after authorize
reverse_budget_charge() to fully reverse the debit. The agent is not charged for a tool call that never executed.Financial receipt metadata
Every tool invocation that exercises a monetary grant produces a FinancialReceiptMetadata record embedded in the receipt's metadata field. This struct captures the complete economic state of the transaction:
pub struct FinancialReceiptMetadata {
/// Index of the grant within the capability token.
pub grant_index: u32,
/// Actual cost charged (after reconciliation).
pub cost_charged: u64,
/// Currency of the charge.
pub currency: String,
/// Budget remaining after this invocation.
pub budget_remaining: u64,
/// Total budget for the grant.
pub budget_total: u64,
/// Depth in the delegation chain (0 = root).
pub delegation_depth: u32,
/// Identity of the root budget holder.
pub root_budget_holder: String,
/// External payment reference for settlement.
pub payment_reference: Option<String>,
/// Settlement status of this charge.
pub settlement_status: SettlementStatus,
/// Itemized cost breakdown from the tool, as an arbitrary JSON value.
/// Keys are tool-defined.
pub cost_breakdown: Option<serde_json::Value>,
/// Oracle conversion evidence (for cross-currency).
pub oracle_evidence: Option<OracleConversionEvidence>,
/// Cost that was attempted (present in denial receipts).
pub attempted_cost: Option<u64>,
}The SettlementStatus enum tracks the lifecycle of the financial transaction:
pub enum SettlementStatus {
/// No monetary cost (e.g., free-tier grant).
NotApplicable,
/// Cost recorded, awaiting settlement.
Pending,
/// Settlement completed successfully.
Settled,
/// Settlement failed (e.g., cost overrun).
Failed,
}Budget hold lineage
FinancialReceiptMetadata is the settled summary. Underneath it, the authorize path records the budget hold itself. When check_and_increment_budget authorizes a charge it opens a hold via authorize_budget_hold, and three sibling records capture that hold's lineage on the receipt:
FinancialBudgetHoldAuthorityMetadata: the authority behind the hold:authority_id,lease_id,lease_epoch.FinancialBudgetAuthorizeReceiptMetadata: the authorize step:exposure_unitsand thecommitted_cost_units_afterthe hold was opened.FinancialBudgetTerminalReceiptMetadata: the terminal step: the hold'sdisposition, therealized_spend_units, and the committed total after reconcile.
Together, these records identify the hold authority, authorization, and terminal reconciliation.
Here is a complete receipt with financial metadata for a tool call that cost $1.50 against a $10.00 budget:
{
"id": "rcpt-econ-001",
"timestamp": 1710000100,
"capability_id": "cap-budget-001",
"tool_server": "srv-ai-inference",
"tool_name": "generate_text",
"action": {
"parameters": {
"prompt": "Summarize this document",
"max_tokens": 500
},
"parameter_hash": "sha256:7f3a9b..."
},
"decision": {
"verdict": "allow"
},
"receipt_kind": "mediated_decision",
"boundary_class": "prevent",
"tool_origin": "caller_executed",
"redaction_mode": "none",
"content_hash": "sha256:c4d5e6f7...",
"policy_hash": "abc123def456",
"evidence": [
{"guard_name": "forbidden-path", "verdict": true, "details": null},
{"guard_name": "path-allowlist", "verdict": true, "details": null},
{"guard_name": "shell-command", "verdict": true, "details": null},
{"guard_name": "egress-allowlist", "verdict": true, "details": null},
{"guard_name": "mcp-tool", "verdict": true, "details": null},
{"guard_name": "secret-leak", "verdict": true, "details": "no secrets detected"},
{"guard_name": "patch-integrity", "verdict": true, "details": null},
{"guard_name": "velocity", "verdict": true, "details": null}
],
"metadata": {
"financial": {
"grant_index": 0,
"cost_charged": 150,
"currency": "USD",
"budget_remaining": 850,
"budget_total": 1000,
"delegation_depth": 0,
"root_budget_holder": "agent-orchestrator-001",
"payment_reference": "pay-ref-abc123",
"settlement_status": "pending",
"cost_breakdown": {
"compute": 120,
"io": 30
},
"oracle_evidence": null,
"attempted_cost": null
}
},
"trust_level": "mediated",
"kernel_key": "9c7b3f2e8a1c4d5b6f0a9e8d7c6b5a4f...",
"signature": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8091a..."
}Cross-currency enforcement
A capability token's budget may be denominated in one currency while a tool reports its cost in another. For example, a grant with a USD budget invoking a tool that charges in USDC. When this happens, the kernel resolves the exchange rate through an oracle via chio-link before the budget check.
The conversion uses integer arithmetic. The rate is a rate_numerator/rate_denominator pair, and the cost is carried as both original_cost_units (what the tool charged) and converted_cost_units (what the budget was debited). The quote's freshness is bounded explicitly: updated_at records when the feed reported the rate, max_age_seconds caps how stale it may be at use, and cache_age_seconds records how old the cached rate actually was at conversion time.
The conversion evidence is embedded in the receipt as OracleConversionEvidence:
pub struct OracleConversionEvidence {
/// Wire schema id ("chio.oracle-conversion-evidence.v1").
pub schema: String,
/// Base currency of the quoted pair.
pub base: String,
/// Quote currency of the quoted pair.
pub quote: String,
/// Identifier of the oracle authority that issued the quote.
pub authority: String,
/// Exchange-rate numerator (integer representation).
pub rate_numerator: u64,
/// Exchange-rate denominator.
pub rate_denominator: u64,
/// Oracle source identifier.
pub source: String,
/// Address of the price feed the rate was read from.
pub feed_address: String,
/// Timestamp the feed reported the rate.
pub updated_at: u64,
/// Maximum age (seconds) the rate may be at use.
pub max_age_seconds: u64,
/// Age (seconds) of the cached rate at conversion time.
pub cache_age_seconds: u64,
/// Converted cost in the grant currency's minor units.
pub converted_cost_units: u64,
/// Original cost in the tool's charged-currency minor units.
pub original_cost_units: u64,
/// Currency the tool actually charged in.
pub original_currency: String,
/// Currency the grant budget is denominated in.
pub grant_currency: String,
/// Oracle's public key, when the quote is signed.
pub oracle_public_key: Option<PublicKey>,
/// Oracle's signature over the quote, when signed.
pub signature: Option<Signature>,
}Verifying a conversion
oracle_public_key and signature, so the rate can be checked against the oracle's key.Budget attenuation in delegation
When an agent delegates a capability token to a child agent, the economic constraints may be narrowed. The Attenuation enum. Three of its variants govern the budget tiers directly:
| Attenuation Variant | Effect |
|---|---|
Attenuation::ReduceCostPerInvocation | Tightens max_cost_per_invocation on the child token |
Attenuation::ReduceTotalCost | Tightens max_total_cost on the child token |
Attenuation::ReduceBudget | Lowers max_invocations on the child token |
The same enum carries four non-monetary narrowings: RemoveTool and RemoveOperation drop a tool or operation from scope, AddConstraint tightens a tool's parameter constraints, and ShortenExpiry pulls the expiry. Each variant narrows the parent token.
The kernel requires each attenuated value to be less than or equal to the corresponding parent value. Lean 4 proof P1 covers this monotonic attenuation property.
Orchestrator token (root):
max_total_cost: 1000 USD ($10.00)
max_cost_per_invocation: 100 USD ($1.00)
max_invocations: 200
└─ Research agent (delegated):
max_total_cost: 500 USD ($5.00) ← tightened
max_cost_per_invocation: 50 USD ($0.50) ← tightened
max_invocations: 50 ← tightened
└─ Sub-agent (delegated again):
max_total_cost: 100 USD ($1.00) ← tightened further
max_cost_per_invocation: 25 USD ($0.25) ← tightened further
max_invocations: 10 ← tightened furtherChild budgets cannot exceed parent budgets
Budget state persistence
Budget state (the running invocation count and total cost charged) is persisted in a SQLite store. Each budget entry is keyed by the tuple (capability_id, grant_index), ensuring that different grants within the same token have independent budgets.
The store tracks two values per key:
invocation_count: how many times this grant has been exercisedtotal_cost_charged: the running sum of all costs charged against this grant
For high-availability deployments, budget state is replicated across cluster nodes using a deterministic leader with sequence-based replication (per HA_CONTROL_AUTH_PLAN). This avoids last-writer-wins state and maintains monotonic budget accounting through failover.
Atomicity at the store level
check_and_increment_budget() function uses a single SQLite transaction to read the current state, validate against limits, and write the updated state. This prevents race conditions in concurrent invocations against the same grant.Budget guarantee levels
Each budget store uses BudgetGuaranteeLevel to declare the guarantee behind its holds. A store can report ha_linearizable only when a replicated quorum store backs the hold. The enum has four variants:
| Level | What it claims |
|---|---|
single_node_atomic | Hold and reconcile are atomic on one node |
ha_linearizable | The hold is linearizable across a replicated quorum store |
partition_escrowed | The hold is escrowed so a network partition cannot double-spend it |
advisory_posthoc | No enforced hold; spend is recorded after the fact, and is not authorization |
The level accompanies the hold model described above. The kernel authorizes the maximum exposure before the call (the max_cost_per_invocation, or the quoted cost when present), then reconciles the hold to the realized spend after the tool returns. A denial or abort reverses the full hold. The authorize and reconcile records together determine spend. See Authoritative Spend for the receipt field and validation rules, and Reconciliation & Watchdog for the same reconciliation cycle.
Related components
Per-call budgets and the authorize / capture / reconcile cycle support other components. Each charge has a signed receipt linked to its capability and budget lineage:
- Markets.
chio-market,chio-open-market, andchio-listingturn priced tool calls into biddable, listable offers. - Credit and insurance.
chio-creditmodels credit facilities, bonds, scorecards, and exposure ledgers;chio-underwritingturns receipt history into underwriting input. - Settlement and anchoring.
chio-settle,chio-anchor, andchio-web3carry a settled charge onto external and on-chain rails.
This page covers the per-call budget mechanics shared by those components. A signed receipt records the authorization, cost, budget holder, and any oracle rate used for the call. Autonomous Commercedescribes how these records support settlement and underwriting.