Chio/Docs

Worked Example: Agent Commerce Network

One transaction, end to end. Lattice Platform Security needs a security review for its payments API. Vanguard Security provides reviews via a governed MCP tool server. A procurement agent reasons about scope, evaluates a quote, and runs the job. Chio governs every step and signs the evidence.

Where the code lives

The full example sits in examples/agent-commerce-network/. Snippets on this page are quoted from that source. Run it with cargo build --bin chio && ./smoke.sh. Set OPENAI_API_KEY for a live agent loop, or leave it unset for the deterministic fallback used in CI.

The Cast

  • Buyer: lattice-platform-security. Runs a FastAPI procurement service behind chio api protect.
  • Provider: vanguard-security. Runs an MCP tool server behind chio mcp serve-http.
  • Trust control: an authority that issues capabilities, tracks budgets, and projects financial reports.
  • Procurement agent: an OpenAI Agents SDK or Anthropic SDK loop that picks a scope, accepts a quote, and approves a job when needed.
rendering…
One procurement transaction. The buyer kernel and provider kernel each sign their own receipts; both bind to the same governed intent hash.

Step 1: Buyer Issues a Capability with a Budget

The orchestrator asks trust control for a capability. The token carries two grants: a free read for quote requests, and a budgeted write grant for job creation. The budget cap is denominated in USD minor units (cents).

examples/agent-commerce-network/orchestrate.py
def _usd(cents: int) -> dict:
    return {"units": cents, "currency": "USD"}

cap = trust.issue_capability(
    subject_pk="00" * 32,
    scope={
        "grants": [
            {"server_id": "http-sidecar-client",
             "tool_name": "procurement_quote_read",
             "operations": ["invoke"], "constraints": []},
            {"server_id": "http-sidecar-client",
             "tool_name": "procurement_job_write",
             "operations": ["invoke"], "constraints": [],
             "maxInvocations": 3,
             "maxCostPerInvocation": _usd(args.budget_minor),
             "maxTotalCost": _usd(args.budget_minor)},
        ],
        "resource_grants": [], "prompt_grants": [],
    },
    ttl=3600,
)

The default budget is 90,000 cents (USD 900.00). The grant uses the three-tier shape from Economics: maxInvocations, maxCostPerInvocation, maxTotalCost.


Step 2: Buyer Reads the Provider Manifest

Vanguard's tool server publishes a manifest declaring the review tools it exposes. The agent learns the input schema for request_quote from the manifest. In production the wire form is SignedManifest (declared in chio-manifest), with an Ed25519 signature over the canonical JSON encoding of ToolManifest. The kernel verifies the signature against the server's registered public key before admitting the tool. Pricing rides on the same artifact as a ToolPricing entry on each ToolDefinition.

Pricing is advisory on the manifest

The manifest declares advertised pricing. The contract a buyer binds to is the per-call quote returned by request_quote, captured as a MeteredBillingQuote on the next governed intent. See Manifests and Pricing.

Step 3: Agent Asks for a Quote

The agent calls the buyer's procurement service, which proxies into the provider via MCP. The quote response carries price, currency, and an approval_required flag.

examples/agent-commerce-network/provider/review_server.py
price_minor = {
    "hotfix-review": 45_000,
    "release-review": 125_000,
    "release-plus-cloud-review": 175_000,
    "full-estate-review": 325_000,
}.get(scope, template["price_minor"])
template.update({
    "quote_id": random_id("quote"),
    "price_minor": price_minor,
    "approval_required": price_minor > APPROVAL_THRESHOLD_MINOR,
    "pricing_basis": f"bounded {scope} for {arguments['target']}",
})

A typical quote response:

examples/agent-commerce-network/contracts/quote-response.json
{
  "quote_id": "quote_vanguard_001",
  "request_id": "quote_req_lattice_001",
  "service_family": "security-review",
  "offer_id": "release-review",
  "price_minor": 125000,
  "currency": "USD",
  "approval_required": true,
  "estimated_delivery_hours": 48,
  "pricing_basis": "bounded release review for one release window"
}

The buyer caches the quote keyed by quote_id for the duration of the procurement.


Step 4: Agent Assembles a GovernedTransactionIntent

To bind the quote to a specific action, the buyer wraps it in a GovernedTransactionIntent with a MeteredBillingContext. The intent has a stable hash that both kernels can co-sign against.

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 metered_billing: Option<MeteredBillingContext>,
    // call_chain, autonomy, runtime_attestation, commerce, context ...
}

