aspern
Server Details
What the chain records about an address before you pay it, and whether a payment fits it.
- Status
- Healthy
- Uptime
- 99.4% over 20 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-06-18
- URL
TDQS
Scored across 20 tools
Most tools target clearly distinct questions: per-address check vs. bulk shortlist vs. single-agent history, and vault_check vs. vault_exits vs. vaults_earned split levels, flows, and realised returns. The only mild overlap is among evaluate_action, preflight_payment, and inspect_payment, but their descriptions sharply distinguish action-approval, payment-time, and calldata-inspection scopes.
Names are consistently snake_case with a strong verb_noun or noun_action pattern (find_agents, vault_check, list_policies, monitor_subject). A few entries (agent_changes, evidence_for, vaults_earned) invert the order but stay readable and within the same convention, so no real inconsistency.
20 tools is slightly heavy but each maps to a distinct capability (identity, counterparty, payment preflight, vault due diligence, evidence, monitoring, receipts). Nothing feels redundant enough to cut, though the surface is on the larger side for the domain.
The surface covers the full lifecycle: identify a subject, check it, preflight and inspect payments, evaluate actions, find agents/vaults, monitor changes, and record receipts. Minor gaps exist (e.g. no explicit update/close for watches beyond idempotent re-calls), but agents can work around them.
Available Tools
29 toolsagent_businessDoes this agent have a business (paid)IdempotentInspect
Does this agent have a BUSINESS, and can any of it be demonstrated? Six questions an investor, a marketplace or an operator actually asks, each answered separately: are the addresses paying it really independent customers; is revenue growing or shrinking; how much is repeat custom; how many of those payments can be shown to have bought anything; what does it cost to run and to whom; and if it has several addresses, can the link be DEMONSTRATED or is it an unconfirmed assumption. Measured on two live agents: one takes $2,388 a month from 4,772 payers of whom 97% are repeat, the other $932,414 from 7,220 payers of whom 12% are — two completely different businesses that a counterparty count reports identically. THERE IS NO SCORE over the six, deliberately: a number would average "thousands of addresses paid this" against "we hold no delivery record at all", and the second is a statement about US. Four things the data invites and this refuses: an ADDRESS is not a customer (one customer can hold twenty); a PAYMENT is not a delivery (the busiest agents settle on rails that carry money without carrying a job, so "no delivery record" there is our reach and not a finding); a SHARED FUNDER is not an identity (an exchange funds thousands of strangers), so a link is published as demonstrated or as merely co-occurring and the second is never promoted; and a COST we cannot see is not a cost that is not there. PAID. SINCE 2026-10-11 IT ALSO CARRIES economicChain: the four links of the chain an agent has to complete to be a working economic subject — a customer paid it, it ordered or did work, the result was demonstrably delivered, a customer came back. Each link is evidenced, unevidenced (we read the rail and found nothing — a statement about the agent), unread (THE RAIL RECORDS IT AND WE DO NOT READ IT — a statement about us, and the only one of the four that closes by our building something) or unevidenceable (the rail does not record it at all, so no reading by anybody will change it — a statement about the rail). Those three silences are never folded together, because they call for three different acts. Masumi settles work through an escrow whose release or refund is on chain, and SINCE 2026-10-11 WE READ IT: a release to the seller is the buyer letting the escrow go, which is the closest thing to an accepted delivery this chain can show, and it counts alongside an ACP completion. A CLOSURE does not count — over all 29,088 settled escrows, 5,819 refunded to the BUYER against 4,659 released, so counting closures would publish a refund as delivered work more often than not. An agent whose escrows the step reader has not walked yet is unread rather than unevidenced, per agent, because the chain carries the answer and we have not asked for that one. THE FOURTH STATE is the one to read carefully: x402 is 91% of the volume and records payment, never delivery, so for an x402-only agent link three is unevidenceable and reporting it as missing would blame the agent for the rail. NO SCORE: the worst link governs, because averaging lets a strong payment record carry an absent delivery record. Measured over all 3,135 addresses we hold: paid 3,048, hires 432, delivered 684, returned 2,412, and 185 with all four.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | The agent’s address. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | How much of the question we could answer, and which parts we could not. |
| limits | Yes | The four conclusions the data invites and this refuses. |
| address | Yes | The agent this is about, read back. |
| answers | Yes | One per question: `asks` in a person’s words, `answered` as measured/partial/unmeasured, `says`, and the `figures` behind the sentence so you can do your own arithmetic. |
| coverage | Yes | How many of the six are measured, partial and unmeasured. A count, never averaged into a grade. |
| recordAsOf | No | When the nightly record behind most figures was computed. The revenue months are read live. |
| answeredStates | No | What measured, partial and unmeasured each mean. |
agent_changesWhat moved in the agent recordRead-onlyIdempotentInspect
What moved in the agent record, across every agent, since a date. The counterparty check answers what is true about one address NOW; this answers what changed, for all of them, which is the question anybody holding a list asks next. One row per FIELD that moved, not per address: an agent whose dealings and concentration both moved is two facts, and folding them would make you diff the answer to work out what was meant. Roughly one agent in five moves on an ordinary day, out of about 2,900 tracked. A day with no row for an address is a day it did not move, never a day nobody looked. The record began on a date and from says which: asking for anything earlier answers from there rather than pretending nothing happened. Needs a key and the agents.changes capability.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Default 1,000, maximum 5,000. Read `capped` before concluding you have it all. | |
| since | No | An ISO date, such as 2026-10-01. The last seven days if you leave it out. | |
| address | No | One address, where you want its movement rather than everybody’s. |
Output Schema
| Name | Required | Description |
|---|---|---|
| from | No | The first day held at all. There is nothing before it because the feed began when it began. |
| count | Yes | Rows IN THIS ANSWER, which is one per field that moved and not one per agent. Where `capped` is true it is the page size and not the total, so it is a floor on how much moved and never the whole of it. |
| items | Yes | address, day, field, was, now, and the path of that agent’s full check. |
| since | Yes | The day this answer starts from, read back so a clamp is visible. |
| capped | No | TRUE where the page came back full, so ask again with an `offset`; FALSE means nothing moved after these rows in the window asked for, so the feed is complete rather than merely begun. A cap is not a count. |
| limits | Yes | What this answer cannot tell you. Quote it with the numbers. |
agent_dependenciesWhat several agents rest on at once (paid)IdempotentInspect
If your firm relies on several external agents, what do they rest on AT ONCE? Give it two to twenty-five addresses and it finds the parties more than one of them pays. THE PRODUCT IS THE DISTINCTION, NOT THE JOIN: finding that three agents paid the same address tells you almost nothing — on our rails one address is paid by 71 agents across 4,100 payments and another by three agents once each, and calling both "shared" makes the second sound like the first. Four tests must ALL hold before the word dependency is used: repeated (more than one payment, because a single payment is an event), one-way (it has never paid them back, because money moving both directions is trade between peers and survives either of them leaving), sustained (spanning more than a day, so a burst of twenty in an afternoon is not a standing arrangement), and shared (more than one of the agents you named). All four are published on every party under tests, so you can draw the line somewhere else than we did. Anything short is a shared-counterparty with its failed test named and is reported as a LEAD. The concentration line counts dependencies only. A party just ONE of them pays is left out entirely — that is counterparty_check, free. Most shared infrastructure, a cloud region or a model provider on a card or one operator holding the keys, leaves no payment at all, so what this finds is a FLOOR on the concentration that exists and never a measure of it. PAID.
| Name | Required | Description | Default |
|---|---|---|---|
| addresses | Yes | The agents your firm relies on. At least two, because the question is what they rest on together; at most 25, because the join covers every payment each has made. |
Output Schema
| Name | Required | Description |
|---|---|---|
| read | Yes | HOW CURRENT THE RAIL BEHIND THIS IS. Recomputed from the payments table on every call, never a stored snapshot — but only as current as the chain that has fallen FURTHEST BEHIND, which is the date given, not the chain most recently read. `furthestBehind` names it and `stalled` lists any chain reporting an error, which may be further behind still. A dependency formed after `railReadAt` is not here yet. Do not confuse it with `firstAt`/`lastAt` on each party: those are when payments HAPPENED. |
| says | Yes | What was found, with the floor stated. |
| kinds | No | What dependency and shared-counterparty each mean. |
| agents | Yes | The agents asked about, read back and de-duplicated. |
| limits | Yes | That the four tests are a JUDGEMENT about where a relationship becomes a reliance, published as one so you can draw the line elsewhere, and that a party only one of these agents pays is left out rather than listed. |
| shared | Yes | Parties paid by more than one of them, dependencies first. Each carries `kind`, `tests` with all four, `paidBy` with payments and span, and what it means. |
| cannotSee | Yes | Why this is a floor: most shared infrastructure leaves no payment at all. |
| concentration | No | The dependency reaching the most of your agents, or null. DEPENDENCIES ONLY: counting leads here would let three agents who each bought something once produce "three of your five depend on this". |
agent_economic_profileAgent economic profile (paid)IdempotentInspect
One agent, four readings, in the order a buyer actually asks them: what it EARNS and from whom, whether its contracted work FINISHED and who signed it off, who it RESTS ON as a supplier, and whether it is still TRADING and its endpoints answer. Every other tool here answers one of those; this is the one that answers them together, over the same nightly record, so the four cannot disagree with each other or with the endpoints they summarise. THERE IS NO SCORE ON TOP and there will not be one: a single figure would be the thing every reader quotes and the only one none of them can check, and it would average a measured quantity with an unmeasured one until neither is visible. Each block keeps its own counts and its own denominator. A block we have not read comes back NULL rather than as a row of zeros, because "it has no completed jobs" and "we have not read its job side" are different facts and a buyer choosing between agents deserves to know which one they are looking at; blocksAnswered says how many of the four this answer could fill. cannotSee names what no block here can reach at all — revenue that never touched a rail we read, dependencies that are not payments, and whether completed work was any GOOD, which we cannot see from who signed it off. PAID.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | The agent’s address. EVM or Cardano; both resolve to the record key. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asOf | No | When the nightly record behind these figures was computed. |
| says | Yes | How much of the profile is answered, and which parts are missing because we have not read them. |
| format | No | What kind of address this is and which rails were checked for it. |
| health | No | Endpoints listed and probed, what the unpaid handshake got, and how long it has been quiet. |
| address | Yes | The agent this is about, read back. |
| revenue | No | Dealings, buyers, repeat buyers, largest buyer share, independent vs two-way, and whether its payers share an obscure third party. |
| delivery | No | Of contracted work that reached an outcome: completed, who judged it, refunded, and the phases nobody read. |
| cannotSee | Yes | What no block here can reach, named in the answer rather than in a footnote. |
| wellKnown | No | Set when the address is not a party at all — a burn address, a router — so a record against it is not a business. |
| dependencies | No | Who it pays, split into suppliers the protocol NAMES, those merely listed, and those with no evidence of supplying anything. |
| blocksAnswered | Yes | How many of the four this answer could fill. Read it as the denominator of everything above. |
check_actionOne check before you sign (paid)IdempotentInspect
CALL THIS BEFORE YOUR AGENT SIGNS ANYTHING THAT MOVES MONEY. One request instead of five: it reads the counterparty record, decodes the calldata you are about to sign, looks up the seller’s own catalogue listing, runs an unpaid 402 handshake with the endpoint, and applies a published policy — and then, which is the point, compares them WITH EACH OTHER. The losses an agent actually suffers live between those readings and no single one of them can see them: the bytes paying an address you never checked, so a spotless counterparty record is about a party this transaction does not pay; an UNLIMITED APPROVAL wearing the shape of a one-cent payment; the seller’s listing naming a payee the calldata does not; a policy allowing a payment for a path that is not served. Every cross-check names BOTH readings that disagree in between, and none of them is an accusation — the record can be wrong. Send calldata whenever you have it: it unlocks the strongest check there is. A cross-check can only make the verdict worse, never better. SEND calldata, chain AND from and it is also SIMULATED: one eth_call at the latest block, the node executes it and throws the result away, nothing is signed or spent. A revert is the strongest finding available, because every other reading argues about whether you should send it and this one is that it will not work. Not a state diff, run against the current block, and a node that refuses is reported as our gap rather than as a failure. ran says which parts did not run and why, because a check that did not happen must never look like one that passed. PAID; its five components are each free on their own tools and what is sold here is the comparison.
| Name | Required | Description | Default |
|---|---|---|---|
| from | No | The address the transaction would be sent FROM. Only used to SIMULATE it, and worth sending: without it the call runs as the zero address and reverts for a reason about our request rather than your transaction. | |
| asset | No | The TOKEN you are paying in. Compared against the one the seller’s listing prices in: a payment in a token the seller does not credit leaves your side and arrives nowhere, and every other check passes on it. | |
| chain | No | The chain it is about to be sent on, e.g. base. | |
| action | No | What you are about to do, because the checks differ: `pay` weighs a recipient’s payment record, `allocate_capital` weighs a VAULT (pass its slug as `subject`) on exit, controller and evidence, `connect_mcp` and `call_tool` weigh a server or tool you are about to trust. Defaults to `pay`. Choosing the wrong one does not fail — it answers the wrong question, and `checked` in the reply names which checks actually ran. | |
| policy | No | A policy slug or version from list_policies. Defaults to conservative. | |
| subject | No | For allocate_capital: the vault slug. | |
| calldata | No | The hex bytes you are about to sign. Left out, the transaction is reported as UNREAD rather than fine. | |
| resource | No | The http(s) URL of the endpoint being bought, where there is one. | |
| valueWei | No | Native value in wei, where the transaction carries any. Simulation only. | |
| amountUsd | No | What is about to be sent, in dollars. | |
| recipient | No | The address about to be paid. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ran | Yes | Which parts ran and why each one did not. |
| says | Yes | The worst thing found, in one sentence. |
| parts | Yes | Each reading on its own: policy, transaction, listing, endpoint, settledOn. |
| limits | Yes | What this check structurally cannot contain: what the action is FOR, terms agreed privately, any simulation, and calls the decoder refuses rather than guesses at. Read it before treating a clean answer as a safe one. |
| verdict | Yes | The policy’s decision, worsened by the cross-checks and never improved by them. |
| crossChecks | Yes | The comparisons between parts. Each names the TWO readings that disagree. The ones that AGREED are published too, because a comparison that ran and agreed is different from one that never ran. `tone` is `bad`, `warn`, `good` or `neutral`, and the fourth is the one to read carefully: a NEUTRAL check established nothing and can neither improve nor worsen the verdict. `the-price-has-moved-since-the-listing` compares the endpoint’s own quote with its catalogue entry in BASE UNITS after checking that both name the same token, so it is exact; where the tokens differ or either is unnamed it reports `the-two-prices-are-not-comparable` instead, because a 402 states an amount in the asset’s smallest unit and never its decimals. The same rule is applied by `preflight_payment` and `evaluate_action`. |
check_service_endpointCheck a service endpoint before connectingRead-onlyIdempotentInspect
Call this before connecting to a service. Give it the http(s) URL of an MCP or A2A endpoint and it says who declares it, whether our daily probe reached it, what it answered with, and how many of the last readings answered. It keeps three things apart and never merges them: what an identity DECLARES the endpoint offers, what a probe OBSERVED, and the readings behind that. Read drift where present — tools declared but not answering is the signal that an endpoint has changed under the people relying on it. It also answers the three things a buyer wants BEFORE calling a paid endpoint, as separate fields and never folded into one number: price is the seller’s own published amount, asset, network and payee; handshake says whether it answered without credentials, which is the nearest observable thing to “can I try it”; and measured is how many of how many days answered and how slow it was, which is what we read rather than a guarantee anybody made. manifest and changes carry the series: a registration says what an agent offers now, and the readings say what it offered LAST WEEK. Store manifest.hash and compare it next time to detect an endpoint that changed under you. Two things this is NOT: an unreachable endpoint is an availability fact and never evidence of bad faith (weigh latest against history, since one bad day and a dead service look identical in a single reading), and an endpoint we have never probed is outside our reading rather than absent from the world. For a CATALOGUED x402 resource that no agent registered, read unpaidProbe: our own unpaid 402 handshake, which is free for both sides and says whether the endpoint is still there and what it charges now against a catalogue entry that may be months old. Free.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The absolute http(s) URL of the service endpoint you are about to connect to. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | The reading in one sentence. An endpoint we have never probed says so here: that is our gap, not evidence the service is down. |
| drift | No | Declared but not observed, and the reverse. Null where either side is unknown — subtracting silence would manufacture a finding. |
| price | No | The seller’s OWN published terms for this URL: `amount` in the asset’s own units with `asset` named beside it (a bare number would be read as dollars), `network` as CAIP-2, `payTo`, which catalogues list it, and `cardPriceUsd` where the registration states a price too. Null throughout is UNPRICED, which is not free. Where the card and the catalogue disagree, both are shown — two claims by the same party, and picking one would hide that. |
| latest | No | The most recent probe: outcome, latency, and what it answered with. |
| changes | No | Every move we saw in what it offers, oldest first, each with `added`, `removed`, a protocol-version move where there was one, and the two hashes. `at` is the day we SAW the change, not the day it happened: we probe daily and cannot place it more precisely. An empty array where we read a list and it never moved; a tool list we could NOT read is skipped entirely rather than folded in as an empty one, which would invent a “removed everything” out of our own gap. |
| history | No | Up to fourteen readings. One bad day and a dead service look identical in a single reading. |
| endpoint | No | The URL as we read it back, so a typo is visible before anything is concluded from the answer. |
| manifest | No | What the endpoint offers NOW, as something you can bind to: `hash` over the sorted tool names and the declared protocol version and nothing else, with `tools`, `firstSeen`, `lastSeen` and how many readings carried it. Store the hash and compare it on your next call to know whether the offering moved under you. Null where we have never read a tool list here. |
| measured | No | What we measured, which is NOT a guarantee: nothing on these rails publishes one. `serving` of `days`, every outcome by how often, and median and worst latency of the readings that answered. Left as counts with the denominator stated, never a rate and never a grade — 12 of 14 over two weeks means something different from the same fraction over two days, and only the caller can pick the denominator that matters to them. |
| outcomes | No | What each outcome word means, so a caller never has to guess. |
| handshake | No | Whether the protocol HANDSHAKE completed without credentials on the latest reading. `open` is the closest thing here to “you can try it” and is NOT a statement that calling its tools is free — a server can answer openly and charge for every call, and we complete a handshake rather than call a tool. `gated` means it asked for something we do not have, which is working as intended. Null where we have no reading. |
| declaredBy | No | Identities that declare this endpoint, and the tools each one claims. Their claim, not our verification. |
| unpaidProbe | No | OUR OWN unpaid x402 handshake with this URL, which is the free availability test for an endpoint no agent registered. x402 requires a server to answer an unpaid request with 402 and its requirements BEFORE doing any work, so the first half of every real client’s handshake costs nothing and proves three things: the host is there, it still speaks x402, and what it asks for NOW. `outcome` is one of quoting, open, refusing, gone, error, unreachable — `open` means it answered 200 unpaid, so it is up and not charging on this path. `quoted.amount` is in the asset’s own smallest unit and is NOT scaled to dollars, because nothing in the requirements document says how many decimals the asset has. Read it beside `price`, which is what the catalogue recorded whenever that entry was written; a price that has moved is a finding neither one shows alone. Null means we have not run this probe here, which is not a finding about the endpoint. |
counterparty_bulkCheck up to fifty addresses in one call (paid)IdempotentInspect
Check up to fifty addresses in one call, each with its observations, AND what the set shares underneath: the parties that two or more of them pay. That second part is the one answer no per-address row can contain, because the input is your own shortlist — four agents stopping together because they all pay one party is invisible in four separate clean records. PAID two ways and they buy different things: one cent a call over x402, priced per call rather than per address, buys the rows; the shared block needs the dependency.shared capability, on Analyst and above, and when it is missing the block says so rather than vanishing. A shared recipient is not proof of a shared dependency — several agents paying one address may be paying a relayer, a bridge or the same customer back — and an empty list is a finding about these addresses AND about our reach. WHY readOnlyHint IS false: this tool reads and writes nothing in our store, but calling it WITH an x402 payment authorisation transfers USDC from the caller to us and records a receipt, so the call is not free of consequence and an agent must not make it speculatively. Called without an authorisation it changes nothing and answers with the price.
| Name | Required | Description | Default |
|---|---|---|---|
| addresses | Yes | One to fifty addresses, in any mix of forms: an EVM address in any case, a Solana base58 address, a Cardano bech32 one. Fifty-one or more is REFUSED with a 400 `too_many` rather than silently truncated, so a caller never reads a partial answer as a whole one. An address we have never seen paid comes back as a row saying so, not omitted — so the answer has one row per address you sent, in the order you sent them. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | One entry per address given, in the order given, each with its own observations and its own limits. |
| limits | No | What this answer cannot tell you. |
| shared | No | The parties two or more of the given addresses pay, most shared first, each with how many of yours pay it and which ones. `available: false` with a `capability` name where the plan does not carry it. An empty list means no party is paid by more than one of them on a rail we read, which is a finding about them and about our reach: a model, an endpoint or a host shared between them is a dependency no payment rail shows. |
| checked | No | How many addresses were read. |
| payment | No | What was paid and how it settled. Priced per call, not per address. |
counterparty_checkWhat the chain records about one addressRead-onlyIdempotentInspect
Before paying or hiring an agent: what the chain records about that address. Independent payers (counterparties that paid it and were never paid back), the ones it does pay back, how concentrated its custom is, WHETHER THOSE INDEPENDENT PAYERS ARE INDEPENDENT OF EACH OTHER under independence, WHAT IT ITSELF RESTS ON under restsOn (how many parties it pays and how much of its spending goes to the largest of them), how its ACP jobs ended, whether its advertised service answers, and when it was last paid. Free. Three limits to repeat whenever quoting it: independent means no payment BACK on the rails we read, NOT proof the payers are different parties, since one owner can fund many addresses that never pay each other; an all-time record says nothing about whether the agent still works — 44% of agents ever paid have not been paid in 90 days; and restsOn counts every party this address has PAID rather than purchases from identified sellers, so a recipient there has not been shown to supply anything, and restsOn.suppliers of zero means it has paid nobody on a rail we read, never that it depends on nobody. Takes an EVM address, a Cardano payment address (addr1…) or a Solana address.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | The address you are about to pay or hire. |
Output Schema
| Name | Required | Description |
|---|---|---|
| acp | No | How its jobs ended, where it has any. |
| mech | No | Deliveries on the Olas mech marketplace, and what was paid for them where we hold it. A rail many agents never touch; zero here is not a mark against an address. |
| x402 | No | Sales and payers on the x402 rail. Payers are counted as parties, not payments: one buyer paying fifty times is one payer. |
| format | Yes | What kind of address this is and what we read for it. |
| limits | Yes | What this answer cannot tell you. Quote it with the numbers. |
| masumi | No | Escrows on the Masumi rail. Null where we hold no reading for this address at all, which is not the same as zero escrows. |
| address | Yes | The address as we read it, normalised. Compare it with what you sent before acting on the answer. |
| paidFor | No | What it was paid for, in the subject’s own words. |
| restsOn | No | suppliers, payments, spentUsd, largestShare and recent.{suppliers90,largestShare90}: every party this address has PAID. NOT the mirror of `dealings` — a dealing is a sale and needs a seller on the other end, while a payment out counts whoever receives it, so a recipient here may be a relayer, a settlement route or a customer being paid back. `largestShare` is null below three suppliers, where it could only be a half or a whole. Zero suppliers means it has paid nobody on a rail we read, never that it depends on nobody: a model, an endpoint, a host and a key are dependencies no payment rail shows. |
| alsoHere | No | The same address on the capital side — a vault or an operator — with the check to call. A match on the address, never an identification of the party. |
| dealings | No | rails, chains, counterparties, independent, largestShare, firstPaid, lastPaid. `independent` means no payment BACK on the rails we read — NOT proof the payers are different parties, since one owner can fund many addresses. |
| identity | No | Registrations it holds. Claims, never verification. |
| services | No | Callable services it declares, and how many answered our probe. |
| independence | No | payers, linked, viaParties, largestGroup: payers of this address that share an OBSCURE third party with another of its payers. This is the test of `dealings.independent`, which counts payers that never paid it back and has never been proof they are different parties. A party paid by two to ten addresses in all counts; a hub paid by more does not, because two agents both paying a hub have shown only that the hub is popular. EVIDENCE OF A LINK, NEVER PROOF OF ONE OPERATOR — two payers paying one small service are two customers of that service. `groups` names which payers and through what and needs the `independence.test` capability; where it is withheld, `capability` says so. A linked count of zero is not proof they are unrelated: one owner funding addresses that never touch each other again leaves nothing for this to find. `differentPopulation` IS PRESENT WHEN THIS BLOCK AND THE RECORD ABOVE IT COUNT DIFFERENT NUMBERS OF PAYERS, which happens because they are two jobs on two schedules: it carries `why: "different_population_snapshots"`, both counts and both dates. Neither figure is wrong, and the linkage here describes the population in THIS block, not the larger one. It is null when they agree, so its presence means something. |
| observations | Yes | The findings, each with its evidence class and its own words. Read these first. |
counterparty_historyOne agent’s record day by day (paid)IdempotentInspect
How one agent’s record has moved: dealings, independent payers, concentration and delivery, day by day. PAID, one cent a call over x402 — the median price of this rail. Without payment the tool answers with the price and how to pay it, and the free check remains available. The history begins the day we started keeping it; it is a record we keep, not one the chain gives away. WHY readOnlyHint IS false: this tool reads and writes nothing in our store, but calling it WITH an x402 payment authorisation transfers USDC from the caller to us and records a receipt, so the call is not free of consequence and an agent must not make it speculatively. Called without an authorisation it changes nothing and answers with the price.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | 1 to 365, default 90. The history begins the day we started keeping it, so a longer window does not reach further back than that. | |
| address | Yes | The agent whose record you want day by day. An EVM, Cardano or Solana address. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | One entry per day: dealings, independent payers, concentration, delivery. |
| change | No | What moved across the window, and over which dates. |
| address | Yes | The address this history is for, normalised and read back. |
| payment | No | What was paid and how it settled. Present because this call took money. |
| keptSince | No | The day we began keeping this. Nothing before it exists, at any window. |
endpoint_disagreementsEndpoints that contradict their own listingRead-onlyIdempotentInspect
WHICH ENDPOINTS CONTRADICT THEIR OWN LISTING: they ask to be paid at an address the catalogue entry they published does not name. This is the one reading here that cannot be reproduced from anywhere else — an uptime checker sees a live endpoint and a catalogue reader sees a published payee, and only holding BOTH shows the contradiction. A disagreement is between two statements by the SAME party, so it is theirs to explain and never ours to resolve, and it is NOT evidence of fraud: a seller may have moved their payee and not relisted. Measured only over endpoints we have knocked on, which is our reach and not the catalogue; comparable is the denominator, because an endpoint that names no payee cannot disagree and is counted neither way. THE COUNTS ARE FREE AND THE LIST IS NOT: items comes back NULL without a plan rather than empty, since an empty list would say we found none. Any SINGLE endpoint is free — test_purchase and list_x402_endpoints both carry its own reading — because that one is reproducible in two requests and because withholding something that can cost a buyer money is not a thing we do.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Rows once a plan is held. Default 50, capped at 200. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | The finding in a sentence, with its denominator. |
| items | No | One per disagreeing endpoint: `resource`, `listedPayee`, `quotedPayee`, `seenAt`. NULL without a plan — never an empty array, which would say we found none. |
| limits | Yes | What this is measured over and what a disagreement is not. |
| knocked | Yes | Endpoints we have knocked on at all. The population every other figure here is drawn from. |
| sellers | Yes | How many distinct listed payees those belong to. Worth more than the endpoint count: it says whether this is scattered or a few parties contradicting themselves repeatedly. |
| serving | No | Of those, how many answered with a price at the most recent knock. |
| comparable | Yes | How many could be compared at all: both the endpoint and its listing named a payee. The DENOMINATOR for `disagreeing`. |
| notServing | No | Gone, unreachable or erroring at the most recent knock. A fact about our last look, not a verdict on the seller. |
| disagreeing | Yes | How many name a payee their own listing does not. |
evaluate_actionWeigh one action against a named policyRead-onlyIdempotentInspect
Call this when you are about to DO something and need one answer you can act on: pay an address, connect to an MCP server, call a tool, or put capital into a vault. The answer depends on the AMOUNT, the ACTION, the POLICY you name and how much we actually read — so the same address can be allow for $5 and abstain for $5,000. Four decisions. allow means nothing we could check objects, up to maxAmountUsd, and is NOT a statement that the action is safe: nothing here sees what it is for or what you agreed. review means something we READ does not match, and reasons names which rule. abstain means we did not read enough to have an opinion — our gap, never approval. unsupported means the policy has no rule for this action, and inventing one would be worse than declining. Every rule id in reasons is published in full at the policies tool, including to the party being evaluated. SINCE 2026-10-11 A POLICY JUDGES THE RISK LEVEL, NOT ONLY ITS TRUSTWORTHINESS. risk-band-is-supported asks whether the band survives what we could not read; risk-band-within-policy and controller-risk-within-policy ask whether the band and the control we DID read are ones this policy will commit capital against. Conservative will not allocate into a band worse than moderate, nor where control is thin — one party able to move the money — and returns review rather than abstain, because a band we read as high is a finding about the vault and not a gap in our reading. Permissive declares neither threshold and is unchanged. This closed a real defect: a vault our own vault_check called high risk with 0.5% withdrawable used to come back allow, because every rule about the AVAILABILITY of risk data passed. Free.
| Name | Required | Description | Default |
|---|---|---|---|
| chain | No | The chain the action settles on, e.g. base, polygon, solana. | |
| action | Yes | What you are about to do. | |
| policy | No | A policy version or slug. Defaults to conservative-v1. An unknown name is REFUSED rather than silently replaced with the default. | |
| subject | Yes | What you are about to do it to: an address to pay, an endpoint URL to connect to, or a vault slug. | |
| resource | No | The http(s) endpoint being bought or connected to, where that differs from `subject`. This is what reaches the seller’s own catalogue entry, carrying their price and their payee. | |
| amountUsd | No | What you are about to commit, in US dollars. Leave it out and the amount rules report that they did not run, rather than passing. | |
| requiredChecks | No | Rule ids YOU will not act without, e.g. ["quoted-payee-matches-proposal","live-price-matches-proposal"]. The policy is OUR view of what matters; this is yours. Any one of them that does not reach a verdict — because we could not read it, or because it never applied to what you sent — turns the answer into ABSTAIN instead of ALLOW. It can only ever make the answer more conservative: a required check that passes changes nothing, and a real objection stays a REVIEW rather than being buried as an abstain. An id we do not hold is NAMED in `required.unknownIds` rather than ignored, because a caller whose requirement was never looked at must not read `allow` as it having been met. `list_policies` has every id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | The decision in one sentence, naming the rules that drove it. Written to be shown to whoever authorises the action. |
| rules | No | Every rule considered: `id`, `state` (pass, fail or unknown), `checks` and `says`. THE TWO SENTENCES ARE DIFFERENT THINGS and the distinction is the audit trail. `checks` is the QUESTION the rule asks and never moves; `says` is WHAT WE FOUND and follows the state, so a failing rule reads as a failure. Until 2026-10-13 `says` carried the question in every state, which meant a `fail` arrived beside the claim it had just refuted — a model reading the prose rather than the state got the opposite of the decision. Read `state` to decide and `says` to explain; they can no longer disagree. |
| byArea | No | The same coverage, PER QUESTION: counterparty, payment-intent, service, capital. Read this rather than the single `coverage` when the action moves money. The denominator is the rules the policy holds for that area, NOT the ones that happened to apply — so an area where nothing could be checked reports `none`, which is the fact, instead of reporting high coverage of nothing. |
| limits | No | What a decision here is and is not. `allow` means no rule objected under this policy at this coverage, which is not a statement that the action is safe. |
| policy | No | The policy applied: its intent, its ceiling and the coverage floor below which it abstains. |
| checked | No | WHICH ACCEPTANCE QUESTIONS THIS POLICY PUT AT ALL: `riskBand`, `controller`, `amount`, as booleans. READ THIS BEFORE ACTING ON `decision`. FALSE is the dangerous value and the reason the field exists: it means the question was never put, which is NOT a question that passed. `permissive` returns `allow` on a vault that lost 92.8% of its value because it declares no risk ceiling, and a client reading only `decision` cannot see that. Derived from what the POLICY declares and never from how the subject turned out, so a refusal and a clean pass under one policy carry identical flags. |
| reasons | Yes | Rule ids that decided. Look them up in the policy to see the sentence each one checks. |
| coverage | Yes | How much of what the policy wanted was actually there. Below the policy floor the decision is `abstain` rather than `allow`. |
| decision | Yes | `allow` is not “safe” and `abstain` is not “nothing found”. Read `decisions` in the answer for what each one means. |
| proposal | No | What you asked about, read back, so a typo is visible before you act on the answer. |
| required | No | Present only where you sent `requiredChecks`. `met`, `unmet` and `unknownIds`, with a sentence. An `unmet` entry is why the decision is ABSTAIN. |
| decisions | No | What each decision word means, so a caller never has to guess. Read it before treating `allow` as approval or `abstain` as a clean result. |
| maxAmountUsd | No | The most this policy permits for this proposal. Null where the action moves no money, and null on anything but an `allow`, because a limit printed beside a `review` reads as permission. |
| policyIntent | No | What the policy is FOR. `risk-and-evidence` puts questions about the level AND about what we could read. `evidence-availability` asks only whether we could read enough — which is what `permissive` is: an availability-of-evidence policy rather than an investment risk policy. An `allow` from one is not an `allow` from the other. |
| notApplicable | No | Rules this PROPOSAL does not raise, each with `why` and what to send to have it checked. Distinct from `missingEvidence`, which is a gap in our record: a payment naming no `resource` has no listing to be found in, so those rules do not apply and do not lower coverage. Send `resource` and two more checks run, both decisive. |
| paymentIntent | No | Whether this payment was checked against WHAT IT IS BUYING, in one field. `not-verified` means the policy holds such rules and none of them ran, which on a payment is almost always a missing `resource`: the counterparty may have an excellent record and nothing has compared this amount to this service. `verified` means at least one reached a verdict. `not-applicable` means the policy asks nothing about it, or the action is not a payment. |
| policyVersion | Yes | Carried so an answer given today can be reproduced after the rules change. |
| missingEvidence | No | Rule ids whose evidence we do not hold. These lower `coverage` and are NEVER counted as objections. |
evidence_forEvery edge we hold about one subjectARead-onlyIdempotentInspect
Everything we hold about one subject, as edges, each carrying where it came from. Use it when you need to explain a decision rather than just make one, or to see what is MISSING before you act. Every edge has source, observedAt (when the world was in that state), asOf (when we read it — a fresh read of a stale fact is not a fresh fact), a confidence that names what it is confident IN, its own coverage, and the method that established it. Edges come in three kinds and are NEVER summed: declared is the subject speaking about itself, observed is our reading, derived is arithmetic over the others. Adding them together rebuilds the reputation score this replaces. It infers NO identity: a shared host or funder is reported as exactly that, because being the same party is a conclusion no join supports. lookedForAndMissing lists what we searched for and did not find, so a thin subject never reads as a complete picture. Free.
| Name | Required | Description | Default |
|---|---|---|---|
| subject | Yes | An address, or the http(s) URL of an endpoint. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | What the evidence amounts to, in one sentence. Never a verdict: this tool reports edges and leaves the conclusion to the caller. |
| edges | Yes | Each with claim, object, kind, source, observedAt, asOf, confidence {value, in}, coverage and method. |
| kinds | No | What declared, observed and derived each mean. |
| counts | Yes | Edges by kind. NOT a score: the three are reported apart and never added. |
| limits | No | What this graph cannot contain. Declared, observed and derived are different kinds of fact and are never added together; `counts` keeps them apart for the same reason. |
| subject | Yes | What was asked about, read back. Where we resolved it to something else, this is the resolved form. |
| subjectKind | No | What we took the subject to BE. `unknown` means we could not classify it, so the empty edge list below is our failure to look rather than a finding about the subject. |
| lookedForAndMissing | No | What we searched for and did not find, with why. Listed rather than omitted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world, non-destructive, yet the description still adds substantial behavior: the distinctions between source/observedAt/asOf, the three edge kinds that must never be summed, the refusal to infer identity, and the lookedForAndMissing coverage signal. This is exactly the added context the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then usage, then semantics; each sentence carries meaning. It is dense and slightly sprawling, and some sentences describe output fields that a present output schema already covers, but nothing is idle filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with annotations and an output schema, the description covers when to use it, what each edge means, the no-summing rule, the no-identity-inference rule, missing-data signaling, and cost. Nothing an agent needs to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with a single well-documented 'subject' parameter (address or endpoint URL). The description adds no syntax, format, or edge-case guidance beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States what it returns concretely: every edge held about one subject, each carrying provenance. It also implies differentiation by noting it 'replaces' a reputation score, though it does not name a sibling tool explicitly. Clear but the 'edges' framing is jargon that requires inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use conditions: 'when you need to explain a decision rather than just make one, or to see what is MISSING before you act.' It also implies when-not via the warning that edges are never summed or joined into identity. No named alternatives among siblings, so it stops short of 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_agentsFind agents by what the record showsRead-onlyIdempotentInspect
Find agents to hire by what the chain records rather than what they claim: filter every address ever paid on x402, Virtuals ACP, the Olas mech marketplace or Masumi by independent payers, dealings, ACP completion, whether its declared service answers, whether it pays its own payers back, how spread its own SPENDING is (spreadSuppliers, the one filter here about what the agent rests on rather than who rests on it), and how recently it was paid. Free. An address absent from the result was never paid on a rail we read, which is not the same as never having worked. EVERY ROW CARRIES subject, WHICH IS WHAT WE CAN POSITIVELY SAY IT IS, with the evidence under it. Measured over all 3,077 paid addresses: 1,377 agent, 38 marketplace, 1,662 unknown. agent means we saw agent-protocol work (ACP, Olas mech, Masumi) or saw it HIRE as well as be hired. marketplace means many paid it and it paid many, both above a stated floor. unknown is the largest bucket and is a real answer, not a failure: it means the evidence does not separate an agent from something that merely sells. READ THIS BEFORE FILTERING: a catalogue listing does NOT make a subject an API service. Agents sell priced endpoints too — this platform sells four — so a listing says it sells over HTTP and nothing about which kind of seller. api-service is therefore in the vocabulary and is currently UNREACHABLE: separating it would need evidence that a subject does NOT do agent work, and that is an absence, since 86% of these addresses pay nobody on a rail we read and paying from a second wallet looks identical to buying nothing. Nothing is inferred from a zero and no self-description is read, so a listing calling itself an autonomous agent moves nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| rail | No | x402, acp, mech or masumi. | |
| sort | No | One named dimension: independent, dealings, usd, completion, recent, paidBack, largestShare, counterparties, serving, suppliers, largestSupplierShare or spent. The last three order by what an agent rests on rather than by who rests on it. There is no "best" — nothing here has earned the right to rank. | |
| limit | No | Default 25, maximum 200. | |
| serving | No | Only agents whose declared service answered our last probe. An agent that declares none is excluded, not failed. | |
| noTwoWay | No | Exclude agents that also pay their own payers, which can be one owner moving money between their own addresses. | |
| activeDays | No | Paid within this many days. | |
| registered | No | Only agents holding a registration in a registry we read. A registration is a claim, never a verification. | |
| minDealings | No | Fewest dealings on the rails we read, all time. | |
| minCompletion | No | ACP jobs completed over those that ended, 0 to 1. | |
| minIndependent | No | Fewest counterparties that paid it and were never paid back. The closest thing here to "has real custom". | |
| supplierSpread | No | The precise form of `spreadSuppliers`. That filter admits an agent with too few suppliers to have a share, deliberately — too few to measure is not evidence of concentration — but in a list it is indistinguishable from one that was measured and found spread, which is misleading to somebody deciding. Ask for `diversified` to get only the measured ones. `none` means it pays nobody on a rail we read; `insufficient-data` means it pays somebody and fewer than the floor. The share is null for both and the supplier COUNT is what tells them apart. | |
| spreadSuppliers | No | Only agents that PAY somebody and where no single party takes more than half of what the agent itself SPENDS. The other direction from the concentration of its custom: an agent with forty payers and one supplier looks diversified on every other figure here and is one supplier away from stopping. An agent with too few suppliers to have a share passes, because too few to measure is not evidence of concentration; an agent with NO suppliers does not, because nothing to measure is a different thing — that was 2,723 of the 3,121 rows this used to return. Use `supplierSpread=diversified` for the measured ones alone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asOf | No | When the record behind these rows was last rebuilt. Null means nothing in the answer carries a date, which is a gap in our reading rather than a fact about the agents. |
| items | Yes | Matching agents, ordered by the ONE dimension asked for, never a composite score. Each row carries `subject`: { type, evidence[], alsoShows[], says }. `evidence` names each thing we SAW and, in `supports`, which type it is evidence for — or null where the observation is real and separates nothing, which is the case for a catalogue listing. So `unknown` WITH evidence is the normal shape here and means "we saw these things and they do not settle it", never "we saw nothing". `alsoShows` carries the types a subject also shows evidence for, because they are not exclusive and dropping one would make the label more confident than the evidence. |
| filters | No | What was applied, read back, including what a floor excluded. |
find_vaultsFind a vault by what it has doneRead-onlyIdempotentInspect
Find a vault by what it has DONE rather than what it is called. Free. The filter worth knowing is earned: short returns the vaults where a holder earned LESS than the venue advertises — how many there are is in the answer, never here — and beating the ones where they earned more. It matches only vaults whose realised return is COMPARABLE with an advertised one, which is a SMALL part of the open vaults and the exact share is in vaults_earned, not in this sentence; a venue that quotes nothing or a share price that never moves is excluded rather than counted as in-line, so a short list here means few comparable and not few that performed. Call vault_check on a slug for the full answer.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Part of a name or an address. | |
| chain | No | e.g. base, solana, hyperliquid. | |
| limit | No | Default 25, capped at 100. | |
| earned | No | in-line, beating or short — realised against advertised, comparable cases only. | |
| minTvl | No | Floor on stated size, in US dollars. | |
| maxRisk | No | Ceiling on the published risk score. Scored for a part of the open vaults and not all of them; the unscored are EXCLUDED from a scored filter, which is not the same as scoring well, and the counts are on the answer rather than here. | |
| platform | No | A platform id or its display name, e.g. morpho or Hyperliquid. | |
| minOwnShare | No | Floor on the share of the vault its leader holds, 0 to 1. Readable on Hyperliquid and Drift only, so a floor on it excludes every other venue, where it is ABSENT and not zero. How many that is today is in the answer. Evidence of alignment, never proof: the holder can be a treasury or a custodian. | |
| agentManaged | No | Only vaults a machine runs. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Each with its slug, which vault_check takes. |
| fields | No | Which fields this tool kept from the endpoint’s own rows. |
| warnings | No | READ THESE: an `earned` or `minOwnShare` floor carries what it excluded, and the denominator is not visible from the rows. |
identifyIdentify the party behind an identifierARead-onlyIdempotentInspect
Call this FIRST whenever you hold something other than a wallet address. Give it a transaction hash, an http(s) URL, a hostname or an ERC-8004 registration number and it says which party that is, with the evidence for the link, so the other tools here can then be called with the address. It never picks between candidates: where a hostname or id matches several parties, address comes back null and every candidate is listed, because choosing one would be an identification the evidence does not support. A link through a hostname or a declared endpoint is the subject’s own claim, never proof that they control it. An identifier it cannot resolve is not evidence of anything wrong — read says, which distinguishes "no such thing" from "we do not read that chain". Free.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | What you have: an address (returned as given), a transaction hash (the payee is read from the transfer inside it), a URL or hostname (matched against the x402 catalogue and declared agent endpoints), or an ERC-8004 registration number, optionally as `chain:id`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | The answer in words, including the difference between "no such thing" and "we do not read that chain". |
| check | No | The free check to call next with the address. |
| given | No | What you sent, as sent. |
| kinds | No | What each reading would have meant, so an unrecognised identifier is not a dead end. |
| format | No | What kind of address it is and what we read for it. |
| address | No | The party, or null where the evidence names more than one. Never a guess between candidates. |
| evidence | No | Why each link is claimed, and whether it is the subject’s own claim or something we read. |
| looksLike | No | What the identifier was read as: address, transaction, endpoint, host, agent-id or unrecognised. |
| candidates | No | Every party the identifier could be, where it is not one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld/idempotent annotations, the description reveals critical behavior: it never chooses among multiple candidates, returns null for ambiguous matches while listing all candidates, and clarifies that hostname/endpoint links are claims, not proof. This is exactly the kind of context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence contributes: usage order, accepted inputs, ambiguity behavior, epistemic limits, and error interpretation. It is front-loaded with the most important instruction and has no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists for return values, the description covers everything needed to call the tool correctly: accepted identifier formats, ambiguous-candidate behavior, what constitutes evidence/non-evidence, and how to read failure via `says`. It is complete for an identifier-resolution tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the single `q` parameter at 100% coverage, including the address, transaction hash, URL/hostname, and ERC-8004 forms. The description repeats those forms but does not materially add new parameter-level meaning beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific action—'Call this FIRST'—and states it resolves transaction hashes, URLs, hostnames, and ERC-8004 registrations to a party with evidence. This clearly distinguishes it from sibling tools that operate on wallet addresses.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this tool first whenever you have something other than a wallet address, and that other tools can then be called with the resulting address. It also warns that an unresolvable identifier is not evidence of wrongdoing, setting expectations for follow-up.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_paymentRead the transaction you are about to signRead-onlyIdempotentInspect
Call this with the CALLDATA you are about to sign, before you sign it. Every other check here asks whether an address is worth dealing with; this asks whether the transaction is the one you think it is, and the two catch different losses. No amount of reputation makes the recipient in the bytes match the recipient on your screen, and a spotless counterparty record says nothing about an UNLIMITED APPROVAL granted to it, which is not a payment at all but a standing permission that outlives the transaction. It reads three calls — transferWithAuthorization, approve, transfer — and REFUSES to guess at any other: decoding unknown calldata without the ABI means guessing where each argument begins, and a confident wrong answer about where money goes is worse than none. Amounts are atomic units, never dollars, because the token owns its decimals. Free, needs no key, stores nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | The contract being called, where you know it. On an ERC-20 payment this IS the token: the calldata carries a recipient and an amount and never the asset, so without `to` there is nothing to compare the endpoint’s quoted asset against. | |
| data | No | The calldata, 0x-prefixed. Without it nothing about the transaction is read, and the answer says so rather than passing. | |
| expect | No | What you believe you are doing. Anything you leave out is not compared, and is reported as not compared rather than as agreeing. | |
| resource | No | The http(s) URL of the endpoint you are paying, where there is one. Send it and the answer also compares the bytes with the amount and the payee that endpoint demanded in its own 402 — the check that catches a transaction which is exactly what you meant and is not what the seller asked for. | |
| refreshQuote | No | Knock on `resource` NOW instead of comparing against a stored reading, and set what comes back against the reading it replaced. `againstEndpoint.refreshed.quoteStillMatches` is true, false, or null where the two cannot be compared, with `verdict` as match/changed/unknown and `differs` naming which of amount, asset, network or payee moved. A CHANGED PAYEE is the substitution this whole check exists to catch. Only for an endpoint already in the x402 catalogue we read — we do not fetch a URL because a request named it — and at most one live handshake a minute per resource, shared by every caller. A match is what the endpoint said a moment ago, not a promise about the next moment. | |
| maxQuoteAgeSeconds | No | How old a quote you are willing to act on, in seconds. YOURS, not ours: four hours is alarming for a market quote and irrelevant for a tariff unchanged since March, so a threshold published here would be a number we invented wearing the clothes of a measurement. The answer comes back as `againstEndpoint.standing.freshness` — `within-your-limit` or `older-than-your-limit` — with `freshEnough` as the boolean and your limit echoed back. Without it the answer says `no-limit-given` rather than grading the age. |
Output Schema
| Name | Required | Description |
|---|---|---|
| call | No | What the bytes actually are, or null where it is not a call this decodes. |
| limits | No | What decoding a payment establishes. It reads what the transaction SAYS it will do; it does not simulate it and cannot tell you the recipient is honest. |
| spender | No | Who would be allowed to move your tokens later. Only an approve() has one, and an approve() has nothing else. |
| verdict | Yes | `read` means every comparison you asked for agreed. `mismatch` means at least one did not. `undecodable` means the call is not one this reads and NOTHING was checked — it is not a pass. |
| findings | Yes | One per check, each carrying whether it ran: observation, mismatch, or unknown. |
| selector | No | The four-byte function selector the calldata begins with, where we could read one. Null means the payload is not a call we can decode, which is not evidence that it is bad. |
| recipient | No | Who RECEIVES the money. Null on an approve(), which pays nobody: branch on this rather than on the prose. |
| amountAtomic | No | Atomic units, as a decimal string. The token owns its decimals and this does not apply them. |
| actualTransfer | No | Whether tokens move in THIS transaction. False for an approval, where the amount is a ceiling on what somebody else may take later rather than a sum leaving now. |
| againstEndpoint | No | SENT `resource`? THEN THIS COMPARES THE BYTES WITH WHAT THE ENDPOINT ITSELF IS DEMANDING, which is the one thing `expect` cannot catch: bytes that are exactly what you meant and are not what the seller is asking for. `amount` is `exact-match`, `below-quote`, `above-quote` or `unknown`, in BASE UNITS with no scaling and only where the token the call is made against is the token the quote prices in. **`below-quote` is the expensive one**: the call is refused and the tokens have left. `payee` is `matches`, `differs` or `unknown` against the address the 402 named, and it reads the approved SPENDER on an approval, which pays nobody. `asked: false` means we have never probed that endpoint, which is our gap and not evidence about it. `verdict` above is UNCHANGED by any of this — that is the manifest against YOUR expectation, and the two questions are kept apart on purpose. |
| unlimitedAllowance | No | True where this grants permission to move every token of this kind you will ever hold. |
list_policiesThe policies a decision can be made underARead-onlyIdempotentInspect
The policies evaluate_action can be run under, in full: every rule, its id and the sentence it checks. Published deliberately, including to the agents being evaluated — a rule nobody can read is a rule nobody can correct. Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Each policy with its slug, version, intent, ceiling, coverage floor and rules. |
| says | No | What these policies are and are not. They are rules a decision is checked against, never a ranking of the agents evaluated under them. |
| default | No | The slug of the policy used when a call names none. Read it rather than assume: the default is an operator setting and can change without any tool changing. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive, so the safety profile is covered. The description adds genuine context beyond them: the disclosure is uncensored ('in full', ids plus the sentence each rule checks), deliberately published even to evaluated agents, and carries no cost.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is short and front-loads the essential fact (what the policies are and that all are returned). The closing aphorism about unreadable rules is rhetorical justification rather than operational information, a minor bit of flourish.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing with an output schema that already documents the returned structure, the description supplies everything needed: scope (full set), trust semantics, and cost. Only the absence of any tie-in guidance for evaluate_action keeps it from the top.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4. The description correctly implies a parameterless, whole-set read rather than a filtered one, and adds nothing misleading about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description concretely identifies the resource (the policies evaluate_action runs under) and the payload shape ('every rule, its id and the sentence it checks'), which clearly separates it from the evaluate_action sibling. It never says the verb 'list'/'return', but the meaning is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied through the reference to evaluate_action — an agent can infer you read this to understand what rules will be applied before deciding. There is no explicit when-to-use, when-not, or named alternative, and 'Free' is the only operational hint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_vaultsFind the vault you meanARead-onlyIdempotentInspect
The vaults we read, so a caller holding a name rather than a slug can find the one it means. Free. Absence from this list means we do not read that vault, never that it does not exist.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Part of a vault or platform name, matched as typed. | |
| limit | No | Default 25, maximum 200. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Each with its slug, which is what vault_check takes. |
| fields | No | Which fields this tool kept from the endpoint’s own rows, and where the rest are. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description adds the non-obvious open-world behavior: if a vault is absent from this list, the caller should conclude the service does not read it, not that it does not exist. It also notes the operation is free. Because annotations already cover read-only, idempotent, and non-destructive behavior, the description's additional context is valuable but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exceptionally short and every sentence earns its place: the scope, the use case, the cost, and the key absence semantics. The most important behavioral note is front-loaded. There is no redundant restating of the tool name or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with a full output schema and supportive annotations, this is nearly complete. It explains what is listed, why someone would call it, and the critical interpretation of absence. The only minor gap is the lack of any explicit note about pagination beyond the limit parameter, but the schema covers limit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents both parameters fully with 100% coverage. The description adds only the indirect context that q represents a name rather than a slug, which is already captured by the schema's 'vault or platform name' wording. No meaningful parameter semantics are added beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description conveys that this tool enumerates the vaults this service can read, and frames it as a name-to-vault lookup. It distinguishes the scope by saying 'the vaults we read' and by explaining that absence means no read access, not nonexistence, which separates it from a general vault finder like find_vaults. However, the core verb is implied rather than stated explicitly ('The vaults we read' instead of 'List the vaults...').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear use case: a caller who holds a name rather than a slug can use this to find the intended vault. It also provides an important semantic warning about absence from the list. It does not explicitly name sibling alternatives or state when to prefer find_vaults, but the context is strong enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_x402_endpointsWhat this address sellsRead-onlyIdempotentInspect
WHICH ENDPOINTS A PAYEE SELLS, or which ones match some text. The sharpest check a payment can get is the endpoint being bought, and until this a caller had to know its URL by heart. Nearly every catalogued resource names a payee, and the catalogue holds tens of thousands of them. Every field is the SELLER’s own catalogue entry and never our reading of it, and a listing is not evidence that the endpoint answers — test_purchase knocks on it. priceUsd is their published price and priceRaw is the figure in the asset’s own base units; the two are different claims. FREE.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Part of a URL, matched case-insensitively. | |
| limit | No | Default 20, capped at 100. | |
| payee | No | An address, to list what it sells. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | What the list is and is not: the seller’s own entries, and a listing is not evidence the endpoint answers. |
| count | Yes | How many came back, which is at most `limit` and says nothing about how many exist. |
| items | Yes | One per catalogued endpoint: `resource`, `payTo`, `priceUsd` and `priceRaw`, `asset`, `network`, the seller’s own `description` and when the listing was last seen — every one of those is the SELLER’s claim. `seenByUs` is the only field here that is OURS and the only one they cannot write: `state` (`answering`, `not-answering`, `unconfirmed` — one failure, which is a reason to ask again and not a finding — `seen-once`, or `never-knocked`), `answered` of `knocks`, `lastKnocked`, and an outage as a RANGE in `downAtLeastHours` / `downAtMostHours` rather than as a duration, because a stop happened somewhere between two knocks and that window is as wide as the gap between them. `never-knocked` and `seen-once` are statements about OUR reach, not about the seller, and today they cover most of the catalogue. The full timeline is on `test_purchase`. |
| capped | No | TRUE where the page came back full, so there are probably more; FALSE means the catalogue holds no further match and the list is everything we have, not just the first slice. This replaced a declared `limit` that the answer never carried — the envelope owns the paging keys — and it answers the question that field was for in one go. |
monitor_subjectBe told when the answer about an address changesDestructiveIdempotentInspect
Ask to be told when the answer about an address CHANGES. The dimensions are the ones the counterparty check already answers, so this is that same reading on a schedule rather than a second opinion; what it adds is the comparison. The first run records a reading and reports nothing — there is nothing yet to compare against, and a first reading dressed up as news is the thing this avoids. Idempotent per subject: calling it again edits the watch rather than creating a second. An unknown dimension or policy is REFUSED rather than dropped, because a watch that quietly ignores half of what you asked for is worse than no watch. Needs a key. WHY readOnlyHint IS false: this call writes a row in our store on behalf of the caller, so a second identical call is not free of consequence.
| Name | Required | Description | Default |
|---|---|---|---|
| policy | No | The policy its verdict is read against. An unknown name is refused rather than replaced with a default. | |
| subject | Yes | The address to watch. | |
| dimensions | No | What to watch. All four if you leave it out. An unknown name is refused, not ignored. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The watch, for changing or ending it later. |
| says | No | What this watch will and will not tell you. It reports a CHANGE in what we hold, which is not the same as a change in the world. |
| policy | No | The policy its verdict is read against. Null where the watch names none and the default applies; read `says` for which that is. |
| subject | Yes | The address being watched, read back so a watch cannot be set on the wrong one. |
| dimensions | Yes | What is actually being watched, which is what you asked for or all four. |
| firstReadingAt | No | When the comparison baseline was taken. Null means no reading yet, so nothing can be reported as a change. |
operator_checkWho runs the money, and how much is theirsRead-onlyIdempotentInspect
The question that follows vault_check: who runs the money, and how much of it is their own. Free. Read ownShare with its limits, which travel inside it: the leader’s holding is readable on Hyperliquid and Drift ONLY, so elsewhere it is ABSENT and not zero, the median describes the strategies we can read rather than the manager, and a large own-share is evidence of alignment and never proof, because the address running a vault can be a treasury or a custodian holding for other people. cannotSee names whatever of that applies here. Take the slug from vault_check’s operator.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | The operator’s slug, as vault_check returns it in `operator.slug`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | The operator’s name as published. Their words, not an identity we verified. |
| says | Yes | The operator in one sentence, including what we cannot see about them — own-capital share is readable on two venues only. |
| ownShare | No | Median share of the vault its leader holds, the count it is taken over, and what it does and does not mean. |
| cannotSee | Yes | |
| capitalUsd | No | Capital across every open strategy we read for this operator. Null where none of them can be priced. |
| strategies | No | How many open and closed, and on which platforms. |
| agentManaged | No | How many of their open strategies we have reason to call agent-managed. A COUNT of strategies, never a share of the capital. |
preflight_paymentWeigh one payment before sending itRead-onlyIdempotentInspect
Call this immediately before sending a payment, every time — not once per counterparty. It weighs THIS payment (the amount, the chain, the endpoint) against what the address has actually done: the price the seller themselves published for that endpoint, the address that endpoint names as its payee, the largest payment this address has ever received, and whether it has ever been paid on the chain you are about to use. Answers one of three verdicts. nothing-against-it means every check ran and none objected — it is NOT a statement that the payment is safe, because nothing here can see what the payment is for or what you agreed. look-first means at least one thing we could READ does not match, and the findings say which; a check that could not run never produces it, it produces cannot-say. cannot-say means we did not read enough to have an opinion, and must never be read as the first. Free. Give as much of amountUsd, chain and resource as you have: each one left out is a check that did not run, and the answer says so rather than passing. THE ENDPOINT’S OWN WORD OUTRANKS THE CATALOGUE. Where we have probed the endpoint, againstEndpoint.price carries what it actually demanded and when, ranked above the seller’s listing and above what the address has been paid, with every disagreement between the three kept rather than resolved — live-price-differs-from-listing means the price has MOVED and the live figure is the one to pay, and quoted-payee-is-not-the-one-being-paid means the endpoint asks to be paid somewhere other than where you are sending. live-price-not-comparable means the two prices are in different tokens or one is unnamed, so they were NOT compared rather than compared and found to agree. againstQuote IS THE FIELD TO BRANCH ON: exact-match, below-quote, above-quote or unknown. below-quote is not a pass — the endpoint has said what it wants for THIS call and the payment is under it, so it will not buy the thing unless the terms allow a partial payment, which we cannot see; it is a REVIEW and never a refusal. Paying less than the CATALOGUE’s price is a different question and stays neutral, because a directory entry may price a different unit and was written once. FINDINGS WORTH KNOWING BY NAME. below-listed-price means the payment is under half the seller’s published price: ordinary, not an objection, and NOT a confirmation of the amount either, because the listing may price a different unit or tier — it is neutral and cannot improve the verdict. network-not-comparable means the listing names a network we could not resolve, so the chains were not compared rather than compared and found to agree. A CAIP-2 id and a chain name are resolved through one shared map, so eip155:8453 and base are the same network here and in check_action; they used to disagree.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | The address you are about to pay. | |
| chain | No | The chain you are about to send it on, e.g. base, polygon, solana. | |
| resource | No | The http(s) URL of the endpoint you are buying, where there is one. This is the sharpest check available: its catalogue entry carries the seller’s own price and their own payee address. | |
| amountUsd | No | What you are about to send, in US dollars. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | The verdict in one sentence, naming what did not match. Written to be shown to a person deciding whether to go ahead. |
| check | No | The free counterparty check for this address. |
| limits | No | What this check cannot establish, in full. Quote it whenever you quote the verdict: a clean answer here is the absence of an objection, never a guarantee about the payment. |
| listing | No | The seller’s own catalogue entry for the resource, where there is one — their word, written once, possibly months ago. |
| verdict | Yes | `nothing-against-it` means every check ran and none objected — NOT that the payment is safe. `cannot-say` means too little was read to have an opinion, and must never be read as the first. It is also the answer when nothing contradicted the payment but a check could not run, because reporting our own gap as a clean result would be the worst of the three. |
| findings | No | Every check that ran, each with the record behind it and its own `tone` and `kind`. NOT only the ones that objected: a `tone` of `good` is a check that MATCHED, so reading this array’s length as a count of problems overstates them. Bucket on `kind` — `fact` and `signal` were established, and `unknown` means we could not see, which never counts as something standing against the payment. |
| proposal | No | Your payment as we understood it: payee, amount, chain and resource. Null where too little was given to form one. Check it before reading the verdict, which is about THIS proposal and no other. |
| received | No | What you told us, read back, so a typo is visible. |
| verdicts | No | What each verdict word means, so a caller never has to guess. |
| observations | Yes | Every check that ran, including the ones that could not: a field you left out appears here as a check that did not run, rather than as silence. |
| againstEndpoint | No | WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.againstQuote` is the one word to branch on — `exact-match`, `below-quote`, `above-quote`, `unknown` — and `below-quote` is NOT a pass: the endpoint stated what it wants for this call and less than that does not buy it unless its terms allow a partial payment, which we cannot see. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment. |
record_receiptRecord what you did, so it can be checked laterInspect
Call this AFTER you have paid an address or called a tool, to put what you did on the record. Until now this platform answered "should I" and never heard what happened, which is the difference between a lookup and a control layer: a receipt lets the next question about this subject be asked against a record instead of a guess, and lets a verdict we gave be read back against what followed. reference is YOUR evidence, a transaction hash or the digest of a signed payload, and we store it WITHOUT verifying it. outcome comes back null and stays null until something actually reads what happened, so a receipt nobody has checked never looks like one that settled. Needs a key; a receipt is readable only by the key that wrote it. WHY readOnlyHint IS false: this call writes a row in our store on behalf of the caller, so a second identical call is not free of consequence.
| Name | Required | Description | Default |
|---|---|---|---|
| chain | No | The chain it settled on, where it settled on one. | |
| action | Yes | Which kind of thing you are recording: `payment` for money that left, `tool_call` for a call you made. It decides nothing about verification — both are stored as YOUR claim, with your `reference` as the evidence — but it decides what the receipt can later be reconciled against, and a payment filed as a tool call will never meet the chain reading that would confirm it. | |
| policy | No | The policy you evaluated under, so a later disagreement can be read against what we said at the time. | |
| subject | Yes | The address you acted on. | |
| verdict | No | The decision we gave you before you acted, for the same reason. | |
| deadline | No | ISO 8601 time you expected it by. A time already past is refused, because it is usually seconds where milliseconds were meant. | |
| expected | No | What you expected to follow, in your words. Ours to store and yours to claim. | |
| amountUsd | No | What you committed, in US dollars. | |
| reference | Yes | Your evidence that it happened: a transaction hash, or the digest of a signed payload. Stored, not verified. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The receipt, for asking about it later. |
| says | No | What was and was not verified. |
| outcome | No | Always null here. It stays null until something reads what actually happened; null is "nobody has checked", never "it failed". |
| subject | No | The address the receipt is about, read back, so a receipt cannot be filed against the wrong party. |
| recordedAt | Yes | When we wrote it down. Not when your action happened. |
test_purchaseTest purchase, without payingRead-onlyIdempotentInspect
WALK THE WHOLE PURCHASE OF AN x402 ENDPOINT WITHOUT PAYING, in the order a buyer actually asks the questions, stopping at the first one that objects. Every other tool here answers ONE question about one subject; the losses live between them. Five steps: is the endpoint there, what does it charge RIGHT NOW, does the seller’s own catalogue entry agree with what it just said, does the record say anything against paying that payee under a published policy, and — the step that only exists because this is a rehearsal — is the price still the one the decision was made on, re-read a moment later. A quote that moved between the decision and the signature would authorise something nobody decided on. THE VERDICT HAS THREE STATES AND cannot-tell IS NOT would-proceed: an unanswered question is never rounded up to a passed one. quotedRaw is what the endpoint said, in the asset’s smallest unit, and quotedUsd is NULL unless the catalogue carries both halves of the same token’s pair to scale it — nothing in a payment-requirements document names the decimals, and a figure scaled by a guessed exponent is a hundred-fold error waiting to be quoted. We knock only on endpoints already in the x402 catalogue we read, at most one live handshake a minute per resource, because fetching a URL because a request named it would make us a prober-for-hire pointed at somebody else’s host. Nothing is signed and nothing is spent. FREE.
| Name | Required | Description | Default |
|---|---|---|---|
| fill | No | Values for the slots the SELLER’s own catalogue URL declares, e.g. `{"doi": "10.1000/xyz"}` for a resource listed as `…?doi={doi}`. A SMALL PART of the catalogue is templates rather than plain addresses — `askedWithUnfilled` on the answer names the slots for the endpoint in front of you — and without this we knock with `{doi}` where a value belongs and answer a question nobody asked. ONLY declared slots are accepted: a name the template does not contain is REFUSED rather than ignored, because a parameter silently dropped would let you read the answer as being about the call you meant to make. Values are percent-encoded and the filled URL is verified to reach the same origin and path shape as the catalogue entry, so a value can never choose the host — not even a slot the seller put in their own hostname. A filled rehearsal is ALWAYS a live knock, so inside the one-a-minute cooldown it answers 429 rather than serving back the reading of the unfilled question; and it is NOT written to the endpoint history, because two different questions in one run series would look like a price that moved. | |
| policy | No | A policy version or slug to decide under. Defaults to conservative-v1. | |
| resource | Yes | The http(s) endpoint to rehearse buying. It must be one the x402 catalogue already holds; `list_x402_endpoints` finds it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| live | No | Whether the handshake happened just now or is the stored reading from within the last minute. A stored reading is a weaker claim and this says which it is. |
| says | Yes | The verdict in one sentence: where a careful buyer stops and why, or what could not be answered. An unanswered question is named rather than passed over. |
| payee | No | The address the ENDPOINT named in its handshake, which is not always the one its listing names. That disagreement is step three. |
| steps | No | One per question, in the order a buyer asks them. Each carries `asks` in a person’s words, `state`, `stops` and `says`. |
| because | No | The NAME of the finding that decided it, two or three words, e.g. `Payee mismatch` or `Price moved`. NULL only where nothing decided, which is a clean walk: a verdict must not assert a cause it did not measure. |
| history | No | EVERY TIME WE HAVE KNOCKED, which is the half a checker cannot hold: it sees the endpoint now, only we hold the record of each time we looked. `state` is `answering`, `not-answering`, `unconfirmed` (one failure, which is a reason to ask again and not a finding), `seen-once` or `never-knocked` — the last two are about OUR reach and not about the seller. An outage is published as a RANGE and never as a duration: `downAtLeastHours` counts from the first knock that failed and `downAtMostHours` from the last that answered, because the stop happened somewhere between and that window is as wide as the gap between two knocks. `downAtMostHours` is NULL where nothing has ever answered, since there is then no moment to measure from and zero would read as a bound we do not have. `answered` of `knocks` is the denominator for everything here, `runs` is the timeline oldest first with a knock COUNT per run rather than a span, and `longestFailureRun` is counted in knocks for the same reason. NULL where the endpoint is not one we knock on. |
| network | No | The chain the endpoint asked to be paid on, as it stated it, usually CAIP-2. |
| verdict | No | `would-proceed`, `would-stop` or `cannot-tell`. The third is NOT the first. |
| headline | No | The outcome in three words or fewer: `Purchase stopped`, `Cannot tell` or `A careful buyer would go ahead`. Same fact as `verdict`, in a reader’s words. |
| resource | Yes | The endpoint this is about, read back. |
| askedWith | No | The values we put in, read back, so you can see the question that was actually asked. NULL where you sent none, which is the ordinary case. |
| cannotSee | No | What no rehearsal establishes however well it goes. |
| decidedAt | No | The id of the step that stopped it, so a caller acts on a step rather than parsing a sentence. |
| knockedOn | No | The URL we actually knocked on once your values were in it. NULL where you sent none, in which case it is `resource` unchanged. |
| quotedRaw | No | What it asked for, in the asset’s smallest unit. Always the number the endpoint actually said. |
| quotedUsd | No | The same amount in dollars, NULL where we could not scale it from the catalogue’s own pair. |
| rehearsed | No | False where the endpoint is not in the catalogue, with `says` explaining that we do not fetch a URL because a request named it. |
| askedWithUnfilled | No | Placeholders in the catalogue URL we sent UNFILLED, e.g. `doi`. Empty is the ordinary case: the URL is an address, not a template. Non-empty qualifies the PRICE and not the availability — the endpoint answered and quoted, but for a call with a gap in it, so the figure may be the generic one rather than the price of the call you mean to make. Templates are a small part of the catalogue and `askedWithUnfilled` names the slots on each answer. |
| walkedPastTheStop | No | TRUE where a question after the stopping one was still asked, which is deliberate: halting at the first objection would hide a second. FALSE means the stop was the last thing asked, or nothing stopped at all. Either way nothing financial happened, because none of these steps signs or spends. |
vault_checkWhat the record shows about one vaultRead-onlyIdempotentInspect
Before putting capital into a vault: what the record shows about it. The headline is what a holder ACTUALLY EARNED set against the advertised rate, with the risk band, the components that apply, who runs it, and keys: who can move the money. Read keys.actsAlone before any return figure, because a strategy can be excellent and one private key away from being emptied; across what we read, a single key controls $1.26bn and 47 of 249 multisigs require one signature. Free. Read earned.comparability AND earned.representativeness before quoting the ratio: the first says whether a realised rate can be compared with the advertised one at all, the second whether the result is worth planning around rather than one day that moved, and cannotSee lists everything we could not establish for this vault rather than leaving it as an absence you have to notice. Rates are decimal fractions: 0.0432 is 4.32% a year.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | The vault’s slug, or an address we can resolve to one. Call list_vaults first if you have only a name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| keys | No | Who can move the money, read from the contract. `holds` is multisig, eoa, contract or timelock; `signaturesRequired` is how many a multisig needs; `actsAlone` is true where ONE party can act with no second signature, which covers a single key AND a multisig with a threshold of one — read that rather than the word multisig. `canBeHalted` is null where neither pause function answered, which may mean nobody can stop the vault or may mean its pause is behind a name we do not read — do not read a null as nobody. `notice.basis` is the field to check before trusting a delay: `measured` means we read one, `not-a-timelock` means the controller we read is not a timelock and we do not separately search for one behind it, `unread` means we did not ask. Null means we have not read this vault’s control at all, which is not the same as nobody controlling it. |
| name | No | The vault’s name as the venue publishes it. Their words, and two venues may use the same one. |
| risk | No | The band, the components it was measured from, and `dimensions`. READ `dimensions` BEFORE THE BAND. The band covers market, liquidity, concentration and operating risk and **does not contain the controller at all** — `bandCovers` says so on the object. A vault can read `low` while a single key can empty it, which is exactly what two did. Each dimension carries its own level, the components behind it, and `outsideTheBand`; `controller` and `evidence` are both outside it. A null level is UNREAD and never low. THERE IS NO OVERALL FIGURE and there will not be one: a composite would be the number every reader quotes and none can check. (This used to tell a caller to read `bandRange` first. That field is on the FULL vault document and this tool has never returned it, so the instruction could not be followed; the full document is one link away in `full`.) |
| says | Yes | The finding in one sentence. Where we cannot say what a holder earned, it says that plainly rather than reporting the venue’s own figure as ours. |
| slug | Yes | The vault this answer is about, read back so it cannot be attached to the wrong one. |
| earned | No | Advertised against realised, with the ratio, the verdict and the window. TWO SEPARATE QUESTIONS live here and both must be read: `comparability` is whether the two rates can be set against each other at all, and `representativeness` is whether the result is worth planning around — `typical` where the movement is spread across the window, `event-dominated` where ONE step carries the return, `unknown` where we did not look at the shape. A vault can be `comparable` AND `event-dominated` at once: one was, with a single day accounting for 52% of the movement its return comes from, and a reader seeing only `comparable` planned around a figure that describes an event. `biggestStepShare` is that day’s share of total movement. Null where we have too few price points to say. |
| operator | No | Who runs it, as the venue names them. |
| cannotSee | Yes | What we could not establish. Empty means every check ran. |
| capitalUsd | No | What the vault holds, in US dollars, at `capitalAsOf`. Null where we cannot price the underlying — unread, never zero. |
vault_exit_confidenceCould you get your money back out (paid)IdempotentInspect
Before you put capital in, ask what evidence there is that you could get a PARTICULAR amount back out. Every other reading about a vault is about return or about risk of loss; this is about the practical question a holder has, and it is always about a size: "can I get out" has no answer, "can I get $2m out of a vault with $400k free and 25,941 settled withdrawals behind it" has several. Six readings, each with its own verdict and the question it answers in a holder’s own words: has anybody actually got money out, is there anything in it now, could YOUR amount leave, is somebody queued ahead of you, how much of the capital is lent out, and can somebody change the terms under you. The answer is the WORST of them and never an average — a queue in front of you is not offset by a long history, it happens before your turn — and an unknown outranks a supports, because a gap we could not read must never be counted as a pass. not-asked marks a component whose input you did not send, and not-applicable one this venue does not have at all — only two venues have an exit queue to be behind. Neither is a gap in our record and neither lowers the answer. A withdrawable figure is a FLOOR on venues whose vaults lend into markets holding their own liquidity, and the component says so rather than reading it as a ceiling. NOTHING HERE IS A GUARANTEE of withdrawal and no sentence it emits contains the word: a vault that has paid everybody for a year can stop tomorrow. PAID.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | The vault’s slug, or its contract address — either resolves. | |
| amountUsd | No | What you are thinking of taking out, in dollars. Send it: without it the sizing component reports `not-asked` and you get the general picture rather than an answer about you. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | The worst component in one sentence, with what it does and does not mean. |
| slug | Yes | The vault this is about, read back, so an answer cannot be attached to the wrong one. |
| limits | Yes | Why the answer is the worst component rather than an average, and why no sentence here contains the word guarantee. |
| summary | Yes | The worst component. Never an average and never a score. |
| verdicts | No | What each verdict means, beside the answer rather than in documentation you have to find. |
| amountUsd | No | The amount asked about. Null means the sizing did not run. |
| cannotSee | Yes | What this structurally cannot contain, so a supporting answer is never read as an assured exit. |
| components | Yes | Each reading: `key`, the `asks` it answers, its `verdict` and what it read. |
vault_exitsWhat actually left a vaultRead-onlyIdempotentInspect
Before putting capital somewhere, ask what has actually LEFT it. Every liquidity figure elsewhere is a level at an instant — how much could be withdrawn right now. This is the other half: withdrawals that SETTLED, over 7, 30 and 90 days, with the largest single exit we have ever recorded and the day it happened. Measured on the largest vault we read: $52.8M declared withdrawable against $265.8M actually withdrawn over thirty days, so a holder reading only the declared figure would badly underestimate what the vault has been able to pay. A LEVEL and a FLOW are never divided by one another and this returns no ratio between them. We see withdrawals that settled and NOT an attempt that reverted, a queue somebody waited in, or a gate that refused them. An empty register therefore has FOUR readings, not two: “nobody withdrew”, “nobody could”, “a reader asked and found nothing at all”, and “no reader has ever asked”. haveFlowHistory separates the first two from the last two and lastReadAt separates those — null there means nobody has ever looked, so the register is not a weak reading of the vault but the absence of one. haveFlowHistory separates the third from the first two, and where it is false every figure is NULL rather than zero. Every answer dates itself: capitalAsOf and declaredAsOf say when each level was read, flowsNewestAt how far our movement history reaches, and windowsEndAt the instant the windows count back from. For a capital decision the age of the record is part of the record. Free.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | The vault’s slug, or its contract address — either resolves. Until 2026-10-08 this route was the one of eight that took the slug only, so an agent holding an address got a 404 here and a 200 everywhere else. | |
| exitAmountUsd | No | A position to weigh the exit against, in US dollars, e.g. 500000. Turns "can we READ the withdrawable figure" into "could I get THIS much back out". The verdict is deliberately named for what was observed rather than for a promise: `covered-now` means the amount is inside what the vault declares withdrawable AT THE MOMENT WE READ IT, and the answer carries when that was and what it cannot see — queues, notice periods, failed attempts, other holders leaving at the same time. |
Output Schema
| Name | Required | Description |
|---|---|---|
| says | Yes | What actually left, against what the vault advertises as withdrawable, in one sentence. |
| slug | Yes | The vault this register is for, read back so an answer cannot be attached to the wrong vault. |
| readBy | No | Which reader last asked, e.g. `vault-flows`, `morpho-flows`, `solana-flows`. |
| tvlUsd | No | What the vault holds, for scale beside the withdrawals. A LEVEL, never to be divided into the flow figures in `windows`. Null means unread, not empty. |
| windows | Yes | FLOWS over 7, 30 and 90 days plus all time: count, total, largest single, most recent. Never a share of the level. Every figure is NULL where `haveFlowHistory` is false, because a zero would claim we looked. Each window carries `window` as well as `days`: `7d`, `30d`, `90d` or `allTime`. `days: 0` is the all-time one and reads as a zero-day window if you only look at the number, which is why the name is there. |
| cannotSee | Yes | What this register structurally cannot contain, so an empty one is never read as an easy exit. |
| lastReadAt | No | When a reader last ASKED about this vault, found or not — which `flowsNewestAt` cannot tell you. Eighteen withdrawals with the newest eleven months ago is a vault that went quiet OR a vault we stopped reading, and only this separates them. NULL MEANS NO READER HAS EVER ASKED: the vault is outside what our flow readers cover, so an empty register is not a weak reading of it, it is the absence of one. |
| capitalAsOf | No | When `tvlUsd` was read. Same name and same column as `vault_check` uses. |
| readToBlock | No | How far through the chain that pass actually got. Not the same as `lastReadAt`: a reader that ran a minute ago but is 400,000 blocks behind looked recently at an old part of the chain, and only this says so. Null where the reader has no block to report. |
| declaredAsOf | No | When `declaredWithdrawableUsd` was read. NULL means we hold no stamp for it rather than that it is fresh — 180 of the 809 declared levels we hold come from a writer that does not stamp them. |
| exitCapacity | No | Present ONLY where you sent `exitAmountUsd`, and null otherwise. TWO READINGS, NEVER AVERAGED: `now` is `covered-now`, `above-declared` or `unknown` against what the vault declares withdrawable at this instant — THEIR figure, an instant and not a promise, and not a queue or a notice period; `everThisLarge` is whether a single withdrawal at least that size has ever been recorded here, and it is NULL rather than false where we hold no flow history, because never having seen one is not evidence it cannot happen. `shareOfDeclared` is the position as a share of that declared figure, null where there is nothing to divide by. `cannotSee` names what no withdrawable figure contains: queues, notice periods, failed attempts, and other holders leaving at the same moment as you. |
| windowsEndAt | Yes | The instant every window counts back from, so the 7-day and 30-day figures share an edge and either can be reproduced. It is a window boundary and NOT a freshness claim: the ages of the data are `capitalAsOf`, `declaredAsOf` and `flowsNewestAt`, and `meta.freshness` is computed from those. |
| flowsNewestAt | No | The newest movement of any kind we hold for this vault. |
| largestEverAt | No | When `largestEverUsd` was taken out. An old date beside a large figure is the whole point: it says the exit was possible then, not now. |
| largestEverUsd | No | Somebody actually got this much out, on `largestEverAt`. Evidence about the past, never a promise about now. |
| haveFlowHistory | Yes | Whether we hold ANY movement for this vault, of either direction. FALSE means the empty register is our silence and not the vault’s: it says nothing about whether anybody got out. Of 3,672 open vaults on 2026-10-10, 2,673 are in this state. |
| flowsNewestAnywhereAt | No | The newest movement we hold for ANY vault. Read beside the field above it tells a quiet vault from a stopped reader, which is what every zero here turns on. |
| declaredWithdrawableUsd | No | A LEVEL at this instant. Null where we cannot read it, which is not zero. |
vault_risk_dimensionsSix risks across every vault we scoreIdempotentInspect
SIX RISKS, NOT ONE WORD, across every vault we score. A risk band is a weighted whole and a reader takes it as a summary of everything, which it is not: ours weighs drawdown, crowding, exit, concentration and consistency, and it contains NO reading of who may move the money. Two vaults read low while a multisig needing a single signature controlled them. So this groups what is already measured into market, liquidity, concentration and operating risk, ADDS the controller as its own dimension, and ADDS evidence — how much of the vault we could read at all. There is deliberately NO overall figure: a composite would be the number everybody quotes and nobody can check. THE FINDING IS FREE: population says how many scored vaults carry a band that reads BETTER than one of their own dimensions, and how many of those read worse on a dimension the band never contained — which is the number to read before trusting any one word on this platform. THE LIST IS PAID (dimensions.read): which vaults, with each one’s six levels, what it holds, and a sentence naming the disagreement. locked says when it is withheld, so an empty items is never mistaken for no matches — denominators.matchedTheFilter counts them either way. For ONE vault the whole table is FREE at vault_check, which also computes what else it could not see. Filter with dimension and level to run the screen that matters, e.g. the vaults whose controller reads high.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | The level to keep. With `dimension` it applies to that one; alone it keeps any vault reading this on ANY dimension, which is the fastest way to find everything that reads `severe` somewhere. | |
| limit | No | Rows to return, 1 to 200, default 50. The population figures are over EVERYTHING scored and never over the page. | |
| offset | No | Rows to skip, for walking a long list. `denominators.matchedTheFilter` is the total to walk. | |
| dimension | No | Keep only vaults with a READING on this dimension, and with `level` keep only those at that level. Without `level` it keeps every vault whose dimension read at all, which excludes the unread — an unread dimension is our coverage and never a level. | |
| disagreeing | No | Send `true` to keep only the vaults whose overall band reads BETTER than at least one of their own dimensions. This is the screen the dimensions exist for: it is where reading the single word would have misled you. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asOf | No | When this was assembled. Each row carries its own `asOf`: the scores were taken at different moments, so this is a register of readings and not a snapshot. |
| items | Yes | PAID. One row per vault: `slug`, `name`, `tvlUsd`, `band`, `levels` keyed by dimension, `coverage` with the component COUNTS behind the evidence dimension, `worseThanBand`, `outsideTheBand`, `says` and `asOf`. EMPTY where withheld, which `locked` states — never read an empty list here as no matches. |
| limits | Yes | What this route does not do: nothing here is a new measurement, and its evidence dimension counts components only — `coverage.cannotSeeCount` is 0 for every vault and means NOT COMPUTED HERE, not "nothing was unreadable". The per-vault `vault_check` computes it properly and is free. |
| locked | No | Null for a caller entitled to the list. Otherwise it names the capability, the number of free rows, and says plainly that the rest is withheld rather than absent. |
| withheld | Yes | How many matching vaults are NOT in `items`. Zero for an entitled caller. For everybody else it is the difference between what matched and the free rows, so a short list is never mistaken for a short population. |
| population | Yes | FREE. `scored` is the denominator, `disagreeing` how many carry a band better than one of their dimensions, `withARiskOutsideTheBand` how many read worse on a dimension the band does not contain, `byDimension` which dimension does it and how often, and `says` the finding in a sentence. Computed over everything scored, BEFORE any filter: a headline over a filtered set would be a headline about the filter. |
| denominators | Yes | What every figure above is over: `openVaults`, `scored`, `neverScored` (named rather than left to subtraction, because a vault nobody scored must never read as one that scored well), `matchedTheFilter` and `returned`. |
vaults_earnedWhat depositors kept, against what was advertisedRead-onlyIdempotentInspect
What depositors actually KEPT, against what their vault advertised. READ population BEFORE QUOTING ANY SHARE FROM THIS. The comparison covers only the vaults where we hold BOTH an advertised rate and a realised one, which is a narrow and lopsided set, usually dominated by one venue: population.largestVenue names it and population.concentration says how much of the set it is. A share from here is a statement about those vaults, never about DeFi and never about this whole site. Not the vault’s return, which is what a unit held throughout would have earned: this is read from the depositor register, per vault, and set against the venue’s own quote scaled to how long those depositors have held. Measured today: of the vaults with a comparison, four in five gave their depositors less, at a median of thirty points short. ADVERTISED RATES ARE DECIMAL FRACTIONS and some are in the hundreds of per cent: 0.042 is 4.2% and 4.2 is 420%. Those survive a stated band of -1 to 5 (-100% to 500%); advertisedBand.refused says how many readings the band threw out, and advertisedIsHigh marks each row above 100% so a remarkable figure cannot be mistaken for a misplaced decimal. TWO THINGS TO REPEAT WHENEVER QUOTING IT. A depositor who withdrew everything is not in the register and the ones who left after losing are exactly the ones a return figure most needs, so this reads BETTER than the truth rather than worse; and gapPoints is percentage POINTS, not per cent, because a depositor cannot lose more than they put in. The aggregate and the widest gaps are free; the rest of the list needs the earned.detail capability and withheld says how many are missing.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | name, slug, venue, advertised, advertisedIsHigh, kept, gapPoints, medianDaysHeld. Widest gap first. |
| limits | Yes | What this cannot tell you, including the survivorship inside the register. Quote it with the numbers. |
| returned | No | Rows in this answer. |
| withheld | No | Rows the plan does not carry. Zero with earned.detail. |
| comparable | Yes | Vaults where the two sides can be set against each other at all. This is the population every share here is over. |
| population | No | Who the comparison is actually about: listed, comparable, byVenue, largestVenue, concentration and isOneVenue. `listed` is how many survived the advertised band and are in `byVenue`; `comparable` is the job own count. They are different counts and must never be divided into one another. Where isOneVenue is true the figure is a reading about that one venue in a market-wide sentence. |
| losingShare | No | Measured depositors who are down, as a decimal fraction. |
| advertisedBand | No | minDecimal, maxDecimal, refused and means. Advertised rates are decimal fractions, so a value above 1 is above 100%; readings outside the band are refused rather than counted as zero. |
| shortOfAdvertised | No | Of those, how many gave their depositors less. |
| shortOfAdvertisedShare | No | The headline share, as a decimal fraction. Never quote it without `population` beside it. |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
- Changed
vault_exits2 fields changed- added
Input schema / exitAmountUsdAdded value: +{ + "description": "A position to weigh the exit against, in US dollars. Turns \"can we READ the withdrawable figure\" into \"could I get THIS much back out\", which the auditor who asked for it rightly called a different question.", + "type": "number" +} - added
Output schema / properties / exitCapacityAdded value: +{ + "description": "Present ONLY where you sent `exitAmountUsd`, and null otherwise. TWO READINGS, NEVER AVERAGED: `now` is `covered-now`, `above-declared` or `unknown` against what the vault declares withdrawable at this instant — THEIR figure, an instant and not a promise, and not a queue or a notice period; `everThisLarge` is whether a single withdrawal at least that size has ever been recorded here, and it is NULL rather than false where we hold no flow history, because never having seen one is not evidence it cannot happen. `shareOfDeclared` is the position as a share of that declared figure, null where there is nothing to divide by. `cannotSee` names what no withdrawable figure contains: queues, notice periods, failed attempts, and other holders leaving at the same moment as you.", + "type": [ + "object", + "null" + ] +}
1 tool update
- Changed
evaluate_action2 fields changed- added
Output schema / properties / checkedAdded value: +{ + "description": "WHICH ACCEPTANCE QUESTIONS THIS POLICY PUT AT ALL: `riskBand`, `controller`, `amount`, as booleans. READ THIS BEFORE ACTING ON `decision`. FALSE is the dangerous value and the reason the field exists: it means the question was never put, which is NOT a question that passed. `permissive` returns `allow` on a vault that lost 92.8% of its value because it declares no risk ceiling, and a client reading only `decision` cannot see that. Derived from what the POLICY declares and never from how the subject turned out, so a refusal and a clean pass under one policy carry identical flags.", + "type": "object" +} - added
Output schema / properties / policyIntentAdded value: +{ + "description": "What the policy is FOR. `risk-and-evidence` puts questions about the level AND about what we could read. `evidence-availability` asks only whether we could read enough — which is what `permissive` is: an availability-of-evidence policy rather than an investment risk policy. An `allow` from one is not an `allow` from the other.", + "enum": [ + "risk-and-evidence", + "evidence-availability" + ], + "type": "string" +}
1 tool update
- Changed
evaluate_action1 field changed- changed
Output schema / properties / rules / descriptionPrevious value: -"Every rule considered, each pass, fail or unknown. The audit trail for the decision."New value: +"Every rule considered: `id`, `state` (pass, fail or unknown), `checks` and `says`. THE TWO SENTENCES ARE DIFFERENT THINGS and the distinction is the audit trail. `checks` is the QUESTION the rule asks and never moves; `says` is WHAT WE FOUND and follows the state, so a failing rule reads as a failure. Until 2026-10-13 `says` carried the question in every state, which meant a `fail` arrived beside the claim it had just refuted — a model reading the prose rather than the state got the opposite of the decision. Read `state` to decide and `says` to explain; they can no longer disagree."
8 tool updates
- Changed
agent_changes1 field changed- changed
Output schema / properties / capped / descriptionPrevious value: -"The page was full, so there may be more. A cap is not a count."New value: +"TRUE where the page came back full, so ask again with an `offset`; FALSE means nothing moved after these rows in the window asked for, so the feed is complete rather than merely begun. A cap is not a count."
- Added
agent_economic_profile - Added
endpoint_disagreements - Changed
evaluate_action4 fields changed- added
Input schema / properties / requiredChecksAdded value: +{ + "description": "Rule ids YOU will not act without, e.g. [\"quoted-payee-matches-proposal\",\"live-price-matches-proposal\"]. The policy is OUR view of what matters; this is yours. Any one of them that does not reach a verdict — because we could not read it, or because it never applied to what you sent — turns the answer into ABSTAIN instead of ALLOW. It can only ever make the answer more conservative: a required check that passes changes nothing, and a real objection stays a REVIEW rather than being buried as an abstain. An id we do not hold is NAMED in `required.unknownIds` rather than ignored, because a caller whose requirement was never looked at must not read `allow` as it having been met. `list_policies` has every id.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / byAreaAdded value: +{ + "description": "The same coverage, PER QUESTION: counterparty, payment-intent, service, capital. Read this rather than the single `coverage` when the action moves money. The denominator is the rules the policy holds for that area, NOT the ones that happened to apply — so an area where nothing could be checked reports `none`, which is the fact, instead of reporting high coverage of nothing.", + "items": { + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / paymentIntentAdded value: +{ + "description": "Whether this payment was checked against WHAT IT IS BUYING, in one field. `not-verified` means the policy holds such rules and none of them ran, which on a payment is almost always a missing `resource`: the counterparty may have an excellent record and nothing has compared this amount to this service. `verified` means at least one reached a verdict. `not-applicable` means the policy asks nothing about it, or the action is not a payment.", + "type": "object" +} - added
Output schema / properties / requiredAdded value: +{ + "description": "Present only where you sent `requiredChecks`. `met`, `unmet` and `unknownIds`, with a sentence. An `unmet` entry is why the decision is ABSTAIN.", + "type": "object" +}
- Changed
find_agents1 field changed- changed
Input schema / properties / spreadSuppliers / descriptionPrevious value: -"Only agents where no single party takes more than half of what the agent itself SPENDS. The other direction from the concentration of its custom: an agent with forty payers and one supplier looks diversified on every other figure here and is one supplier away from stopping. An agent with too few suppliers to have a share passes, because too few to measure is not evidence of concentration."New value: +"Only agents that PAY somebody and where no single party takes more than half of what the agent itself SPENDS. The other direction from the concentration of its custom: an agent with forty payers and one supplier looks diversified on every other figure here and is one supplier away from stopping. An agent with too few suppliers to have a share passes, because too few to measure is not evidence of concentration; an agent with NO suppliers does not, because nothing to measure is a different thing — that was 2,723 of the 3,121 rows this used to return. Use `supplierSpread=diversified` for the measured ones alone."
- Changed
inspect_payment2 fields changed- added
Input schema / properties / maxQuoteAgeSecondsAdded value: +{ + "description": "How old a quote you are willing to act on, in seconds. YOURS, not ours: four hours is alarming for a market quote and irrelevant for a tariff unchanged since March, so a threshold published here would be a number we invented wearing the clothes of a measurement. The answer comes back as `againstEndpoint.standing.freshness` — `within-your-limit` or `older-than-your-limit` — with `freshEnough` as the boolean and your limit echoed back. Without it the answer says `no-limit-given` rather than grading the age.", + "type": "number" +} - added
Input schema / properties / refreshQuoteAdded value: +{ + "description": "Knock on `resource` NOW instead of comparing against a stored reading, and set what comes back against the reading it replaced. `againstEndpoint.refreshed.quoteStillMatches` is true, false, or null where the two cannot be compared, with `verdict` as match/changed/unknown and `differs` naming which of amount, asset, network or payee moved. A CHANGED PAYEE is the substitution this whole check exists to catch. Only for an endpoint already in the x402 catalogue we read — we do not fetch a URL because a request named it — and at most one live handshake a minute per resource, shared by every caller. A match is what the endpoint said a moment ago, not a promise about the next moment.", + "type": "boolean" +}
- Added
list_x402_endpoints - Added
test_purchase
1 tool update
- Changed
find_agents1 field changed- added
Input schema / properties / supplierSpreadAdded value: +{ + "description": "The precise form of `spreadSuppliers`. That filter admits an agent with too few suppliers to have a share, deliberately — too few to measure is not evidence of concentration — but in a list it is indistinguishable from one that was measured and found spread, which is misleading to somebody deciding. Ask for `diversified` to get only the measured ones. `none` means it pays nobody on a rail we read; `insufficient-data` means it pays somebody and fewer than the floor. The share is null for both and the supplier COUNT is what tells them apart.", + "enum": [ + "diversified", + "concentrated", + "insufficient-data", + "none" + ], + "type": "string" +}
1 tool update
- Changed
inspect_payment3 fields changed- added
Input schema / properties / resourceAdded value: +{ + "description": "The http(s) URL of the endpoint you are paying, where there is one. Send it and the answer also compares the bytes with the amount and the payee that endpoint demanded in its own 402 — the check that catches a transaction which is exactly what you meant and is not what the seller asked for.", + "type": "string" +} - changed
Input schema / properties / to / descriptionPrevious value: -"The contract being called, where you know it."New value: +"The contract being called, where you know it. On an ERC-20 payment this IS the token: the calldata carries a recipient and an amount and never the asset, so without `to` there is nothing to compare the endpoint’s quoted asset against." - added
Output schema / properties / againstEndpointAdded value: +{ + "description": "SENT `resource`? THEN THIS COMPARES THE BYTES WITH WHAT THE ENDPOINT ITSELF IS DEMANDING, which is the one thing `expect` cannot catch: bytes that are exactly what you meant and are not what the seller is asking for. `amount` is `exact-match`, `below-quote`, `above-quote` or `unknown`, in BASE UNITS with no scaling and only where the token the call is made against is the token the quote prices in. **`below-quote` is the expensive one**: the call is refused and the tokens have left. `payee` is `matches`, `differs` or `unknown` against the address the 402 named, and it reads the approved SPENDER on an approval, which pays nobody. `asked: false` means we have never probed that endpoint, which is our gap and not evidence about it. `verdict` above is UNCHANGED by any of this — that is the manifest against YOUR expectation, and the two questions are kept apart on purpose.", + "type": [ + "object", + "null" + ] +}
1 tool update
- Changed
preflight_payment1 field changed- changed
Output schema / properties / againstEndpoint / descriptionPrevious value: -"WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment."New value: +"WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.againstQuote` is the one word to branch on — `exact-match`, `below-quote`, `above-quote`, `unknown` — and `below-quote` is NOT a pass: the endpoint stated what it wants for this call and less than that does not buy it unless its terms allow a partial payment, which we cannot see. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment."
1 tool update
- Changed
check_action1 field changed- changed
Output schema / properties / crossChecks / descriptionPrevious value: -"The comparisons between parts. Each names the TWO readings that disagree. The ones that AGREED are published too, because a comparison that ran and agreed is different from one that never ran."New value: +"The comparisons between parts. Each names the TWO readings that disagree. The ones that AGREED are published too, because a comparison that ran and agreed is different from one that never ran. `tone` is `bad`, `warn`, `good` or `neutral`, and the fourth is the one to read carefully: a NEUTRAL check established nothing and can neither improve nor worsen the verdict. `the-price-has-moved-since-the-listing` compares the endpoint’s own quote with its catalogue entry in BASE UNITS after checking that both name the same token, so it is exact; where the tokens differ or either is unnamed it reports `the-two-prices-are-not-comparable` instead, because a 402 states an amount in the asset’s smallest unit and never its decimals. The same rule is applied by `preflight_payment` and `evaluate_action`."
1 tool update
- Changed
agent_dependencies2 fields changed- added
Output schema / properties / readAdded value: +{ + "description": "HOW CURRENT THE RAIL BEHIND THIS IS. Recomputed from the payments table on every call, never a stored snapshot — but only as current as the chain that has fallen FURTHEST BEHIND, which is the date given, not the chain most recently read. `furthestBehind` names it and `stalled` lists any chain reporting an error, which may be further behind still. A dependency formed after `railReadAt` is not here yet. Do not confuse it with `firstAt`/`lastAt` on each party: those are when payments HAPPENED.", + "type": "object" +} - changed
Output schema / requiredPrevious value: -[ - "agents", - "shared", - "says", - "cannotSee", - "limits" -]New value: +[ + "agents", + "shared", + "says", + "cannotSee", + "limits", + "read" +]
1 tool update
- Changed
preflight_payment2 fields changed- added
Output schema / properties / againstEndpointAdded value: +{ + "description": "WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment.", + "type": [ + "object", + "null" + ] +} - changed
Output schema / properties / listing / descriptionPrevious value: -"The seller’s own catalogue entry for the resource, where there is one. The sharpest check available."New value: +"The seller’s own catalogue entry for the resource, where there is one — their word, written once, possibly months ago."
12 tool updates
- Added
agent_business - Added
agent_dependencies - Added
check_action - Changed
check_service_endpoint1 field changed- added
Output schema / properties / unpaidProbeAdded value: +{ + "description": "OUR OWN unpaid x402 handshake with this URL, which is the free availability test for an endpoint no agent registered. x402 requires a server to answer an unpaid request with 402 and its requirements BEFORE doing any work, so the first half of every real client’s handshake costs nothing and proves three things: the host is there, it still speaks x402, and what it asks for NOW. `outcome` is one of quoting, open, refusing, gone, error, unreachable — `open` means it answered 200 unpaid, so it is up and not charging on this path. `quoted.amount` is in the asset’s own smallest unit and is NOT scaled to dollars, because nothing in the requirements document says how many decimals the asset has. Read it beside `price`, which is what the catalogue recorded whenever that entry was written; a price that has moved is a finding neither one shows alone. Null means we have not run this probe here, which is not a finding about the endpoint.", + "type": [ + "object", + "null" + ] +}
- Changed
counterparty_check1 field changed- changed
Output schema / properties / independence / descriptionPrevious value: -"payers, linked, viaParties, largestGroup: payers of this address that share an OBSCURE third party with another of its payers. This is the test of `dealings.independent`, which counts payers that never paid it back and has never been proof they are different parties. A party paid by two to ten addresses in all counts; a hub paid by more does not, because two agents both paying a hub have shown only that the hub is popular. EVIDENCE OF A LINK, NEVER PROOF OF ONE OPERATOR — two payers paying one small service are two customers of that service. `groups` names which payers and through what and needs the `independence.test` capability; where it is withheld, `capability` says so. A linked count of zero is not proof they are unrelated: one owner funding addresses that never touch each other again leaves nothing for this to find."New value: +"payers, linked, viaParties, largestGroup: payers of this address that share an OBSCURE third party with another of its payers. This is the test of `dealings.independent`, which counts payers that never paid it back and has never been proof they are different parties. A party paid by two to ten addresses in all counts; a hub paid by more does not, because two agents both paying a hub have shown only that the hub is popular. EVIDENCE OF A LINK, NEVER PROOF OF ONE OPERATOR — two payers paying one small service are two customers of that service. `groups` names which payers and through what and needs the `independence.test` capability; where it is withheld, `capability` says so. A linked count of zero is not proof they are unrelated: one owner funding addresses that never touch each other again leaves nothing for this to find. `differentPopulation` IS PRESENT WHEN THIS BLOCK AND THE RECORD ABOVE IT COUNT DIFFERENT NUMBERS OF PAYERS, which happens because they are two jobs on two schedules: it carries `why: \"different_population_snapshots\"`, both counts and both dates. Neither figure is wrong, and the linkage here describes the population in THIS block, not the larger one. It is null when they agree, so its presence means something."
- Changed
evaluate_action1 field changed- added
Output schema / properties / notApplicableAdded value: +{ + "description": "Rules this PROPOSAL does not raise, each with `why` and what to send to have it checked. Distinct from `missingEvidence`, which is a gap in our record: a payment naming no `resource` has no listing to be found in, so those rules do not apply and do not lower coverage. Send `resource` and two more checks run, both decisive.", + "items": { + "type": "object" + }, + "type": "array" +}
- Changed
find_agents1 field changed- changed
Output schema / properties / items / descriptionPrevious value: -"Matching agents, ordered by the ONE dimension asked for, never a composite score."New value: +"Matching agents, ordered by the ONE dimension asked for, never a composite score. Each row carries `subject`: { type, evidence[], alsoShows[], says }. `evidence` names each thing we SAW and, in `supports`, which type it is evidence for — or null where the observation is real and separates nothing, which is the case for a catalogue listing. So `unknown` WITH evidence is the normal shape here and means \"we saw these things and they do not settle it\", never \"we saw nothing\". `alsoShows` carries the types a subject also shows evidence for, because they are not exclusive and dropping one would make the label more confident than the evidence."
- Changed
inspect_payment3 fields changed- added
Output schema / properties / actualTransferAdded value: +{ + "description": "Whether tokens move in THIS transaction. False for an approval, where the amount is a ceiling on what somebody else may take later rather than a sum leaving now.", + "type": "boolean" +} - changed
Output schema / properties / recipient / descriptionPrevious value: -"Who the bytes pay, read from the payload rather than from a label."New value: +"Who RECEIVES the money. Null on an approve(), which pays nobody: branch on this rather than on the prose." - added
Output schema / properties / spenderAdded value: +{ + "description": "Who would be allowed to move your tokens later. Only an approve() has one, and an approve() has nothing else.", + "type": [ + "string", + "null" + ] +}
- Changed
vault_check1 field changed- changed
Output schema / properties / risk / descriptionPrevious value: -"The band, the share of components we could measure, and each applying component in its own words."New value: +"The band, the share of components we could measure, and each applying component in its own words. READ `bandRange` BEFORE ACTING ON `band`: the score renormalises over what read, so it is what the vault scores if the unread part behaves like the read part. `bandRange` fills the unread weight with its best and its worst and names the band at each end — on one vault, moderate at 27 but anywhere from low (15) to high (60) on the 45% we cannot read. It collapses onto the band itself when every applying component was read, so a narrow range is a fact and not a formality. Null on a record not yet rescored, which `measured` tells apart from fully measured."
- Added
vault_exit_confidence - Changed
vault_exits11 fields changed- added
Output schema / properties / capitalAsOfAdded value: +{ + "description": "When `tvlUsd` was read. Same name and same column as `vault_check` uses.", + "format": "date-time", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / declaredAsOfAdded value: +{ + "description": "When `declaredWithdrawableUsd` was read. NULL means we hold no stamp for it rather than that it is fresh — 180 of the 809 declared levels we hold come from a writer that does not stamp them.", + "format": "date-time", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / flowsNewestAnywhereAtAdded value: +{ + "description": "The newest movement we hold for ANY vault. Read beside the field above it tells a quiet vault from a stopped reader, which is what every zero here turns on.", + "format": "date-time", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / flowsNewestAtAdded value: +{ + "description": "The newest movement of any kind we hold for this vault.", + "format": "date-time", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / haveFlowHistoryAdded value: +{ + "description": "Whether we hold ANY movement for this vault, of either direction. FALSE means the empty register is our silence and not the vault’s: it says nothing about whether anybody got out. Of 3,672 open vaults on 2026-10-10, 2,673 are in this state.", + "type": "boolean" +} - added
Output schema / properties / lastReadAtAdded value: +{ + "description": "When a reader last ASKED about this vault, found or not — which `flowsNewestAt` cannot tell you. Eighteen withdrawals with the newest eleven months ago is a vault that went quiet OR a vault we stopped reading, and only this separates them. NULL MEANS NO READER HAS EVER ASKED: the vault is outside what our flow readers cover, so an empty register is not a weak reading of it, it is the absence of one.", + "format": "date-time", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / readByAdded value: +{ + "description": "Which reader last asked, e.g. `vault-flows`, `morpho-flows`, `solana-flows`.", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / readToBlockAdded value: +{ + "description": "How far through the chain that pass actually got. Not the same as `lastReadAt`: a reader that ran a minute ago but is 400,000 blocks behind looked recently at an old part of the chain, and only this says so. Null where the reader has no block to report.", + "type": [ + "integer", + "null" + ] +} - changed
Output schema / properties / windows / descriptionPrevious value: -"FLOWS over 7, 30 and 90 days: count, total, largest single, most recent. Never a share of the level."New value: +"FLOWS over 7, 30 and 90 days plus all time: count, total, largest single, most recent. Never a share of the level. Every figure is NULL where `haveFlowHistory` is false, because a zero would claim we looked." - added
Output schema / properties / windowsEndAtAdded value: +{ + "description": "The instant every window counts back from, so the 7-day and 30-day figures share an edge and either can be reproduced. It is a window boundary and NOT a freshness claim: the ages of the data are `capitalAsOf`, `declaredAsOf` and `flowsNewestAt`, and `meta.freshness` is computed from those.", + "format": "date-time", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "slug", - "windows", - "says", - "cannotSee" -]New value: +[ + "slug", + "windows", + "says", + "cannotSee", + "windowsEndAt", + "haveFlowHistory" +]
- Changed
vaults_earned5 fields changed- added
Output schema / properties / advertisedBandAdded value: +{ + "description": "minDecimal, maxDecimal, refused and means. Advertised rates are decimal fractions, so a value above 1 is above 100%; readings outside the band are refused rather than counted as zero.", + "type": "object" +} - changed
Output schema / properties / comparable / descriptionPrevious value: -"Vaults where the two sides can be set against each other at all."New value: +"Vaults where the two sides can be set against each other at all. This is the population every share here is over." - changed
Output schema / properties / items / descriptionPrevious value: -"name, slug, advertised, kept, gapPoints, medianDaysHeld. Widest gap first."New value: +"name, slug, venue, advertised, advertisedIsHigh, kept, gapPoints, medianDaysHeld. Widest gap first." - added
Output schema / properties / populationAdded value: +{ + "description": "Who the comparison is actually about: listed, comparable, byVenue, largestVenue, concentration and isOneVenue. `listed` is how many survived the advertised band and are in `byVenue`; `comparable` is the job own count. They are different counts and must never be divided into one another. Where isOneVenue is true the figure is a reading about that one venue in a market-wide sentence.", + "type": "object" +} - added
Output schema / properties / shortOfAdvertisedShareAdded value: +{ + "description": "The headline share, as a decimal fraction. Never quote it without `population` beside it.", + "type": [ + "number", + "null" + ] +}
1 tool update
- Changed
vault_exits1 field changed- changed
Input schema / properties / slug / descriptionPrevious value: -"The vault slug, as list_vaults and find_vaults return it."New value: +"The vault’s slug, or its contract address — either resolves. Until 2026-10-08 this route was the one of eight that took the slug only, so an agent holding an address got a 404 here and a 200 everywhere else."
1 tool update
- Changed
vault_check1 field changed- changed
Output schema / properties / keys / descriptionPrevious value: -"Who can move the money, read from the contract. `holds` is multisig, eoa, contract or timelock; `signaturesRequired` is how many a multisig needs; `actsAlone` is true where ONE party can act with no second signature, which covers a single key AND a multisig with a threshold of one — read that rather than the word multisig. `notice.basis` is the field to check before trusting a delay: `measured` means we read one, `not-a-timelock` means the controller we read is not a timelock and we do not separately search for one behind it, `unread` means we did not ask. Null means we have not read this vault’s control at all, which is not the same as nobody controlling it."New value: +"Who can move the money, read from the contract. `holds` is multisig, eoa, contract or timelock; `signaturesRequired` is how many a multisig needs; `actsAlone` is true where ONE party can act with no second signature, which covers a single key AND a multisig with a threshold of one — read that rather than the word multisig. `canBeHalted` is null where neither pause function answered, which may mean nobody can stop the vault or may mean its pause is behind a name we do not read — do not read a null as nobody. `notice.basis` is the field to check before trusting a delay: `measured` means we read one, `not-a-timelock` means the controller we read is not a timelock and we do not separately search for one behind it, `unread` means we did not ask. Null means we have not read this vault’s control at all, which is not the same as nobody controlling it."
2 tool updates
- Changed
agent_changes1 field changed- added
Output schema / properties / count / descriptionAdded value: +"Rows IN THIS ANSWER, which is one per field that moved and not one per agent. Where `capped` is true it is the page size and not the total, so it is a floor on how much moved and never the whole of it."
- Changed
vault_check1 field changed- added
Output schema / properties / keysAdded value: +{ + "description": "Who can move the money, read from the contract. `holds` is multisig, eoa, contract or timelock; `signaturesRequired` is how many a multisig needs; `actsAlone` is true where ONE party can act with no second signature, which covers a single key AND a multisig with a threshold of one — read that rather than the word multisig. `notice.basis` is the field to check before trusting a delay: `measured` means we read one, `not-a-timelock` means the controller we read is not a timelock and we do not separately search for one behind it, `unread` means we did not ask. Null means we have not read this vault’s control at all, which is not the same as nobody controlling it.", + "type": [ + "object", + "null" + ] +}
1 tool update
- Added
vaults_earned
1 tool update
- Added
agent_changes
1 tool update
- Changed
counterparty_check1 field changed- added
Output schema / properties / independenceAdded value: +{ + "description": "payers, linked, viaParties, largestGroup: payers of this address that share an OBSCURE third party with another of its payers. This is the test of `dealings.independent`, which counts payers that never paid it back and has never been proof they are different parties. A party paid by two to ten addresses in all counts; a hub paid by more does not, because two agents both paying a hub have shown only that the hub is popular. EVIDENCE OF A LINK, NEVER PROOF OF ONE OPERATOR — two payers paying one small service are two customers of that service. `groups` names which payers and through what and needs the `independence.test` capability; where it is withheld, `capability` says so. A linked count of zero is not proof they are unrelated: one owner funding addresses that never touch each other again leaves nothing for this to find.", + "type": [ + "object", + "null" + ] +}
1 tool update
- Changed
counterparty_bulk1 field changed- added
Output schema / properties / sharedAdded value: +{ + "description": "The parties two or more of the given addresses pay, most shared first, each with how many of yours pay it and which ones. `available: false` with a `capability` name where the plan does not carry it. An empty list means no party is paid by more than one of them on a rail we read, which is a finding about them and about our reach: a model, an endpoint or a host shared between them is a dependency no payment rail shows.", + "type": "object" +}
Related MCP Connectors
Screen a payee address before an AI agent pays: sanctions, mixers, scam lists, on-chain risk.
The on-chain facts you need in the seconds before you transact.
Check an x402 endpoint before your agent pays it: avoid / caution / ok, proven on-chain.
Checks a counterparty before an AI agent pays: what the evidence supports, and for how much.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceRoutes blockchain address screening to third-party KYC/AML providers and checks public sanctions lists, serving as a clean-money gate primitive for MCP-compatible agents.MIT
- AlicenseAqualityBmaintenanceBefore an AI agent pays an x402 endpoint, checks whether it's safe to pay: liveness, scam/anomaly scan (payTo hijack, bait-and-switch, honeypot), and on-chain receiver verification. ~70% of x402 endpoints are dead or scams.3MIT
- FlicenseNot gradedqualityDmaintenanceProvides counterparty risk checks for any EVM address, returning malicious-history flags, tiered risk scoring, and plain-language summaries via x402 payment.-
- AlicenseNot gradedqualityFmaintenanceCrypto compliance tools for AI-agent payments: screen any address for sanctions, frozen-stablecoin and hacker/mixer exposure across 8+ chains, trace fund taint, and get an allow/review/decline decision before settlement. Free keyless address checks; deeper endpoints are x402-payable.297 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.