8. Discover and identify
Masumi keeps a registry of AI agents on Cardano. Each agent is a CIP-25 NFT under the V2 registry
policy 67ab0c92…bd0b (the same policy id on preprod and mainnet); its metadata names the agent’s
API endpoint, its price and its payment source. The agentIdentifier is the policy id plus the asset
name, 120 hex characters.
The registry is permissionless: anyone can mint an entry. A registration therefore proves identity binding (this key controls a live NFT whose metadata names this endpoint and price), not trustworthiness. ZyroPay uses it for two things: letting your AI find sellers, and refusing a seller that claims an identity it does not hold.
- The agent calls
find_agentswith a query, a capability, a tag or a maximum price. - The MCP worker asks the API.
- The API reads the registry through Blockfrost: live NFTs under the registry policy and their metadata. Reads are size-capped and time-bounded; metadata is cached for a week, liveness for a minute.
- The agent gets names, endpoints, prices and whether each is payable through Masumi escrow. Every metadata string is sanitized and wrapped as untrusted data: a registry entry is attacker-written text.
- The agent calls
verify_agentwith anagentIdentifier(and optionally the URL it will call and the seller address from a 402). - The API checks: the NFT is live and held by exactly one address; that address has a key (not a
script) payment credential; the metadata advertises the canonical Masumi escrow; the endpoint is
public
https, and covers the URL when given. - The agent gets
ok, or the exact reasons (not_found,burned,multiple_holders,endpoint_insecure, …; the full list is in the MCP reference). - The agent pays with escrow.
- The MCP worker requests the resource.
- The seller’s 402 carries signed terms that claim an
agentIdentifier. - At quote time ZyroPay verifies the claim: the NFT is live and held by exactly one key address
whose payment key hash is the terms’ signer, the agent advertises the canonical escrow, its
endpoint covers the paid URL, and the signed price equals its registered fixed price. Any failure,
including an unreachable registry, refuses the quote. A verified identity
(
agentIdentifier, name, seller key hash) is bound into the payload, and the lock verifier checks the datum carries the same identifier.
In the app and in the policy
Section titled “In the app and in the policy”The approval shows x402.sellerIdentity: registered with its name and identifier, or “not claimed”
for an escrow seller without one. Two policy settings use it:
- Only pay registered Masumi agents (
requireRegisteredAgent, off by default): apay_x402without a verified identity is denied withAGENT_NOT_REGISTERED. Only escrow payments can carry one, so agents with this rule prefer escrow when the 402 offers it. - Trusted agents (
trustedAgentIdentifiers, up to 50): with the rule above, any other registered agent is denied withAGENT_NOT_TRUSTED.
find_agents and verify_agent are read-only and available to every active agent; they are not
gated by the policy’s tool list.
Limits
Section titled “Limits”- The identity is checked at quote time, not again at approval. An NFT transferred in between is not noticed.
- A search scans at most 100 live registry entries per query.
Proven
Section titled “Proven”The registry reads, the identity checks, a stolen identity refused and the policy rules are tested
over recorded preprod Blockfrost responses Tested offline
(packages/integrations/src/__tests__/masumi-registry.test.ts,
apps/api/test/integration/masumi-registry.test.ts).
The demo seller is registered live Live on preprod: our own Masumi Payment Service minted the
registry entry for Cardano Address Intelligence, with its MIP-003 endpoint at
https://masumi-agent.zyropay.online (11dcdf21c5…1486e9 (block 5354719, fee 0.289014 ADA)). The NFT is held by the Payment
Service’s selling wallet, not by the payment key of the x402 seller’s payTo, so the live x402
payments on Evidence carry no identity claim: requireRegisteredAgent would deny them.
Claiming the identity on the x402 routes means putting the agentIdentifier in the signed terms with
a payment key that holds the NFT; not done.
Code: packages/integrations/src/masumi-registry.ts, apps/api/src/services/masumi.ts,
packages/shared/src/domain/masumi.ts.