pub struct MeteredBillingContext {
    pub settlement_mode: MeteredSettlementMode,
    pub quote: MeteredBillingQuote,
    pub max_billed_units: Option<u64>,
}

pub struct MeteredBillingQuote {
    pub quote_id: String,
    pub provider: String,
    pub billing_unit: String,
    pub quoted_units: u64,
    pub quoted_cost: MonetaryAmount,
    pub issued_at: u64,
    pub expires_at: Option<u64>,
}

pub enum MeteredSettlementMode { MustPrepay, HoldCapture, AllowThenSettle }

The buyer's kernel computes the intent hash with GovernedTransactionIntent::binding_hash(). That hash anchors approval tokens, receipts, and the matching provider-side receipt to the same governed action.

Three settlement postures

MustPrepay requires funds in escrow before the tool runs. HoldCapture places a hold and settles by capture or release. AllowThenSettle lets the action run first and reconciles after, with truthful Pending status on the receipt. The example uses the third mode through the authorize-exposure / reconcile-spend flow.

Step 5: Buyer Kernel Pre-Charges the Budget

Before the provider tool runs, the buyer's kernel debits the worst-case cost from the running grant total. Trust control exposes three split-budget endpoints: /v1/budgets/authorize-exposure reserves a worst-case amount, /v1/budgets/release-exposure releases a reservation when the action will not run, and /v1/budgets/reconcile-spend finalizes after dispatch with actual cost. If the pre-charge would breach maxTotalCost or maxInvocations, the kernel denies the call. The buyer service surfaces that as denied_budget:

examples/agent-commerce-network/buyer/app.py
if budget_minor < quote["price_minor"]:
    job["status"] = "denied_budget"
    job["denial_reason"] = "requested work exceeds the buyer budget envelope"
elif quote["approval_required"]:
    job["status"] = "pending_approval"
else:
    self._execute_job(job)

For high-priced scopes (above 100,000 cents in this example), the provider flips approval_required on the quote. The agent has to call approve_job with a reason before the dispatch proceeds.


Step 6: Provider Kernel Verifies and Dispatches

The buyer issues an MCP tools/call with the capability presented in the X-Chio-Capability header. The provider edge (chio mcp serve-http) verifies the capability and runs its guard pipeline before forwarding into execute_review:

examples/agent-commerce-network/commerce_network/agents.py
headers: dict[str, str] = {"Authorization": f"Bearer {auth_token}"}
if cap_header:
    headers["X-Chio-Capability"] = cap_header
r = http.post(f"{buyer_url}{path}", headers=headers, json=body)

The tool returns a fulfillment package. The provider kernel signs a receipt that records the action, the cost, and the guard evidence. Both kernels use the same governed intent hash as the binding anchor, which is what makes the pair of receipts a bilateral artifact.


Step 7: Bilateral Receipts and Cost Charged

Each kernel produces a receipt with FinancialReceiptMetadata (grant index, cost charged, currency, remaining and total budget, delegation depth, root budget holder, payment reference, settlement status, optional cost breakdown, oracle evidence, and attempted cost on denials; full struct in chio-core-types/src/receipt.rs). Buyer-side metadata after dispatch (illustrative):

buyer-receipt.json
{
  "financial": {
    "grant_index": 1,
    "cost_charged": 125000,
    "currency": "USD",
    "budget_remaining": 25000,
    "budget_total": 150000,
    "delegation_depth": 0,
    "root_budget_holder": "lattice-platform-security",
    "payment_reference": "settlement_lattice_vanguard_001",
    "settlement_status": "pending"
  },
  "governed_transaction": {
    "intent_id": "intent-job-001",
    "intent_hash": "sha256:...",
    "server_id": "vanguard-security",
    "tool_name": "execute_review",
    "metered_billing": {
      "settlement_mode": "allow_then_settle",
      "quote": {
        "quote_id": "quote_vanguard_001",
        "billing_unit": "review",
        "quoted_units": 1,
        "quoted_cost": { "units": 125000, "currency": "USD" }
      }
    }
  }
}

Two receipts, one binding

The provider kernel writes a corresponding receipt under its own kernel key. Both share intent_hash. A regulator or counterparty can verify either side independently and confirm the pair lines up. Bilateral Receipts covers the verification flow.

Step 8: Reconciliation

The pre-charge reserved the worst-case cost. After dispatch, the kernel calls /v1/budgets/reconcile-spend with the actual cost from ToolInvocationCost. If actual is less than charged, the difference is credited back; if equal, no adjustment; if greater, the receipt's settlement_status is set to Failed and the overrun is recorded. See Reconciliation.


