# Method — Agent Payability Funnel

Companion to `snapshot.json` and `dataset.csv`. Documents stage definitions,
counting rules, drop-off reasons, and the two measurement regimes we mix
in a single table.

## What this measures

For every ERC-8004 agent registered on Base (and Ethereum mainnet), how far
it gets along a 10-stage path from "registered on-chain" to "accepted my
payment and delivered a response." Stages are cumulative: an agent that
reaches stage N also reaches every stage 1..N-1 by construction.

## Chains

Base (`chain_id` 8453) and Ethereum mainnet (`chain_id` 1). Other chains
(Arbitrum, Optimism, Gnosis, Linea, Soneium, Mantle, Metis, Scroll,
Taiko, Abstract, Goat, SKALE Base, Avalanche, Polygon, Celo) are measured
separately in `data/census/` and are out of scope for this funnel.

## Population

Our live-enriched agent profile store: the registry scan, the daily
re-enrichment and the live endpoint probes all write to it. One row per
(chain, agent id) pair. Rows are not deleted when a revoked tokenURI is seen; stage 1 is therefore an
inclusive count of all registered agents the system has ever seen on each
chain, matching the on-chain `IdentityRegistry.ownerOf()` lifetime count.

## Stage definitions (precise)

| Stage | ID | Rule |
|---|---|---|
| 1 | `s1_registered` | a profile row exists for the chain |
| 2 | `s2_advertises_payment` | the agent is recognised as supporting x402, OR its registration metadata carries a payment field, OR its `.well-known` file carries one |
| 3 | `s3_endpoint_answers` | the live probe reached the host, OR the host returned any HTTP status from 200 to 599 |
| 4 | `s4_valid_402_challenge` | the endpoint's 402 challenge, or its `.well-known` file, lists at least one accepted payment option |
| 5 | `s5_includes_payto` | at least one accepted payment option names a pay-to address (a 0x-prefixed 40-hex string) |
| 6 | `s6_parseable_price` | the profile has a valid x402 payment configuration: a pay-to address plus a positive price in a recognised shape |
| 7 | `s7_price_normal_range` | min advertised `price_usd ≤ $1.00/call`. USDC is converted from µUSDC (6-decimals). Non-USDC assets return `None` and drop this stage |
| 8 | `s8_payable_no_auth` | **observed:** our test-purchase attempt returned a parseable 402 that passed facilitator verify-only (`isValid=true`) — i.e. no 401/403 auth gate, no `missing accepts`, no 405 method mismatch |
| 9 | `s9_settled_onchain` | **observed:** the signed EIP-3009 `transferWithAuthorization` settled on-chain to the advertised payTo, discovered via `pay.tx_hash` in the server response OR a USDC `Transfer` log scan from the payer wallet |
| 10 | `s10_delivered` | **observed:** HTTP 200 with substantive body AFTER the payment settled (= Proven, path b) |

### Deterministic vs observed

Stages 1-7 are deterministic — they read today's profile store and return
the same answer for every call with the same input. Stages 8-10 are
observed from the evidence files of our three test-purchase pilots. They are not a sample — they
are a census of every test purchase Agent Zero has attempted to date.

### Pool restriction and the "observed outside pool" column

Stages 8-10 counts in the main funnel are restricted to agents in today's
stage-7 pool, so the funnel reads monotonically. Pilot attempts against
agents that have since dropped out of stage 7 (e.g. because
the payment terms were never recorded for them —
the price lives only in a POST body or on a sub-path that the probe URL
list didn't carry) are counted separately as `observed_outside_pool`.
Those are real deliveries, just not visible from today's deterministic
funnel. The `delivered_agents` list in `snapshot.json` is the full set,
irrespective of pool membership.

## Owner clusters

For each stage we count distinct `payTo` addresses (lowercased) as a
proxy for operator identity. A single operator who registers 10 ERC-8004
agents behind one treasury payTo contributes 10 to the agent count but 1
to the operator count. This is a lower bound on operator distinctness —
one operator may use multiple payTos — and does not deduplicate across
chains.

## Drop-off reason enum

```
not_advertised        no payment metadata at stages 1→2
unreachable           host_health unreachable or http=0 at stages 2→3
no_402_challenge      reachable but no stored payment options at stages 3→4
no_payto              payment options present but no valid pay-to address at stages 4→5
price_missing         payTo present but no parseable price at stages 5→6
price_above_1usd      parseable price but > $1/call at stages 6→7
auth_walled           pilot attempt returned 401/403 (login/API key gated)
missing_accepts       pilot attempt returned 402 with an empty list of payment options
method_not_allowed    pilot attempt returned 405 (POST-only probed GET)
facilitator_rejects   verify-only came back isValid=false
pay_failed            verify-only valid but POST non-200 (no settlement)
settled_no_delivery   payment settled but response was still 402/non-body
```

## Price distribution

Reported as a histogram over the stage-6 agent set, bucketed by USD:
`[0, 0.001)`, `[0.001, 0.01)`, `[0.01, 0.1)`, `[0.1, 1.0)`, `[1.0, 10.0)`,
`[10.0, 100.0)`, `[100.0, +∞)`. We report min / median / mean / max, plus
the count of agents whose min advertised price exceeds $1/call
(`above_1usd_count`). Non-USDC-denominated prices are excluded from the
USD distribution and reported separately only via the `price_missing`
drop-off reason at stage 6.

## Honesty rules

- Stages 1-7 counts update whenever the profile store rescans — expect
  movement from day to day as enrichment catches up. We timestamp every
  snapshot in `snapshot.json`.
- Stages 8-10 counts update only when a new pilot's evidence lands.
  Backfilled snapshots reflect the pilot cohort that existed on their
  stated date; we do not retroactively credit later deliveries to earlier
  snapshots.
- Each snapshot has a `backfilled` flag set to True if `as_of_date` is
  earlier than `generated_at` and the pilot evidence used was not yet
  present on `as_of_date`. (Today's snapshot is NOT backfilled.)
- No agent is named in aggregate rollups. The `delivered_agents` list
  in `snapshot.json` is the single exception — those agents are already
  publicly identified by on-chain transaction hashes.

## Reproducing a snapshot

We re-run the snapshot daily and publish a new dated dataset when the picture changes. A snapshot reads the live profile store and the evidence from every test-purchase pilot, and writes the structured snapshot (`snapshot.json`) and one flat row per (chain, stage) (`dataset.csv`). The payable-endpoint list it draws on is the one published in the 2026-10-11 x402 payable-endpoints dataset.

## Licence

Dataset released under CC BY 4.0.
