๐Ÿ“… Historical page. This content reflects minia2a as of its publication date and is kept for the record. Current model: x402 pay-per-call in USDC on Base only, 5 free trial calls per signed wallet, no credits and no top-up rail. โ†’ See current

We Blamed the Market for a Metric Our Own Clients Broke

September 25, 2026

Two days ago we published Paying Is Not Identifying, an explanation of a number in our own /api/stats: a trailing seven days with 73 paid calls, four distinct paying wallets, and zero identified agents. The post sorted metrics into two classes โ€” demand metrics that need no cooperation from the caller, and attribution metrics that need the caller to send an identity header โ€” and it located the gap in caller behaviour: the traffic that identifies itself was overwhelmingly traffic we generate ourselves, and the traffic that was a real customer identified itself zero times.

That post was half right, and the half it missed was in our own repositories.

Before concluding that your market will not send you an identity, check whether the client you publish is capable of sending one. We did not, and we published the conclusion first.

Five packages, and what each of them actually sent

We ship five client packages that can draw a trial call against the marketplace: a skill, a CLI, a programmatic client, an MCP server, and the main package. Auditing all five against a mock gateway โ€” capturing the headers each one really emits โ€” collapsed the "customers are not cooperating" story into five separate shipping defects.

packagepublishedwhat it did with X-Agent-ID
minia2a-skill1.3.7sent it on no request at all
minia2a-cli1.1.7sent it on every request, including third-party hosts
minia2a-client2.0.7read one of the two identity-file paths
minia2a-mcp1.2.5read one of the two identity-file paths
minia2a1.1.3read one of the two identity-file paths

An agent that installed our own tooling and drew a trial through it was, in every one of those five cases, either invisible to the counter or counted as the wrong number of agents. The caller does not get to "opt in" to attribution if the client you handed it cannot opt in.

Three defects that are not the same defect

1. A client that sends nothing

The skill's CLI issued signed trial calls โ€” real calls, real allowance consumed โ€” and emitted X-Agent-ID on none of them. The server maps a missing header to an empty identity and counts only non-empty ones, so every trial that tool drew landed in the counter's blind spot. Not a partial bug: zero coverage on a code path whose entire purpose is to make calls.

2. A client that sends it everywhere

The CLI had the opposite defect. It attached the header to every request, and one of its commands resolves a service endpoint out of the public catalog and calls it. Measured against /api/services: 16 of 1703 endpoints live on 11 hosts that are not ours. A per-machine pseudonym plus a wallet signature was riding to those hosts on calls the CLI made on the user's behalf.

{"Accept":"application/json",
 "X-Agent-ID":"agent:098c21be-โ€ฆ",
 "User-Agent":"minia2a-cli",
 "X-Wallet-Signature":"0xdef8โ€ฆ",
 "X-Trial-Timestamp":"1790320167"}

The wallet signature is inherent โ€” you cannot draw a trial without proving you hold the key. The pseudonym is not: it is stable across calls by design, which is exactly what makes it worth not handing to a stranger. Our SDK had already gated it on the host. Three of our clients disagreed about that property; two of them were right.

3. One machine, counted twice

Several of the clients read the identity from ~/.minia2a-agent-id. The CLI read it from ~/.minia2a/agent-id. A machine whose only identity had been minted by the CLI held a value the others could not see, so the next package it touched minted a second one โ€” and one machine became two agents in the metric.

This is the part worth sitting with. The same counter was under-counting and over-counting at the same time, by different mechanisms, over the same window. A single number cannot tell you that two independent bugs are pulling it in opposite directions; it just reads low, or zero, and looks like a fact about the world.

How the defects were measured

Every verdict here came from driving the published artefact โ€” the directory a user would install โ€” as a child process against a mock gateway, and reading the headers it actually produced. No request leaves the host, and no trial allowance is consumed. The published old version serves as the positive control, so a green result on the fixed version is known to be about the fix:

subjectresult
published [email protected]8 failures, rc=1 โ€” sends no identity
published [email protected]2 failures โ€” one leak, one wrong path
published [email protected]2 failures โ€” mints a second identity
published [email protected]2 failures โ€” same
registry tarballs of the fixed versionsgreen, re-downloaded from npm before running

The check that passed on an empty transcript

One of the harness runs reported "no identity header travelled to a third-party endpoint" as PASS while making zero requests. A dependency path was wrong, the client crashed on require, and the leak check โ€” which walks the recorded requests looking for the header โ€” found nothing to complain about, because there was nothing at all.

What caught it was the assertion sitting next to it: the off-domain endpoint was actually called. That one failed. It happened twice in this audit.

A check of the form "we looked and saw no X" is worth nothing on an empty corpus, and an empty corpus is exactly what a crash produces. It needs a companion assertion that the thing it looked at happened at all.

This is the same failure mode as the counter that started the investigation. Zero identified agents was read as a fact about customers; it was a fact about the instrument. A check that cannot distinguish "clean" from "not asked" has the same problem, one level up.

Where the number stands today

The fixed versions have been published and the metric has not moved, which is what we expect: realAdoptingAgents7d still reads 0, and the only identity hash inside the seven-day window is our own verification client, which the counter excludes by digest. An external agent that installed our tooling last week still holds the broken version, and will keep holding it until it upgrades.

We publish the zero. If it moves next week it will be because client coverage changed, not necessarily because the market did โ€” and the useful thing we take from this week is that those two events are indistinguishable from the number alone, so the client has to be audited before the market is judged.


Notes from running an x402 pay-per-call API marketplace and its published tooling. The five fixes shipped as [email protected], [email protected], [email protected], [email protected] and [email protected].

Per-call APIs for agents โ€” no signup
1,700+ endpoints, USDC on Base, 5 free trial calls per signed wallet.
Browse the catalog