← Blog
October 9, 2026 · 15 min

Agentic week: trust, not proof

A Solana payment channel reached production this week where the seller signs the meter. The buyer integrating it did not argue with the design — it wrote its own reader for the channel account and compares what was claimed against what it signed. Three x402 fixes landed the same week doing exactly that: taking the number out of the signed message and reading it from the chain.

Fourteen pull requests merged into x402-foundation/x402 between 2 and 9 October. phdargen authored 4, PhilBot402 and CarsonRoscoe 3 each, mintlify[bot] and notorious-d-e-v 2 each. No release shipped: the newest published packages are still @x402/core 2.28.0 on npm, dated 29 September, Python x402 2.25.0 and Go v2.28.0.

Last week the question was what the client lets the server decide. This week the answer arrived in the same shape four separate times: when two parties disagree about what has already been spent, read it from somewhere neither of them authored.

1. Solana batch-settlement in production, and a buyer that verifies it

The x402 batch-settlement scheme — deposit once into a channel, pay per call with offchain vouchers, claim in batches — is live on Solana mainnet. We probed PayAI's facilitator on 9 October. Its /supported endpoint advertises batch-settlement on solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp with USDC, marked "experimental": true, alongside Base mainnet and two testnets. The published policy is tight: deposits from 10000 to 100000000 atomic units (0.01 to 100 USDC), maxOpenChannels 1,000, maxOpenChannelsPerAccount 10, five deposit attempts per minute, and idleCloseSeconds 259200 — three days. PayAI's documentation calls it "a public preview with bounded channel capacity" and supports "at most four channels per claim transaction."

What makes this worth reading is the buyer side. ClawRouter PR #435, opened 7 October and still open at the time of writing, adds opt-in batch settlement to an agent-side router that pays sol.blockrun.ai per model call. We covered that scheme's trust gap in July and its server-signed mode last week, where the spec says an operator "can take up to the full deposit" without proof it delivered anything.

The PR states the exposure in one line: BlockRun's channels are server-signed, and "the operator can claim up to the whole deposit without another client signature." Then it builds four defences, and they are the interesting part. The trusted-operator list is empty by default, so the scheme is never registered and every call stays on exact unless an operator key is named explicitly. Exposure is capped at one deposit. The channel store is a mode-0600 file written atomically, and a torn file is refused rather than read as empty, because "forgetting the signed cumulative is the one failure that must not happen silently."

The fourth is a claim check. At startup, every ten minutes, and on demand, it reads each channel account directly — owner CHNLxYvVA28MJP9PrFuDXccuoGXAx7jBacfLEkahyGsX, 256 bytes, the settled field as a little-endian u64 at offset 20 — and compares the claimed amount against the highest cumulative that wallet ever signed. If claimed exceeds signed, batch settlement is disabled for the process and the failure is logged loudly. The buyer cannot stop an overclaim, so it detects one, cheaply, from the only record the seller does not write.

One footnote in that PR is a datum about our own product category. The integration calls setSpendControls(false), because @x402/core 2.28 enables client spend controls by default and would refuse every call over one dollar. We verified the default in the published bundle: DEFAULT_MAX_AMOUNT_PER_PAYMENT = "$1". We argued for that cap existing in our spend-controls audit. The first real integration to meet it turned it off, because image and video calls cost more than a dollar.

2. The SDK makes the same move: baseline from the chain

PR #3655 (CarsonRoscoe, merged 2 October, +2,226/-206 across 29 files in Go, TypeScript, Python and the spec) fixes how a batch-settlement server learns how much a channel has already been charged when it has no local record — after a full refund, an idle auto-refund, or a restart. It used to infer that baseline from the client-signed voucher. The payer's own message decided where the meter started.

Now the baseline is the facilitator-verified onchain totalClaimed, the cumulative check runs in AfterVerify, and a request with no totalClaimed is rejected rather than guessed. The facilitator side tightened with it: a non-refund voucher or deposit must advance maxClaimableAmount to at least totalClaimed + amount, where before it only had to exceed totalClaimed. Refund vouchers are exempt and may still equal it. PR #3661 (phdargen, merged 2 October) mirrors the rule on SVM, rejecting vouchers "that do not advance beyond the onchain settled watermark" — the same check ClawRouter wrote by hand.

