Economics
Every tool call can carry a price, and every capability token can carry a budget. Agents never overspend, tool servers get paid the amount they charged, and every cent is accounted for in a signed receipt.
MonetaryAmount
The core economic primitive is MonetaryAmount, a struct that 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,
}Money is u64 integers all the way down. No floats, no rounding errors, no representational ambiguity, no 0.1 + 0.2 != 0.3.
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 |
Integers all the way down
u64 micro-USDC. BTC uses 108 satoshis. EUR is 2 decimals. Floating-point numbers never 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:
All three limits are enforced atomically before tool dispatch. 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: 200All three are independent
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. Setting all three provides maximum control.Budget Enforcement Flow
The kernel enforces budgets through a three-phase cycle that runs for every tool invocation. This cycle ensures that cost is reserved before execution, tracked during execution, and reconciled after execution.
Phase 1: Pre-Charge
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 call is denied immediately. No tool code runs. The pre-charge acts as a pessimistic reservation: it atomically debits the worst-case max_cost_per_invocation before dispatch, assuming the tool will cost the maximum allowed.
Phase 2: Dispatch
The tool executes and reports its actual cost via ToolInvocationCost:
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_tool_output_with_cost() to reconcile the pre-charged amount with the actual cost:
- 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 pre-charge
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,
}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"
},
"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
}
},
"kernel_key": "ed25519:pub:9c7b3f...",
"signature": "ed25519:e5f6a7b8..."
}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 math with a configurable margin expressed in basis points (1 basis point = 0.01%). This margin accounts for exchange rate volatility between the pre-charge and reconciliation phases.
The conversion evidence is embedded in the receipt as OracleConversionEvidence:
pub struct OracleConversionEvidence {
/// Source currency (what the tool charged in).
pub from_currency: String,
/// Target currency (what the grant budget uses).
pub to_currency: String,
/// Exchange rate numerator (integer representation).
pub rate_numerator: u64,
/// Exchange rate denominator.
pub rate_denominator: u64,
/// Margin applied in basis points.
pub margin_bps: u32,
/// Oracle source identifier.
pub oracle_source: String,
/// Timestamp when the rate was fetched.
pub rate_timestamp: u64,
}Auditability by design
Budget Attenuation in Delegation
When an agent delegates a capability token to a child agent, the economic constraints can only be tightened, never loosened. The Attenuation enum provides three cost-specific variants: ReduceCostPerInvocation, ReduceTotalCost, and ReduceMaxInvocations:
| 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::ReduceMaxInvocations | Reduces max_invocations on the child token |
The kernel validates that every attenuated value is less than or equal to the parent's corresponding value. A child token can never widen a budget constraint; this is the monotonic attenuation property proved in Lean 4 as P1.
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 furtherAmplification is impossible
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 is not last-writer-wins and is not eventually consistent; budget guarantees remain monotonic under failover, so a surviving leader never overcounts or under-deducts across a transition.
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.What this lets you build
Per-call pricing, live agent marketplaces, autonomous cross-org spend, and cross-chain settlement all fall out of integer arithmetic plus signed receipts. Nothing else. No invoicing, no accounts-receivable, no end-of-month reconciliation, no vendor whose billing dashboard you have to take on faith. The same artifact that proves the call was authorized also proves what it cost, who owed whom, and which oracle priced it.