Step 9: Settlement

Once reconciliation is final, settlement dispatches over the configured rail. In the example the rail is stub-mocked and returns a synthetic settlement-reconciliation record. The shape is:

examples/agent-commerce-network/contracts/settlement-reconciliation.json
{
  "settlement_id": "settlement_lattice_vanguard_001",
  "job_id": "job_lattice_001",
  "quoted_amount_minor": 125000,
  "approved_amount_minor": 125000,
  "settled_amount_minor": 125000,
  "currency": "USD",
  "status": "reconciled",
  "buyer_position": "accepted",
  "provider_position": "accepted"
}

In a production deployment the settlement layer drives one of the rails declared in chio-settle: EVM escrow via PreparedEvmCall, Solana via PreparedSolanaSettlement, cross-chain CCIP via CcipSettlementMessage, or HTTP-native rails via X402PaymentRequirements and Circle nanopayments. The receipt's payment_reference field carries the rail-level identifier; the receipt's settlement_status moves from Pending to Settled as confirmation lands.

Watchdogs cover the gap

SettlementWatchdogJob wraps long-running dispatches so a stuck transaction does not leave a receipt forever in Pending. See Settlement Rails and On-chain Settlement.

Step 10: Audit and Reputation Update

The orchestrator pulls financial reports from trust control and writes them into the artifact directory:

examples/agent-commerce-network/orchestrate.py
# -- Financial reports from trust-control --
budget_state = trust.query_budgets(capability_id=cap["id"])
_write(out / "financial" / "budget-usage.json", budget_state)
exposure = trust.exposure_ledger()
_write(out / "financial" / "exposure-ledger.json", exposure)
settlements = trust.settlement_report()
_write(out / "financial" / "settlement-report.json", settlements)

Three reports come out of one transaction: budget usage (grant invocation count and total cost charged; see Economics), exposure ledger (outstanding committed cost; type ExposureLedgerReport, schema chio.credit.exposure-ledger.v1), and a settlement report for rail-level status.

A scorecard update is the natural follow-on. Both sides assemble their own LocalReputationCorpus from persisted receipts and recompute the deterministic scorecard. Nothing in the kernel is shared; both reach a score from the same evidence.


The Full Flow at a Glance

Ten steps, ten artifacts: (1) capability token, (2) signed manifest, (3) metered billing quote, (4) governed transaction intent, (5) pre-charge budget state, (6) fulfillment package, (7) two ChioReceipt records sharing an intent_hash, (8) updated financial receipt metadata, (9) settlement commitment plus rail reference, (10) exposure ledger and scorecard updates.


Failure Paths

Three paths a procurement transaction can fall down. Budget denial: the requested work exceeds the envelope; job status is denied_budget; the pre-charge never lands. Pending approval: the quote exceeds the auto-approval threshold; the agent calls approve_job with a reason before dispatch. Dispute: after fulfillment, the buyer calls dispute_job; the settlement record flips to reversal_pending; adjudication is the entry point into the claims path.


Run It Yourself

From the chio workspace root:

run-smoke.sh
cd examples/agent-commerce-network
cargo build --bin chio
./smoke.sh

# Optional: live agent reasoning
export OPENAI_API_KEY=...
./smoke.sh

# Inspect the artifacts
ls artifacts/live/*/
cat artifacts/live/*/financial/budget-usage.json
cat artifacts/live/*/contracts/settlement-reconciliation.json

Expected output (abbreviated):

smoke-output.txt
[smoke] cargo build --bin chio ... ok
[smoke] starting trust-control on :8001
[smoke] starting buyer on :8002
[smoke] starting provider on :8003
[smoke] orchestrate.py: capability issued, quote received, job dispatched
[smoke] artifacts written to artifacts/live/run-2025-04-28/
budget-usage.json   exposure-ledger.json   settlement-report.json
{"capability_id":"cap_...","grants":[...],"total_charged":125000}
{"settlement_id":"settlement_lattice_vanguard_001","status":"reconciled",...}

The smoke test runs the deterministic fallback when no API key is set, which is what CI uses.

Where to go next

Pricing for how quotes and pricing models compose, Bilateral Receipts for receipt-pair verification, Underwriting for risk and premium, Settlement Rails for the dispatch step, Reconciliation for post-execution accounting.
Worked Example: Agent Commerce Network · Chio Docs