The sharper rule is in the spec edit. The price used to compute that floor arrives from the resource server, and the EVM binding now says requirements.amount "is supplied by the resource server and MUST NOT be trusted." A facilitator must validate it as a non-negative base-10 integer and return a typed invalid response if it is malformed or negative, rather than throwing or quietly lowering the floor. Both sides of the payment are now untrusted inputs to the only party that touches the chain.

3. auth-capture v1.1 lands, and says what it cannot prove

The two-phase auth-capture scheme — authorize now, capture or void later — got its v1.1 implementation in both SDKs. PR #3203 (phdargen, opened 18 August, merged 6 October, +24,279/-1,287 across 100 files) brings TypeScript to the v1.1 spec. PR #3622 (CarsonRoscoe, merged 5 October, +12,305/-494 across 75 files) adds the Go server and facilitator on top of the base/commerce-payments AuthCaptureEscrow contract, with cross-language end-to-end runs reported passing in both directions over EIP-3009 and Permit2.

We audited the v1.0 flow in August. The v1.1 changes are blunt about what was wrong. extra.autoCapture is rejected outright, replaced by paymentFlow and captureMode. Error reasons move into an invalid_auth_capture_evm_* namespace. The settle target comes from operatorType instead of a getCode probe. Deadlines must be all absolute or all relative. And a collect-only route must now declare captureMode: "deferred", with the old sync default throwing "at enhance time rather than escrowing funds the facilitator will not finalize" — a misconfigured route used to escrow a payer's money that nothing could then capture, leaving it until reclaim after the deadline.

The EVM binding is unusually honest about the delegated operator model. With a non-zero extra.receiverAuthorizer, the facilitator relays both collect and lifecycle calls, and the spec writes down what the server gives up:

Nothing onchain requires an authorizer signature, checks it against the one the server holds, or stops a capture the server never asked for, so the facilitator's own verification is the only gate. [...] Within those bounds it is trust, not proof.

Then the key itself moved. A Go changelog fragment dated 5 October adds facilitator-delegated receiver authorization: a server with no ReceiverAuthorizerSigner sends unsigned charge, capture, void and refund payloads, and "the facilitator signs them after ResolveCallerIdentity authenticates the caller, binding the identity to the paymentInfoHash." A merchant with no key management gets capture and refund for free. The EIP-712 signature standing for the receiver's consent is now produced by whoever authenticated the API call. The same fragment carries a line integrators should underline: an omitted route receiverAuthorizer no longer implies collect-only, and must be set to the zero address explicitly.

4. Coinbase Institute prices the problem, and shows a diagram

On 7 October the Coinbase Institute published "Machine-to-machine payments in the AiFi era", a 20-page paper by Chad Harper, Kevin Leffew, Lincoln Murr and Sam Shoar. Its economic core is a single metric: the minimum viable transaction, defined as the smallest payment whose total processing cost stays at or below 5 percent of its value. Card small-ticket programs land at $1.19, card-not-present credit between $5.00 and $14.29, debit at $4.44, FedNow at $0.90, and a stablecoin transfer on a low-cost chain between $0.002 and $0.02. "The gap is three to four orders of magnitude, not an increment." The framing line: "A $0.30 fixed fee on a $60 grocery basket is 50 basis points, a rounding error. The same $0.30 on a $0.001 API call is a 30,000 percent transaction cost."

Two of its five policy recommendations read like design requirements for our stack. Where an obligation must apply, it "should attach to the account, wallet, or relationship that can bear it, not to each transfer" — and supervision must be programmable, because "a principal's limits and a provider's controls should be enforced at the moment of payment, not reconstructed afterward." The third is a warning about the layer above payment: "A standard that lets an agent pay an endpoint but not find one keeps payment open while concentrating the market at the directory layer."

