Sell a service

You have an API key, a model, a data source or just a public endpoint worth wrapping, and you want it on the marketplace at a price per call. The catalogue node does the listing; Claude drives it through its admin API: browse the gallery, assemble a config, try a tool before anything goes on-chain, list it, take it down again. The economics and the node: Sell a service; the gallery: Ready-made listings.

The aioum_sell_* tools talk to the node at AIOUM_MULTINODE_URL and send AIOUM_NODE_TOKEN when the node has one. On a real chain the node accepts listings from this API only when started with AIOUM_ADMIN_ALLOW_ADD=1.

Browse the templates

You: "What can I sell without an API key? Something crypto."

Claude calls aioum_sell_templates with { "q": "crypto" }

You see: 9 templates matching "crypto" (7 need no key), then each template's name, title, category, adapter, whether it is keyless, the env names it needs, a description, and its services: each service's key, priceUsdc and tool names. Claude keeps the ones with an empty env. Without q, the whole gallery comes back.

Assemble a config for a node of your own

You: "Give me a services.json with CoinGecko prices and the gas oracle."

Claude calls aioum_sell_config with { "names": ["crypto-coingecko", "eth-gas-price"] }

You see: services.json with 2 services; env needed: none, then the services array ready to save as services.json and env, the sorted list of keys those services need. AIOUM_SERVICES_CONFIG=./services.json npm run multinode sells that file from a node you run yourself. A name the gallery does not know is refused with the list of known ones.

Try a tool before listing

You: "Before we list it, does the CoinGecko price tool actually answer for ethereum?"

Claude calls aioum_sell_preview with the template's first service as spec, "tool": "price" and "args": { "ids": "ethereum", "vs": "usd" }

You see: Preview ok in 412 ms. with the upstream's output and the tool's inputSchema; or Preview failed: … with the error. Nothing touches the chain and nothing is listed. For a keyed upstream, env ({ "OPENAI_API_KEY": "…" }) lets the node try it before the key is in its own environment.

List it

You: "List it at 0.002 USDC a call with a 12000 ZAI stake."

Claude calls aioum_sell_add with { "template": "crypto-coingecko", "price": "0.002", "stake": "12000" }

You see: Listed crypto-price as service #44 at 0.002 USDC/call on http://127.0.0.1:8556., with ok, the listing's key, its on-chain serviceId, the operator that serves it, its priceUsdc and the nodeUrl. The node stakes, registers the service on-chain and serves it; the index is refreshed, so aioum_services finds it at once. When the template needs keys you did not send, the answer names them under envNeeded: "Its upstream needs OPENAI_API_KEY in the node's environment."

From a template, the tool takes the template's first service spec and applies price, stake (both decimal strings) and env; fields given in spec alongside template override the template's. From a spec of your own, send it as spec:

{
  "spec": {
    "key": "crypto-price",
    "category": "data:crypto-price",
    "priceUsdc": 0.002,
    "stakeZai": 12000,
    "tools": [
      { "type": "rest", "name": "price",
        "description": "Spot price for comma-separated CoinGecko {ids} in fiat {vs}.",
        "url": "https://api.coingecko.com/api/v3/simple/price?ids={ids}&vs_currencies={vs}" }
    ]
  },
  "env": { "SOME_UPSTREAM_KEY": "…" }
}

Keys sent as env stay in the node's process for this run; after a restart the node needs them in its own environment. A listing that is already live under the same key is refused.

Sell a skill

You: "List my ./brief-writer skill, once per agent for 50 cents."

Claude calls aioum_sell_skill with { "dir": "/Users/you/brief-writer", "mode": "one-time", "price": "0.5", "category": "writing" }

You see: the listing's key, serviceId, name, description and license read from the folder's SKILL.md, and its terms: one-time at 0.5 USDC, paid once per agent that loads it, which then keeps it; "mode": "per-use" charges every load instead. files lists what went to the node (nodeDir names a folder already there; files sends them inline). The listing's category is skill:writing, and aioum_skills with { "q": "brief" } shows it beside the open-source index with its price and terms (Skills).

Get backed to go live

You: "It is listed with 100 ZAI of mine. Get it live."

Claude calls aioum_stake_request with { "serviceId": "44" }

You see: Service #44 is live: 12,000 ZAI staked (100 the operator's, 11,900 backed), capacity 3 sessions: it answers with real prices for the ids it names · priced like its neighbours. with the request's state, its history (requested, reviewing, approved, backing, live, each with a time), the checks the network's staking node ran (the listing on your node, your own stake, slashes and disputes, the price against the gallery, its cap, the sample call), the review with the model that read the listing against the rubric and its reasons, the stake (yours, the pool's, the total, the capacity), the delegateTx and the paid sample call through your node. Claude follows the request until it is final, ten minutes at most (timeoutSeconds); wait: false returns it as accepted and aioum_stake_requests shows it later. A listing the node will not back comes back rejected with the reviewer's reasons in plain words: fix it, list it again and ask again. Nothing is signed with your wallet: the staking node's pool delegates.

What you sell

You: "What am I selling right now?"

Claude calls aioum_sell_list with {}

You see: 3 services served by your node, then the node's operatorIndex and its live services: each key, serviceId, category, operator, priceUsdc and the names of its tools.

Prove it is yours

You: "The weather API is ours. Mark the listing as official."

Claude calls aioum_sell_verify_domain with { "domain": "api.example.com" }

You see: api.example.com does not yet name operator 0x…: add the DNS TXT record aioum-verify=0x… on api.example.com, or serve https://api.example.com/.well-known/aioum.json with { "operators": [ "0x…" ] }, then ask again. Add either record, ask again: api.example.com names operator 0x…: verified (DNS TXT record). A listing whose spec carries "provider": { "domain": "api.example.com" } now shows Official on the marketplace and ranks first among live ones.

Take it down

You: "Take the CoinGecko listing down."

Claude calls aioum_sell_remove with { "key": "crypto-price" }

You see: Removed crypto-price (service #44). The node stops serving it and marks it inactive on-chain, so the directory drops it; sessions still open settle as usual. The index is refreshed.

Next: Stake and sit on the jury — back an operator with ZAI, collect the USDC that follows, and vote on disputes with a sealed ballot.