Freeze, authorize, settle, execute
Both materialize and read use the same handshake:
- Request the unpaid work with its scope and window.
- On
payment_required, read the quote ID, itemizedlines, server-setamount, andaccepts. - Confirm that spending is authorized for this scope and amount. Present unresolved choices to the operator. Mock payments follow the same consent workflow.
- Settle with
pay_quoteusing the frozen quote ID and a payload for an advertised rail. - Save the payment ID and receipt. Invoke the original verb with only
payment_id.
A quote is not the result; a settlement receipt is not the result; an accepted job is not necessarily completed data.
The quote clock
Every quote expires 120 seconds after freeze, whether paid or unpaid. Pay and start execution within that interval. Repeating a pending request does not extend the clock. After expiry, request a new quote; inspect prior work and settlements first to avoid duplicate spending. An already-started paid background job continues after ticket expiry.
Amounts and rails are discovered
Use inspect subject:pricing for published meters and the actual quote for this operation's price. Do not hardcode rates, payment networks, contracts, or pay-to addresses from an example. Chain of computation and payment network are separate choices.
The real-payment payload is a signed x402 v2 object serialized as JSON text in pay_quote.payload. It is not a base64 blob, a private key, or a custom amount field. Follow the server's payment instructions and selected accepts row. Omit the payload only when the deployment explicitly uses mock settlement.
Batch settlement
For an offered batch rail, inspect subject: "channels" with the payer address and optional advertised CAIP-2 network. Reuse eligible open channel state according to the server's instructions. A first deposit and a later voucher are different actions. Obtain authorization for the full deposit commitment, not just the small individual query price.
Channel fields such as balances and cumulative amounts are decimal strings. Keep precise integer arithmetic. Withdrawal is a separate on-chain escrow workflow; Testril has no MCP withdrawal tool. Use the delay and contract details advertised by the live service.
Materialize pricing and retries
Materialize buys unpaid holes, excluding durable coverage and open paid ranges. extra_cache_days > 0 adds retention beyond the included stamp. Read has its own query pricing; cached computation does not imply free reads.
For a Function that carries state across blocks, materialization is quoted, billed, and walked from its contract's creation block. Read the actual frozen window and line items; a later requested start does not remove that prerequisite work.
Paid materialization starts an asynchronous job. Inspect the returned job until done or failed, and reconcile its error and refund records before retrying. Do not blanket-repay every error or assume a settlement receipt means the data is complete.
Agent expense record
Log quote scope, lines, amount, rail, time frozen, settlement state/reference, payment ID, job ID, and final coverage. Log signed payloads only under the operator's security policy; avoid leaking keys or reusable authorizations into ordinary diagnostic output.