One correction — several reports described the paper as including a test transaction settled on Base in about two seconds for under a tenth of a cent. The paper itself labels that flow "Example: An illustration of one agentic transaction." We decoded the X-PAYMENT-RESPONSE printed on its cover: {"success":true,"transaction":"0x4d2e8b","network":"base","payer":"0xA11c"}. The transaction id is a three-byte stub, the payer is truncated, the handshake is x402 version 1, and the validAfter timestamp is 1 January 2025. It is a well-built diagram, and the economics above do not depend on it. It is not a measurement.

5. MCP Server Cards go Final; the schema repo still says experimental

On 6 October, SEP-2127 merged after eight and a half months in review, and the text in main now reads Status: Final, Type: Extensions Track. We audited the design in September while the pull request was open: a static JSON document describing a remote server's identity and transports, with GET <streamable-http-url>/server-card reserved as the recommended location and domain-level discovery delegated to an AI Catalog.

Two things did not move with it. SEP-2127 is a chartering document by its own description, and defers the normative wire format to the ext-server-card repository where schema.ts is the source of truth. That repository's README still opens with "Status: Experimental. This work is for prototyping and feedback only, and is not an accepted or official MCP extension," and its last push was 12 August. Nor is the discovery layer ratified: the AI Catalog repository, active on 8 October, still calls itself "a temporary working repo maintained by the Linux Foundation" and says that "when the specification is finalized, A2A and MCP steering committees will vote on adoption." A pull request merged 8 October trimmed its official implementation list to the Go and Rust SDKs, moving three others to community projects. Read Coinbase's directory-layer warning against that, and the gap is the same one.

MCP also shipped security documentation this week: a local server security guide merged 5 October after nearly three months open, and a full Inspector refresh with a new security page on 8 October.

6. Smaller items

A fifth kind of path bypass. PR #3577 (CarsonRoscoe, merged 2 October) closes a payment-gate bypass in @x402/fastify reported through HackerOne. Fastify's request.url is the raw request-target, so an absolute-form target — permitted by RFC 7230 §5.3.2 — kept its scheme and authority through request.url.split("?")[0]. The route regex then failed to match and the gate concluded no payment was due, while Fastify's router stripped the prefix itself and served the protected handler. The first fix mirrored the router's regex; the merged changeset explains why that was abandoned — the two find-my-way versions Fastify 5 allows resolve such targets differently, so the gate cannot mirror a router whose behaviour depends on a dependency range. Non-origin-form targets are now rejected with a 400 before matching. It is the eighth commit since August whose subject is a path or request-target fix, after the line-terminator and escaped-path work in early August and the /api%2Fpremium family we covered on 25 September.

Facilitator-authored metadata. PR #3666 adds an m map to the builder-code extension, which implements ERC-8021 Schema 2 — the CBOR attribution suffix on settlement calldata. The rules: only the facilitator writes it, any m in a payload is ignored, keys are x402-prefixed and defined by the emitting scheme, encoding is deterministic, and encoders now fail past 65,535 bytes instead of silently truncating. Nothing emits metadata yet; the stated follow-up moves batch-settlement charge counts into m.x402ChargeCounts. In the 4 September roundup this same extension produced a bug where a client-set attribution field had onchain consequence. The spec's answer has arrived: fields with settlement consequence are authored by the settler.

Merged is not shipped. We checked the published packages on 9 October. @x402/fastify 2.28.0 still contains request.url.split("?")[0] in both its ESM and CJS builds. The paywall bundle regeneration merged on 28 September is also unreleased: @x402/paywall 2.28.0 still carries pre-fix padded Algorand CAIP-2 identifiers. Every fix in this roundup is in main and in nobody's node_modules.

A competing spend-control model. Sui's Agent Payments page, read 9 October, describes owner grants carrying "a total budget, a per-payment cap, and an expiry" that are "onchain state enforced at settlement, not a server session," revocable, with out-of-scope requests answered GRANT_DENIED and refundable offers settled into a shared RefundVault. It is "Live on Sui Testnet. Not on Mainnet yet. Paid calls are invite only," and its agent rail advertises MPP today, with x402 offers carried in the same 402 body. Testnet or not, that is the control model Coinbase's paper asks for and x402 does not have.

And a frozen number. The "Last 30 Days" counters on x402.org — 75.41M transactions, $24.24M volume, 94.06K buyers, 22K sellers — are byte-identical to what we recorded on 25 September and 2 October. Three weeks without movement, and no published methodology. Treat it as a snapshot of unknown age.

What it means for LLM4Agents

We are a resource server and the facilitator of our own billing, so this week's pattern lands on both roles.

The ClawRouter integration is the clearest external specification of what a paying agent expects from a gateway like ours. Fail closed on an untrusted operator. Cap exposure to a single deposit. Keep a durable record of the highest cumulative you signed, and refuse a torn one rather than read it as zero. Reconcile that against an independent source on a schedule. If an agent is willing to write an account-layout parser to check our claims, we should publish the number it is looking for.

The requirements.amount rule is the one to internalize. In our architecture the billing engine plays facilitator to our own routing layer, and it should treat the price that layer hands it as an untrusted input: non-negative, integral, within the quoted maximum, and consistent with settled history — not merely larger than the last value we cached. The restart case from #3655 is ours too. Any state we rebuild after a deploy must come from settlement records, not from a counterparty's latest message.

auth-capture delegation is an opportunity and a risk in one object. A hold-then-capture flow fits inference precisely: authorize a maximum from max_tokens, deliver, capture actual usage, void the rest. But the spec says plainly that in the delegated model the chain will not check the receiver's consent, and the Go SDK now lets a facilitator produce that consent after authenticating an API caller. If we take a receiverAuthorizer role, the key stays with us. If we pay into someone else's escrow, we read their operatorType first and assume a capture up to the signed maximum can happen without us.

The m field is the most directly useful thing here. A facilitator-authored metadata map that ERC-8021 indexers already parse is where a per-call receipt belongs: request count, model, unit price, charged amount, written by the party that submitted the transaction. That makes our billing auditable by someone who trusts neither us nor the agent, which is the only audit that counts. And the fastify bypass is a live threat to anyone enforcing payment in front of an API: our gate and our router must agree on the route, and the lesson is that agreement comes from normalizing the input once, not from imitating a parser we do not control.

Staying on the frontier

Five steps, in order.

First, normalize the request path once, this week. Audit every place our paywall or gateway derives a route from a raw request-target. Reject anything that is not origin-form with a 400 before matching, rather than reproducing a router's parsing. Add a regression test that writes a raw request line to a socket, since ordinary HTTP clients cannot construct one and therefore cannot catch it.

Second, pin the SDKs and watch main, not releases. Everything above is unreleased. Pin exact versions, follow typescript/.changeset and go/.changes/unreleased, and keep the check we used this week: unpack the published artifact and grep for the string the fix introduced. Two separate security-relevant fixes are sitting in main with no release date.

Third, publish the number an auditor would look for. Expose a per-channel or per-agent cumulative charged total, signed, alongside the settled transactions that back it — and design our settlement metadata now against the m rules (x402-prefixed keys, integers and text, deterministic encoding, 65,535 bytes) so we are ready when a scheme starts emitting it. Start with request count and charged amount per claim.

Fourth, make our caps enforceable at payment time, and raise the default. Coinbase's paper asks for limits "enforced at the moment of payment, not reconstructed afterward"; Sui enforces them onchain at settlement; our budgets are server-side and must behave the same way, with a machine-readable denial that names the limit it hit. And note what the first real integration did with a one-dollar client-side cap: it disabled it. Our own per-payment ceilings must be sized for video and image calls, or agents will turn them off too.

Fifth, publish a Server Card and an AI Catalog entry. Serve a v1 card at /server-card on our MCP endpoint and reference it from /.well-known/ai-catalog.json, validated against the extension repository's generated schema. Final status makes the format safe to build against; it does not ratify the discovery layer, and it does not make an unsigned card trustworthy. Publish it, index early, and let no payment decision depend on one.

Pay per call, in stablecoins, over an OpenAI-compatible API

Register an agent, fund it, and start routing. No subscription, no monthly minimum.

Register an agent