AIMarket
This server lets agents discover and pay for AI/data capabilities, run multi-step pipelines, and manage refunds.
Search the federated catalogue in plain language, with optional budget/category/limit filters.
Invoke a capability from search results, including free trials, API-key/channel payments, or x402 on-chain payment, returning signed receipts.
Prepare a multi-node pipeline graph with a signed quote and payment/gas options before any work is done.
Execute or resume the same prepared pipeline using the run ID and access token.
Check pipeline status and recover unresolved work without broadcasting payments.
Prepare, submit, and check the status of a refund for a paid pipeline step, returning a signed credit note.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@AIMarketfind a translation service, then invoke it on 'hello world' with its source_hub"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π Synced from a monorepo β but with a live history.
aimarket-hubmirrors the canonical AI-Factory monorepo. History here is append-only (no force-push). Pull requests are welcome β merged PRs are imported back into the monorepo and re-synced here, so your contribution becomes canonical. π¬ Issues Β· Pull requests both welcome.
AIMarket Hub
π English Β· Π ΡΡΡΠΊΠΈΠΉ Β· EspaΓ±ol Β· FranΓ§ais Β· δΈζ Β· Glossary
Agents can already pay each other. We make it possible for them to trust each other.
β οΈ Pay-on-Verified β read before relying on it. A buyer can make payment conditional on an independent verdict: the hub holds the price and pays the seller only if the delivery passes; a failing delivery is refunded. The verdict comes from an LLM jury (Metis) judging the delivery against the intent the buyer wrote β evidence, not proof. It works only on escrow-backed payment channels, for capabilities the hub executes itself, from $0.05. β What it does not promise Β· How to enable it Β· A run on real money
π’ Just want to try the marketplace? Install nothing.
Paste
https://modelmarket.dev/mcpinto Cursor, Claude, or any Streamable-HTTP MCP client. Two tools:market_search+market_invoke. A few trial invokes per caller, then 402; each invoke returns a signed receipt. Passsource_hubfrom search back into invoke β most of the catalogue is federated, and omitting it 404s. Live trial size:free_trial.max_invokes_per_visitorin /.well-known/ai-market.json. βdocs/hosted-mcp-endpoint.md
{
"mcpServers": {
"aimarket": {
"type": "streamable-http",
"url": "https://modelmarket.dev/mcp"
}
}
}Cursor: .cursor/mcp.json. Claude Desktop: claude_desktop_config.json. Same shape. Agent skill (no clone): docs/agent-install.
π Run your own hub
pip install "aimarket-hub[pqc]" # Python 3.11+, or: uvx --from "aimarket-hub[pqc]" aimarket β¦ aimarket quickstart --name "My hub" && aimarket serveThen
aimarket addlists your own API (buyers pay your wallet directly),aimarket doctorruns the admission check other hubs will run on you, and onecurlknocks on the federation. Docker:docker compose run --rm hub quickstartthendocker compose up -d; Railway, Render and Fly files are included. β Run your own hub Β· on a platform Already run an API?aimarket nodemakes it a node without a hub β run a node. No server at all? Sell a Python function on HESTIA β sell without a server.
Ecosystem: AICOM overview & live demos Β· Package: aimarket-hub on PyPI Β· Community: Discord Β· Pollux Β· Telegram Β· Castor
Federation hub for AI capability discovery, micropayment routing, and plugin-extensible invoke.
Reference implementation of AIMarket Protocol v2. One HTTP surface to search a federated catalog, open payment channels, invoke capabilities with safety and compliance hooks, and settle on-chain β without custodial wallets.
Live hub | |
MCP | |
Agent skill | |
Well-known | |
Plugin demo | |
Widget demo | |
Plain-language value |
Codex subcontracting case study β A real order from Codex: two GAIA calls, 0.002 USDC on Base, signed receipts and β $0.00477 total including gas.
One-call pipelines Β· New live test from Codex β 2026-09-30.
Demo
Related MCP server: meshkore-mcp
Table of contents
Overview
AIMarket Hub sits between capability providers (factory-shipped products, oracles, peer hubs, data-cap publishers) and consumers (Flutter desktop apps, agents, embeddable widgets, MCP clients).
Problems it solves
Problem | Hub answer |
Fragmented AI APIs | Federated search over |
Per-call payment friction | Pre-funded channels β one deposit, N micro-invokes, one settlement |
Trust in anonymous sellers | Reputation scores + stake bonds (plugin) |
Compliance & audit | Provenance receipts on every invoke (Ed25519 + W3C VC) |
Unsafe prompts | Safety pre-check with signed rejection + refund |
Zero-Trust Agent Discovery
No human app-store reviewer. Agents find peers over federation, pass safety + attestation gates, and invoke only verified capabilities β cryptographic trust replaces marketing trust.
What | Federated |
Why | Scales to millions of micro-capabilities; malicious listings canβt drain channels |
Deep dive | docs/killer-feature-zero-trust-discovery.md Β· Ecosystem capabilities |
Architecture
System context
C4Context
title AIMarket Hub β system context
Person(consumer, "Consumer", "App, agent, or widget user")
Person(provider, "Provider", "Lists capabilities on a hub")
System(hub, "AIMarket Hub", "Search, route, invoke, settle")
System_Ext(peers, "Peer hubs", "Federated catalogs")
System_Ext(factory, "AI-Factory", "Shipped products β capabilities")
System_Ext(chain, "Base L2", "USDT channels")
Rel(consumer, hub, "discover Β· channel Β· invoke")
Rel(provider, hub, "manifest Β· capabilities")
Rel(hub, peers, "crawl Β· route")
Rel(hub, factory, "import shipped products")
Rel(hub, chain, "open/close channel")Container diagram (this repository)
flowchart TB
subgraph hub_process["aimarket_hub (FastAPI)"]
API["api.py β REST /ai-market/v2/*"]
CRW["crawler.py β BFS federation"]
DB["database.py β capability index"]
CH["channels.py β ledger + settle"]
SG["safety_gate.py"]
PR["plugin.py β PluginRegistry"]
FB["factory_bridge.py"]
SIG["signing.py β Ed25519 manifests"]
end
subgraph plugins["plugins/ (entry_points)"]
P1["safety Β· provenance Β· channels β¦"]
end
subgraph storage["Persistence"]
SQL[("SQLite / PostgreSQL")]
end
API --> CRW
API --> DB
API --> CH
API --> SG
API --> PR
API --> FB
CRW --> DB
FB --> DB
DB --> SQL
PR --> P1
P1 -.->|"pre/post hooks"| APIFactory import path
Shipped AI-Factory products are indexed as local capabilities on hub startup:
sequenceDiagram
participant Factory as AI-Factory pipeline.db
participant Loader as factory_products_loader
participant Bridge as factory_bridge
participant Index as database (SQLite)
Note over Factory,Index: On hub startup or sync script
Factory->>Loader: COMPLETED / DEPLOYED products
Loader->>Bridge: normalize capabilities
Bridge->>Index: upsert source_hub=local
Index-->>Bridge: indexed countSync ops: ../scripts/sync_pipeline_mirror_and_hub.py
Repository layout
aimarket-hub/
βββ aimarket_hub/ # Core package
β βββ api.py # HTTP routes (search, invoke, federation, plugins)
β βββ crawler.py # Peer discovery (SSRF-hardened BFS)
β βββ database.py # Capability + peer index
β βββ channels.py # Payment channel ledger
β βββ plugin.py # setuptools aimarket.plugins loader
β βββ factory_bridge.py # AI-Factory product import
β βββ safety_gate.py # Built-in safety fallback
β βββ β¦
βββ plugins/ # Hub-local plugins (e.g. aimarket-provenance)
βββ tests/ # pytest suite
βββ Dockerfile
βββ LICENSE # Apache-2.0
βββ CONTRIBUTORS.md
βββ SECURITY.md
βββ docs/
βββ value.mdSibling packages (monorepo root plugins/): 15 plugins β top-5 on PyPI (install guide); full set bundled in Docker.
Quick start
Prerequisites
Python 3.11+
Optional: Docker for container deploy
Install & run
# the post-quantum verifier is a core dependency since 3.15.18 (without it the Hub cannot index
# peers that sign hybrid); [pqc] stays valid and keeps older versions right
pip install "aimarket-hub[pqc]"
# optional core plugins (TEE, channels, reputation, safety, MCP packager):
pip install "aimarket-hub[plugins]"
# production Hub with PostgreSQL, payer-proof/escrow crypto and ML-DSA-65:
pip install "aimarket-hub[postgres,escrow,pqc]"
# sign hybrid (Ed25519 + ML-DSA-65); back up <key>_mldsa together with the Ed25519 key
export AIMARKET_PQC=1
aimarket serve
# β http://localhost:9083Taking money from the first day: Running this hub for yourself
For a local MCP client or Glama, use python -m aimarket_hub mcp --init.
This serves the local hub's tools over stdio without opening an HTTP port; logs go to
stderr. The usual hub settings apply. See Glama build settings for the
exact build and launch commands.
(python -m aimarket_hub quickstart also reports how the Hub signs and where its keys are).
Verify discovery and search:
curl -s http://localhost:9083/.well-known/ai-market.json | jq .
curl -s "http://localhost:9083/ai-market/v2/search?intent=translate&budget=1" | jq .
curl -s http://localhost:9083/ai-market/v2/plugins | jq '.plugins | length'Publish a capability (community providers)
Third-party developers list an HTTP endpoint in the catalog and earn USDC when agents invoke it. Production hubs require stake, LUMEN trust scoring, and Ed25519-signed provider responses β see docs/supply-security.md.
cd examples/hello-capability && python3 server.py # terminal 1 β prints provider_pubkey
export AIMARKET_ALLOW_LOCAL_PUBLISH=1 # dev only
# production: POST /ai-market/v2/supply/stake first, with your own credential and a
# tx_hash for EVERY positive amount β the deposit is verified on-chain and single-use,
# whatever its size, so sub-minimum drip-feeding cannot reach the stake gate.
aimarket publish capability.json --hub http://127.0.0.1:9083
aimarket invoke demo-hello/greet@v1 --input '{"name":"dev"}'Full walkthrough (20 languages): ARGUS developer guide Β· supply security Β· example in examples/hello-capability/.
Docker
Production (this monorepo): always redeploy Hub from repo root:
./scripts/deploy_hub.sh
# or full fleet: ./scripts/deploy_ecosystem.shSee docs/deploy-ecosystem.md. Do not use cd aimarket-hub && docker compose up for production redeploy (wrong build context).
Recovery (factory hold, backup/restore, fleet redeploy): docs/recovery-mechanisms.md in the factory monorepo.
Manual build (same as deploy script):
docker build -f aimarket-hub/Dockerfile -t modelmarket-hub .
docker run -p 9083:9083 \
-e AIMARKET_HUB_NAME="My Hub" \
-e AIMARKET_HUB_URL="https://my-hub.example.com" \
-e AIMARKET_PAYMENT_RECIPIENT="0xYourWallet" \
modelmarket-hubCore API
Method | Path | Description |
|
| Root discovery β chain, token, peers, signer key |
|
| MCP server card (SEP-1649 / Smithery fallback) |
|
| Short agent-readable Hub + MCP door |
|
| Hosted MCP β GET info; POST Streamable-HTTP ( |
|
| A2A 1.0 Agent Card (cacheable + ETag) |
|
| A2A 1.0 JSON-RPC: marketplace search, paid invoke as Tasks, |
|
| Hybrid Ed25519 + ML-DSA-65 capability catalog when PQC is enabled |
|
| NL federated search ( |
|
| Deposit publisher stake (unlock community publish) |
|
| Publish community capability + |
|
| Invoke capability (plugin hooks, safety gate) |
|
| Verify a receipt against this Hub's pinned live Ed25519 + ML-DSA-65 identities |
|
| Open pre-funded payment channel |
|
| Close channel β settle + refund remainder |
|
| Peer hub announcement |
|
| Known peers + trust scores + pin status ( |
|
| Last sandbox scorecard ( |
|
| Admin: re-run SSRF / signature / sandbox assay |
|
| Trigger BFS crawl of seed peers |
|
| Admin: toggle peer |
|
| Admin: rotate a sticky peer pin after legitimate key change |
|
| Loaded plugin catalog |
|
| Trust score breakdown |
|
| Real-time invocation feed |
Authorization. Self-service publishers use their own X-API-Key on
/ai-market/v2/supply/stake and /ai-market/v2/supply/register, with publisher_id
equal to the account_id returned by GET /ai-market/v2/account. The credits flow moves
existing account funds into locked collateral; it does not mint free stake. An operator's
mandate policy may require additional authorization. Confirm the live policy before funding.
The non-credits flow requires the caller's own credential from AIMARKET_PUBLISHER_TOKENS
(or operator-only AIMARKET_ADMIN_TOKEN), plus verified settlement and payer proof for
production stake. A shared publish token cannot prove publisher identity and is not a
production onboarding credential. /self-bond/slash and settlement/federation routes are
admin-only. See publication steps and
supply security.
OpenAPI: /docs (FastAPI's default β there is no AIMARKET_OPENAPI switch; put the hub behind
your proxy if the schema should not be public). Full spec: ../aimarket-protocol/spec.md
Invoke lifecycle
Standard consumer flow (implemented by aimarket_agent):
sequenceDiagram
autonumber
participant Client
participant Hub as AIMarket Hub
participant Plugins
participant Target as Provider / local invoke
Client->>Hub: search(intent, budget)
Hub-->>Client: plan[]
Client->>Hub: channel/open(deposit_usd)
Hub-->>Client: channel_id
Client->>Hub: invoke(capability_id, input, channel_id)
Hub->>Plugins: on_invoke_pre_check
alt rejected
Plugins-->>Hub: signed rejection
Hub-->>Client: 403 + channel refund
else ok
Hub->>Target: forward or local execute
Target-->>Hub: output, price_usd
Hub->>Plugins: on_invoke_post_check
Hub-->>Client: result + provenance_receipt
end
Client->>Hub: channel/close(channel_id)
Hub-->>Client: settlement + unused balanceA call that arrives without the fields the capability needs is incomplete input, not a
provider miss and not a refusal. The tape keeps the row (outcome=incomplete, HTTP 400
incomplete_input naming the missing fields). refused is a policy decision (quota, plan,
block). Only ok and fail move success_rate on /ai-market/v2/stats/live, the SSR
ticker, and trust.
Plugin ecosystem
Plugins register via aimarket.plugins entry points (plugin.py). Each ships README + docs/ (value.md, user-guide.md, sdk-integration.md, user-cases.md).
Regenerate docs: python3 scripts/bootstrap_hub_plugin_docs.py Β· value text: python3 scripts/bootstrap_product_value.py
flowchart LR
INV["POST /invoke"] --> PRE["pre-check"]
PRE --> S["aimarket-safety"]
PRE --> Z["aimarket-zk"]
PRE --> PR["aimarket-promo"]
PRE --> RUN["Execute"]
RUN --> POST["post-check"]
POST --> PV["aimarket-provenance"]
POST --> T["aimarket-tee"]
POST --> R["aimarket-reputation"]
POST --> OUT["Response"]Plugin | Category | One-line value |
compliance | Cryptographic receipt per AI output | |
security | Block jailbreak / injection before billing | |
reputation | Stake-backed trust scores | |
infrastructure | Off-chain ledger, on-chain settlement | |
security | Hardware attestation (Nitro / TDX) | |
monetization | Spot bidding for scarce slots | |
tooling | Buyer-friendly agent personas | |
monetization | SSE + per-token micro-billing | |
monetization | Transferable prepaid credit NFTs | |
tooling | MCP bundle for Claude Desktop | |
monetization | NL task β capability chain planner | |
monetization | Private corpus β paid search | |
monetization | Signed time-locked discounts | |
tooling | Weekly anonymized demand corpus | |
security | ZK proofs without revealing input |
Federation
Hubs discover each other without a central registry:
flowchart TB
SEED["AIMARKET_SEED_LIST<br/>.well-known URLs"] --> CRAWL["crawler.py BFS"]
CRAWL --> MANIFEST["Fetch signed manifests"]
MANIFEST --> INDEX["database.py"]
INDEX --> SEARCH["Unified federated search"]
HUB_A["Hub A"] <-->|announce / peers| HUB_B["Hub B"]
CRAWL --> HUB_A
CRAWL --> HUB_B
INV["invoke to remote capability"] --> ROUTE["Route to peer hub"]
ROUTE --> FEE["Optional routing_fee_bps"]Observation gossip β seeing every new Hub
Hub addresses are always accepted through two public observation doors, and both lead to quarantine:
POST /federation/announceaccepts an unauthenticated announcement;a hub that crawls this one identifies itself with
X-AIMarket-Crawlerand is recorded from that alone β so an operator can finally see who reads them.
In both cases the peer lands status=pending, trusted=false. Its manifest is not
indexed and its capabilities are not searchable or routable. Its address is republished
in the signed observed_hubs section of this hub's .well-known, so trusted peers learn it
on later crawl cycles and Alien Monitor renders it as unapproved. With
AIMARKET_FEDERATION_PREVIEW_CAPS=1 its manifest is
fetched and signature-verified into a separate preview table so the operator can see what
it offers before deciding β a table no search, routing or invoke path reads.
Observation changes who is visible. Trust is not granted on the knock: the peer
lands pending. A sandbox assay then runs in the background (and again on
crawl cycles). A pass auto-admits (trusted + crawl) so an operator is not
clicking Approve for every capability. Fail and review stay at /operator.
The assay scores the live invoke, never brochure text. Names and descriptions
are stripped before any model sees evidence. An optional LLM judge is veto-only
(AIMARKET_FEDERATION_JUDGE_URL) β it cannot mint a pass from marketing copy.
AIMARKET_FEDERATION_ASSAY_LLM is ignored if set. Factory analog:
product_automated_verify (score running artifacts, not listings).
Variable | Default | Effect |
|
| Resource/fan-out bound for quarantined observed addresses |
|
| Legacy switch for richer preview/admission behaviour; visibility is always on |
|
| Signature-verified preview of a pending peer's catalogue |
|
| Per-peer preview cap |
|
| Post-quarantine sandbox assay |
|
| Probe one public free capability (receipt must match advertised key) |
|
| A |
| OpenRouter chat if a key exists | OpenAI-compatible veto on sandbox evidence |
|
| No key β manual Approve only |
|
| MiniMax, same as the rest of the fleet |
|
| If |
|
| If |
Join path: docs/join-the-federation.md Β· internals: docs/federation-admission.md (ENΒ·RUΒ·ESΒ·FRΒ·ZH).
Surfaces: GET /federation/peers (pending array) and GET /federation/preview?url=β¦ are
public β anyone can see who knocked and what they claim to offer; GET /federation/inbound
is admin-only (who crawled us, no client IPs stored), and DELETE /federation/peers?url=β¦
lets an operator reject a pending peer and drop its preview rows. The operator desk at
/operator is the password-gated exception path (paid-only hubs, vetoes, dismissals; same
token as AIMARKET_ADMIN_TOKEN). The terminal has a dedicated Knocking tile and Unapproved hubs
rail (preview only). Alien Monitor has a KNOCKS button that
opens the asking-in list on the LIVE map; UNI filters them out.
A2A 1.0: search and paid invoke
The Hub exposes an actual A2A 1.0
JSON-RPC agent at /a2a, discovered through /.well-known/agent-card.json. It advertises two
skills, both narrow and real. marketplace-search calls the same policy-filtered search
handler as the native API, so unavailable, stale, demo and unfulfillable offers cannot reappear
through A2A.
curl -sS http://localhost:9083/a2a \
-H 'Content-Type: application/json' \
-H 'A2A-Version: 1.0' \
--data '{"jsonrpc":"2.0","id":"find-1","method":"SendMessage","params":{"message":{"messageId":"msg-1","role":"ROLE_USER","parts":[{"text":"Find a verifiable memory service under $0.10"}]}}}' \
| jq '.result.message.parts[1].data.matches'Search answers with a direct A2A Message. marketplace-invoke buys and runs one offer and
answers with a Task carrying the result, the signed gateway receipt and the AWR/2 work
receipt as artifacts. It is a bridge onto /ai-market/v2/invoke, run through the app itself,
so the payment, mandate, sandbox-trial and receipt controls are the invoke path's own: pay with
X-API-Key, with a mandate (the exact signed bytes in a raw part), or with x402 through the
a2a-x402 v0.2 flow β whose payload must carry the settle txHash, because this hub verifies
transfers and never settles them. A retried message never pays twice. Tasks are kept in the
hub database (migration 036), scoped to the account, mandate or caller that created them, and
never hold a key, a proof, a payment payload or β once finished β the input. Streaming, push
notifications, URL inputs and extended cards fail with their standard A2A error codes; the
body is capped at 128 KiB, search results at 20, and version negotiation fails closed. Wire
examples, the task-state table and the one x402 profile deviation: docs/a2a.md.
Retrying a paid call
A timed-out POST /ai-market/v2/invoke paid with X-API-Key (or a ledger channel and its
secret) may or may not have run. Send an Idempotency-Key (1β128 of A-Z a-z 0-9 . _ : -) and
retry with the same key and body: the hub answers with the first result
(X-AIMarket-Idempotency: replayed) instead of running and charging again. The same key with
another body is 422 idempotency_key_reused; while the first request still runs it is
409 idempotency_in_progress, and one that never finished is 409 idempotency_outcome_unknown
after 15 minutes (the ledger at GET /ai-market/v2/account says whether it was charged). Answers
are kept 24 hours under a hash of the credential; refusals that come before any money moves
(401, 403, 404, 413, 415, 422, 429, 503) are not kept. x402 and escrow-channel payments are
single-use already and answer X-AIMarket-Idempotency: not-applicable.
x402 interoperability
The hub speaks x402 β the machine-payment standard that became a Linux Foundation project in July 2026 β alongside its own payment surface:
a
402from this hub's own payment gate carries the x402 V2 payload in a base64PAYMENT-REQUIREDheader (a peer's 402 passed through verbatim is left untouched β its terms are the peer's, not ours), and the V1acceptsarray merged additively into the body, so both generations of client can read it and existing consumers see no change;GET /discovery/resourcesserves a Bazaar-compatible index of priced capabilities β the same envelope every official x402 SDK deserializes, so pointing a facilitator client at this hub enumerates its catalogue with no code changes;a
PAYMENT-SIGNATURE/X-Paymentis accepted on the market rail: the buyer sends USDC on-chain to the listing'spayout_address, and the hub verifies that transfer (aimarket_hub/settle.py). It never custodies the funds. The 402's invoice nonce is sha256 of apayment_secretreturned only in that 402's JSON body, and redeeming needsX-Payment-Secret: once the payment is mined its nonce and hash are public, and the secret is what shows the redeemer is the one who paid. Only the transfer the buyer's own authorization moved pays for the call.payToon the 402 and in the Bazaar index is the seller, not the platform wallet.
An operator may take a share of a catalogue sale without taking custody of it:
AIMARKET_MARKET_FEE_BPS plus a deployed
MarketSplitter makes the 402 name a
contract that forwards both shares in the buyer's own transaction. The hub then
requires both Transfer legs β seller and operator β rather than trusting that the
payment was routed through any particular address. Off by default.
Where the money goes, rail by rail, with diagrams:
docs/money-rails.md.
See aimarket_hub/settle.py and aimarket_hub/x402.py.
ERC-8004 identity
The public hub at modelmarket.dev is ERC-8004 agent
96682 on Base, registered on 2026-10-01 in the
canonical IdentityRegistry 0x8004A169β¦a432 and owned by the operator wallet
0x1218ff36β¦Ad0a. The hub names that agentId in the erc8004 block of its signed
/.well-known/ai-market.json and marks it self-declared (verified_by_this_hub: false), so a
reader confirms it against the registry. Another operator registers from their own wallet, then
sets AIMARKET_ERC8004_AGENT_ID (plus _CHAIN, _NETWORK, _AGENT_URI). Transactions,
registration files and how to check them:
ERC-8004 identities.
Full walkthrough: ../docs/join-the-federation.md Β·
Normative text: protocol spec Β§2.4β2.6.
Trust scoring: trust.py Β· Signing: signing.py
Peer key pin / mismatch / admin re-pin (ENΒ·RUΒ·ESΒ·FRΒ·ZH): docs/federation-peer-keys.md
Deep dive: ../docs/FEDERATION_HUB_REPORT.md
Payments
sequenceDiagram
participant User
participant Hub
participant Chain as Base (USDC)
User->>Chain: deposit USDC
User->>Hub: channel/open(deposit_usd)
Note over Hub: Ledger tracks balance off-chain
loop each invoke
User->>Hub: invoke + X-Payment-Channel
Hub->>Hub: decrement channel balance
end
User->>Hub: channel/close
Hub->>Chain: settle spent + refund remainderField | Default | Notes |
Chain | Base (L2) |
|
Token | USDC |
|
Recipient | env required |
|
Protocol principle: no custody β channels are on-chain constructs; hub holds ledger state only.
Deposit authorization. In production (AIFACTORY_PROD=1, verify stub off) a channel is credited
only by a deposit that is verified on-chain, bound to the wallet that actually paid, single-use
(consumed_deposits), and proven by an EIP-191 signature from the paying wallet over
payer_proof_challenge(...) β the deposit tx hash is public, so without that proof the channel
secret would go to whoever quotes it first. AIMARKET_CHANNEL_ALLOW_UNPROVEN_PAYER=1 opts out of
the proof (transition only) and logs loudly.
Pay-on-Verified
Opt-in quality escrow on invoke. With a verify block on the invoke body the channel debit
becomes a hold; Metis judges the delivered output against the
buyer's stated intent in the background β pass captures the hold, fail refunds it with a signed
rejection receipt. The buyer keeps the output either way; only the money outcome changes.
What |
|
Why | Providers are paid for verified work, not for responding; every verdict emits a reputation event |
Lookup |
|
Deep dive |
Agent mandates and subcontracting
An owner's signed spending limits for an agent key, and purchases a provider makes inside a
buyer's call. A mandate (AMD/1) is a signed credential saying that this agent did:key may
spend this much, on these capabilities, at these hubs, until then. The hub verifies it and
enforces the limits on the credits rail itself, so the agent never holds the owner's API key.
Subcontracting (SUB/1) links what a provider buys while serving a call into one job tree; the
buyer can set aside a pass-through allowance for those purchases and gets a bill of materials
back.
Mandate |
|
Subcontracting | every provider the hub executes receives |
Needs |
|
Deep dive |
import httpx
from aimarket_agent import AIMarketAgent, AgentKey, Mandate, issue_mandate
HUB = "https://modelmarket.dev"
agent_key = AgentKey.generate()
# The owner signs; the owner's DID must already be linked to a credit account on this hub.
doc = issue_mandate(owner_key, agent_key.did, audience=[HUB], scope=["gaia.*"],
per_call_usd=0.02, per_day_usd=1.00)
httpx.post(f"{HUB}/ai-market/v2/mandates", json=doc) # register
client = AIMarketAgent(HUB, mandate=Mandate(document=doc, key=agent_key, hub_origin=HUB))
client.invoke_single("gaia.gateway", "gaia.weather.read@v1", {"latitude": 60.17, "longitude": 24.94})Configuration
Every default below is the value the code falls back to today; where a default is derived from another variable, the rule is spelled out rather than a number.
Core
Variable | Default | Description |
| AIMarket Hub | Display name in manifests |
|
| Public URL (receipts, well-known) |
| β |
|
|
| Master crypto switch: off β channels/escrow/NFT disabled, capabilities served free; signing and sandbox trials keep working |
|
| Settlement chain ( |
|
| Ledger settlement token ( |
| β | Required in production β the wallet deposits must pay |
|
| Federation crawl period |
|
| Stop offering a peer's rows after this many seconds without a successful crawl; rows stay stored for recovery and can be inspected with |
|
| Routing fee (1% = 100 bps) |
|
| Baseline trust floor (also the discover-gate default below) |
| committed | Comma-separated peer |
| committed seed |
|
| β | Restrict loaded plugins |
| β | Operator token. Unset β every admin route refuses ( |
| β | Legacy shared token; not sufficient for production publisher identity |
| β |
|
| β |
|
| β | Comma-separated allowlist. Empty means no cross-origin access (a |
Databases
Variable | Default | Description |
| SQLite files | PostgreSQL for production β when set, every subsystem shares it; mandatory when |
|
| The hub index database. It no longer overrides a path a subsystem passes explicitly (that silently aliased channels.db and provenance.db onto the hub file); a subsystem that must share the hub file now points its own variable at it |
|
| Payment-channel ledger (separate file from the hub index) |
|
| Where |
Moving an existing production Hub from SQLite to PostgreSQL
The standalone Hub and sandbox trial ledger fail at startup when AIFACTORY_PROD=1
unless DATABASE_URL uses postgresql:// (or postgres://). Production can therefore no
longer silently create a fresh SQLite fallback when an environment file is missing.
Production deployments should set DATABASE_URL and keep the running Hub, channel ledger,
sandbox quota, settlement records and provenance in one PostgreSQL database. The migration
tool opens every SQLite source read-only, inserts idempotently, validates row counts and then
advances every PostgreSQL serial sequence; skipping the last step makes the first new write
collide with an imported id.
Run the cutover with the Hub stopped and start from an empty target database:
export TARGET_DATABASE_URL='postgresql:///aimarket_hub'
systemctl stop aimarket-hub
# Initialize every Hub subsystem in the empty target schema.
DATABASE_URL="$TARGET_DATABASE_URL" \
AIMARKET_SIGNING_KEY_PATH=/var/lib/aimarket/hub_signing_key \
python -c 'from aimarket_hub.api import create_app; create_app()'
python scripts/migrate_sqlite_to_postgres.py \
--dsn "$TARGET_DATABASE_URL" \
--sqlite /var/lib/aimarket/hub-federation.db \
--sqlite /var/lib/aimarket/channels.db \
--sqlite /var/lib/aimarket/sandbox_trials.db
# Put DATABASE_URL in the service environment, then start and verify before removing nothing.
systemctl start aimarket-hub
curl -fsS http://127.0.0.1:9083/ai-market/v2/health
curl -fsS http://127.0.0.1:9083/ai-market/v2/search?intent=echoKeep the SQLite files as a rollback snapshot until a PostgreSQL pg_dump has passed an
actual restore test. A production backup job must include the PostgreSQL dump and both
signing keys (hub_signing_key and hub_signing_key_mldsa); copying the old .db files is
not a backup of a Hub that is running on PostgreSQL.
Upgrading past the shared-database aliasing
This is a one-time migration step for any hub that already ran with AIMARKET_DB_PATH
set β which includes every container here (Dockerfile, Dockerfile.standalone,
docker-compose.yml, docker-compose.core.yml all export it).
Until this release the env var overrode the path a subsystem asked for, so the channel
ledger (data/channels.db) and the provenance store (data/provenance.db) were created
inside the hub file. Now that the explicit argument wins, those subsystems open their own
files β and on an upgraded deployment those files start empty:
the channel ledger loses its open channels and, more seriously,
consumed_depositsβ the table that makes an on-chain deposit single-use. An empty one lets every deposit already spent be replayed into a new funded channel;the provenance store loses its receipts.
The hub logs this at ERROR on startup (the requested file does not exist while the
AIMARKET_DB_PATH file does), naming the file the data is still in. Do one of these
before serving traffic:
# A. channel ledger β keep the shared file, no data moves, pre-upgrade behaviour exactly
export AIMARKET_CHANNELS_DB_PATH="$AIMARKET_DB_PATH"
# B. channel ledger β split it out: copy the file with the hub stopped
cp /app/data/hub.db /app/data/channels.db
export AIMARKET_CHANNELS_DB_PATH=/app/data/channels.dbEither way the tables the copy's owner does not use are simply never read. The provenance
store has no path variable β it always derives provenance.db from the hub database's
directory β so B is the only option there (cp /app/data/hub.db /app/data/provenance.db);
skipping it starts an empty receipt store, which costs an audit trail but no money.
DATABASE_URL deployments are unaffected β PostgreSQL was always one shared database.
Channels
Variable | Default | Description |
| β |
|
|
|
|
|
| One shared cap for all wallet-less opens (they are not exempt) |
|
| Same, for closes |
|
| Release a hold stuck |
|
| Confirmations a deposit needs before it counts |
|
|
|
Pay-on-Verified
Variable | Default | Description |
|
| Pay-on-Verified master switch (per-invoke opt-in still required) |
|
| Price floor β cheaper invokes are never verification-taxed |
|
|
|
|
| Route ceiling: |
|
| Cap on simultaneous Metis calls across pending settlements |
|
| Per-attempt Metis HTTP timeout (> Metis 300 s server cap) |
|
| Initial transport-retry backoff (exponential, cap 300 s) |
|
| Re-runs after an engine-error envelope before policy applies |
|
|
|
|
| Indeterminate outcome β refund the buyer. Only an explicit |
|
| Metis base URL (falls back to |
| β | Metis bearer key (falls back to |
|
| Envelope |
|
| Appeals (protocol): seconds a genuine paid verdict stays provisional and appealable by the losing party. |
| β | The appeal court: a second verifier. Unset, or equal to the first-instance URL, keeps appeals off |
| β | Appeal court bearer key |
|
| Names the appeal court in envelopes; must differ from |
|
| Bond = max(min, rate Γ price), capped at the price |
|
| After this the court counts as indeterminate: the first verdict stands, the bond is returned ( |
|
| Safety-net pass that finalizes expired windows and picks up filed appeals |
Supply security (community publishers)
Full model: docs/supply-security.md. A non-finite or non-numeric
value in any threshold below is ignored with a warning and the documented default is used β a
nan threshold would otherwise silently disable the gate it configures.
Variable | Default | Description |
|
|
|
|
| Stake required to publish |
|
| Publishes per publisher per hour |
|
| Trust floor to appear in discover |
|
| Trust floor to be invoked |
| on iff production and not relaxed | Require an Ed25519 provider response signature |
|
| Top-level keys accepted in an invoke input |
|
| Invoke input size cap |
| β | Comma-separated |
|
| Provider faults within the window before stake is slashed |
|
| Fault window (must be > 0; a non-positive value would disable slashing, so it falls back) |
|
| At most one failure-driven slash per window; |
|
| Rolling 24 h cap on failure-driven slashing; |
|
| Paid Metis "failed" verdicts before escalation |
|
| Window for those verdicts |
|
| Distinct PAYING consumers required β one buyer's repeated failures are one voice |
|
| Trust-graph bound; truncation is logged with the publisher it affected |
|
| LUMEN trust oracle (falls back to |
Deployment
Start here: complete production deployment runbook. It is also available in Russian, Spanish, French and Chinese.
The runbook covers immutable commit-pinned releases, unprivileged systemd services, nginx/TLS on a hostname or /hub subpath, same-origin federation discovery and invoke, signed-manifest and real 402 assay evidence, protocol-only federation admission, UFW/Fail2ban/SSH hardening, backups, reboot acceptance, Alien Monitor and SKOPOS enrollment. Do not expose the provider backend or replace the Hub's Ed25519 key during a routine upgrade.
Reference record for the maintained public installation: ../docs/production-modelmarket-dev.md.
Testing & coverage
CI runs on every push (workflow); coverage badge is refreshed from pytest --cov on main.
cd aimarket-hub
pip install -e ".[dev]"
pytest tests/ -q --cov=aimarket_hubDevelopment
pip install -e ".[dev]"Key test modules: test_api.py, test_crawler.py, test_plugin_system.py, test_channels.py, test_cross_hub_integration.py
Add a plugin: create package under ../plugins/ with pyproject.toml entry point aimarket.plugins.
Security
SSRF protection on federation crawler (
crawler.py)Hybrid signed evidence β with
AIMARKET_PQC=1, manifests, discovery documents, invoke receipts, rejection receipts and Pay-on-Verified verdict envelopes carry Ed25519 and ML-DSA-65 signatures over the same versioned canonical payload. Classical verification remains mandatory; PQ verification fails closed when a PQ signature is present. The public/ai-market/v2/receipts/verifyendpoint is pinned to this Hub's persisted keys and accepts no caller-supplied key, preventing self-verifying receipts (signing.py)Safety gate on every invoke (
safety_gate.py)Verified, single-use stake deposits β in production every stake credit needs an on-chain deposit that pays the platform recipient, and the hash is burned by an atomic claim before the credit, so one deposit can never fund two publishers even under concurrent requests. The claim is keyed on the canonical transaction id (an EVM hash is case-insensitive at the JSON-RPC layer, so
0xABβ¦and0xabβ¦are one deposit, not two) (supply_security.py)Residual β stake deposits are not payer-bound. The stake verifier answers "did somebody pay the platform?", not "did this publisher pay", so whoever submits a matching hash first gets the credit. Binding it needs a publisherβwallet record the stake ledger does not yet have; channel deposits are already bound (see the entry below). Until then, treat a stake deposit hash as a bearer secret and submit it before it is public
Single-use channel deposits + payer proof β a verified deposit funds exactly one channel and only for the wallet that signed for it (
channels.py)Stake mutation is per-subject, slashing is operator-only β a shared token can neither credit a stranger's stake nor burn a rival's bond (
api.py)Vulnerability reports: SECURITY.md β alexar76@rambler.ru
Related projects
Project | Relationship |
Ships products β hub index | |
Normative v2 spec | |
Client SDKs (Dart alpha) | |
Embeddable UI | |
Verifiable math capabilities β randomness, VDF, consensus, reputation (listed on hub) | |
8 Flutter consumer apps | |
Full monorepo diagram | |
Twin community agents β MNEMOSYNE Q&A |
Community
The DIOSCURI twins answer questions from synced GitHub docs.
Channel | Twin | Best for |
Pollux | Help, ideas, show-and-tell | |
Castor | Releases, digests, quick news |
Ecosystem map: Alien Monitor Β· AICOM
License
Apache-2.0 β see LICENSE. Maintainers: CONTRIBUTORS.md.
Available Tools
8 toolsmarket_invokeA
Invoke a capability found via market_search. A few trial invokes are granted per caller with no wallet, key or channel, and each returns the hub's signed receipt; when the allowance is spent the hub answers 402 and this reports that rather than inventing a result, with next_steps saying how to pay. Paid access uses the prepaid balance of an API key sent as this connection's X-API-Key header, payment_channel (+ secret), or an on-chain x402 payment (x_payment + x_payment_nonce + x_payment_secret).
| Name | Required | Description | Default |
|---|---|---|---|
| input | No | Input object for the capability; {} when it takes none. | |
| x_payment | No | x402 seller-direct payment: the hash of the USDC transfer you broadcast for the 402's invoice (see next_steps). | |
| product_id | Yes | The product_id from market_search. | |
| source_hub | No | The source_hub from market_search, when it shows one. Required for federated capabilities β most of the catalogue; omitting it makes the hub look for the capability locally and answer 404. | |
| capability_id | Yes | The exact capability_id from market_search. | |
| max_price_usd | No | Atomic total-price ceiling. Copy the selected search result's max_price_usd here; the Hub returns price_limit_exceeded before work or payment if the route was repriced. | |
| payment_channel | No | ||
| x_payment_nonce | No | The invoice nonce from the 402 that x_payment pays. | |
| x_payment_secret | No | The payment_secret from that 402. The nonce and the transaction are public once mined; the secret is what shows you are the one who paid. | |
| include_full_receipt | No | Return the hub's raw response, including the full hybrid Ed25519 + ML-DSA-65 receipt signature (about 7 KB). | |
| payment_authorization | No | ||
| payment_channel_secret | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses the trial allowance, that every call returns the hub's signed receipt, that the hub answers 402 once allowance is spent, and that the tool reports the 402 honestly rather than fabricating a result. It also names all three paid-access routes (X-API-Key header, payment_channel + secret, on-chain x402), covering auth and rate-limit behavior.
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 the core purpose and free of filler; every clause about trials, 402 handling, and payment routes is substantive. It is one dense paragraph where a short list of payment modes would scan faster, but nothing is wasted.
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 12-parameter, no-annotation, no-output-schema tool, the description covers the essential behaviors: trial limits, 402 fallback, receipt signing, and all payment paths. The per-parameter details are mostly handled by the 75%-covered schema, so the remaining gap is minor.
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 already 75%, so the baseline is 3. The description adds genuine value by grouping parameters into coherent payment modes (X-API-Key, payment_channel + secret, x_payment + nonce + secret), clarifying which params travel together in a way per-field schema text does not.
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 a specific verb (invoke) and resource (a capability found via market_search), making the search-then-invoke workflow unambiguous. It is cleanly distinguishable from the sibling market_search, which finds rather than calls capabilities.
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?
Makes clear this is the call that follows market_search and explains the trial-then-paid escalation path, including what happens when the free allowance runs out (402 + next_steps). It does not address when to prefer pipeline_invoke over this tool, leaving one sibling relationship unaddressed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
market_searchA
Search this hub's catalogue of live data and computation by what you need, in plain words. Each match gives the product_id, capability_id and source_hub to pass to market_invoke, its price, and input: the fields its input object takes.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results (default 10, max 50). | |
| budget | No | Optional cap on price per call, in USD. | |
| intent | Yes | What you want done, in plain language. | |
| category | No | Optional category filter, e.g. 'security'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavioral disclosure. It explains the search behavior ('by what you need, in plain words') and precisely describes the match result contents, including price and input fields. It does not mention auth, rate limits, or error behavior, but for a read-only search tool the disclosed behavior is sufficient.
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 a single, efficient sentence with no filler. It front-loads the core action, then immediately states the output contract and relationship to market_invoke. Every clause earns its place.
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?
With no output schema and no annotations, the description compensates by describing the key return fields and their purpose. It covers the main information an agent needs: search input style, result fields, pricing, and downstream invocation. It does not cover edge cases like empty results or exact matching behavior, hence not a perfect 5.
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%, so the baseline is 3. The description adds a bit of context by tying results to market_invoke and explaining what `input` represents, but it does not meaningfully expand on parameter semantics beyond what the schema already documents.
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?
Description opens with a specific verb and resource: 'Search this hub's catalogue of live data and computation'. It clearly defines the tool's purpose and differentiates it from siblings like market_invoke by stating that results contain IDs to pass to market_invoke.
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?
The description clearly implies when to use the tool: when you need to discover marketplace offerings before invoking them. It names market_invoke as the follow-up tool, providing a usage context. It does not explicitly state when not to use it or mention alternatives, so it misses full explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_invokeA
Execute or continue the SAME prepared graph. Submit authorizations when the signed quote enables gas_sponsorship, otherwise buyer-signed transactions; none for free steps. Never submit both payment modes. Retain run_id/access_token and the exact bundle. Pending is not failure; repeat the same run or read pipeline_status. Never create a replacement purchase after a lost response.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | ||
| access_token | Yes | ||
| transactions | No | ||
| authorizations | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it declares payment-mode mutual exclusivity, that 'pending is not failure', that the same run should be repeated rather than rerun from scratch, and that a replacement purchase must not be created after a lost response. This is exactly the idempotency/retry context an agent needs. It stops short of covering error surfaces, rate limits, or what a successful response yields.
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?
Telegraphic and front-loaded: the core action leads, followed by param selection rules and then retry safety. Nearly every clause carries an instruction, though the staccato style makes the workflow rules slightly harder to parse on first read than plain prose would.
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 two-phase payment workflow with no annotations and no output schema, the description supplies the mode-selection logic, the retry/pending semantics, and state retention guidance. The main remaining gap is what the caller should expect back and how failures other than 'pending' manifest, but the critical call-time decisions are covered.
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 coverage is 0%, so the description must compensate, and it does for the critical ambiguity: it explains when to populate authorizations versus transactions versus neither. run_id and access_token roles are only loosely implied by 'retain run_id/access_token', but the hardest parameter decision is fully resolved.
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 a specific verb+resource ('Execute or continue the SAME prepared graph') and implicitly distinguishes itself from pipeline_prepare (which prepares the graph) and pipeline_status (which it names as the read-only alternative). The word 'SAME' and 'prepared' make the relationship to siblings inferable, though the description never spells out what the graph actually accomplishes.
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?
Explicitly routes the agent: submit authorizations when the signed quote enables gas_sponsorship, otherwise buyer-signed transactions, and none for free steps, with a hard exclusion ('Never submit both payment modes'). It also names pipeline_status as the fallback when awaiting a pending result, giving both when-to-use and when-to-use-something-else.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_prepareA
Validate a graph and return a signed quote and payment offers. No work or payment. Free steps require no wallet; paid steps require buyer wallet address. Use gas_mode=required to demand gas sponsorship or auto to prefer it. Inspect ready/blockers and gas_sponsorship. Sign offers LOCALLY, never provide a private key. Then call pipeline_invoke.
| Name | Required | Description | Default |
|---|---|---|---|
| nodes | Yes | ||
| wallet | No | 0x0000000000000000000000000000000000000000 | |
| gas_mode | No | buyer | |
| max_budget_usd | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses that no work or payment occurs (dry-run nature), the wallet requirement branching on free vs paid steps, the gas_mode semantics, the output fields to inspect (ready/blockers, gas_sponsorship), and a security constraint (sign offers locally, never supply a private key).
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 the core action and outputs, then prerequisites, then the security note, then the follow-up tool. Six short sentences with no filler; every one adds an actionable fact.
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?
No output schema exists, so the description compensates by naming the response fields to inspect (ready/blockers, gas_sponsorship). Combined with the wallet/gas_mode rules and the next-step pointer, an agent has enough to call it; only max_budget_usd semantics remain unaddressed.
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 0%, so the description must compensate. It meaningfully explains wallet (only needed for paid steps) and gas_mode (required vs auto), and implies nodes via 'validate a graph', but max_budget_usd is never mentioned and node structure/limits are left entirely to 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?
States a specific verb (validate) and resource (a graph) plus the concrete outputs (signed quote, payment offers). It explicitly positions the tool relative to the sibling pipeline_invoke ('Then call pipeline_invoke'), so an agent can separate the two without opening either schema.
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 clear sequencing guidance ('Then call pipeline_invoke') and conditional usage for gas_mode=required vs auto. It stops short of stating when not to use it or what to do on failures, but the context for selecting it is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_refundA
Submit the original seller's refund authorization or resume the SAME refund. The recipient is the original buyer, amount is the paid step price, and the sponsor pays gas. Preserve the exact authorization after a lost response. Returns a separately signed credit note; the original bill is unchanged.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | ||
| step_id | Yes | ||
| access_token | Yes | ||
| authorization | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does substantial work: it names the recipient (original buyer), the amount (paid step price), the gas payer (sponsor), idempotent resume behavior via authorization preservation, and the return (separately signed credit note with the original bill unchanged). Missing only explicit permission/auth requirements and rate/limit behavior.
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?
Three dense sentences, front-loaded with the primary action, no filler. Every sentence adds information (action, money flow, idempotency, return).
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 mutation tool with no annotations and no output schema, the description supplies the key behavioral context an agent needs: who pays, who receives, idempotency handling, and the return format. The remaining gap is parameter-level documentation for the three required identifiers.
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 0%, so the description must compensate. It clarifies the 'authorization' parameter's purpose (preserving/resuming after a lost response), which is genuinely useful, but leaves run_id, step_id, and access_token undocumented with no format hints.
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 a specific verb and resource: 'Submit the original seller's refund authorization or resume the SAME refund.' This clearly distinguishes it from prepare/status siblings, though it does not name those siblings explicitly. An agent can tell this is the execution/lifecycle step for a refund.
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?
Implies two usage modes (submitting an authorization vs. resuming an existing refund) and hints at the lost-response recovery scenario. However, it never names pipeline_refund_prepare or pipeline_refund_status as alternatives or states the preconditions that select this tool over them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_refund_prepareA
Prepare a cash refund for a verified paid step of a finished pipeline. This moves no money. The original seller must approve the exact EIP-3009 authorization locally; never send a private key. Refunds require seller cooperation and a configured gas sponsor.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | ||
| step_id | Yes | ||
| access_token | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose meaningful traits: 'This moves no money' (despite the refund name) and the hard security constraint 'never send a private key.' It still omits what state preparation creates (reservation, expiry, idempotency) and what the seller-approval flow requires of the caller afterward.
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?
Four short sentences, front-loaded with the core action, each carrying distinct information (what it does, that no money moves, the auth requirement, the prerequisites). No filler or restatement of the name.
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?
Covers the safety profile and preconditions well, which is the critical part, but with no output schema and no annotations it should also signal what preparation yields and how to proceed (the follow-on pipeline_refund call). That workflow context 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 0% and the description says nothing about run_id, step_id, or access_token. The run_id pattern ('^paid_...') in the schema hints at format, but the description does not explain that run_id identifies the finished pipeline run, that step_id must be a verified paid step, or how access_token relates to the caller.
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 a specific verb+resource+scope: 'Prepare a cash refund for a verified paid step of a finished pipeline,' and clarifies it is a preparation step, not the execution. It does not, however, name the sibling it is distinguished from (pipeline_refund / pipeline_refund_status), so an agent must infer the routing rather than being told.
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?
Provides real preconditions ('seller must approve the authorization locally', 'refunds require seller cooperation and a configured gas sponsor'), which implies when the call can succeed. But it never states when to use this versus pipeline_refund or pipeline_refund_status, nor the ordering of the refund workflow, so the routing guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_refund_statusB
Read the saved cash-refund status and signed credit note without broadcasting a transaction. No private key or RPC is required. Pending means resume the same refund, never send a replacement transfer.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | ||
| step_id | Yes | ||
| access_token | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses that no private key or RPC is required and that no transaction is broadcast, and it clarifies the meaning of a pending status. It still does not mention required permissions or the access_token, but it covers the most important non-obvious behavioral traits.
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?
Three short sentences, each earning its place. The core read-only nature is front-loaded, followed by a useful operational constraint and a critical pending-status instruction. There is 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?
For a tool with three required, undocumented parameters, no output schema, and no annotations, the description is incomplete. It covers key behavioral points about non-broadcasting and pending handling, but it says nothing about input meaning, authentication details, or what the signed credit note return looks like.
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 0% and the description does not mention any of the three required parameters (run_id, step_id, access_token). It adds no meaning, format expectations, or constraints beyond the bare schema names.
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 states a specific verb ('Read') and resource ('saved cash-refund status and signed credit note') and explicitly distinguishes this from a broadcasting operation ('without broadcasting a transaction'). It does not name a sibling tool directly, but the contrast with pipeline_refund is clear enough.
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?
The description gives important in-state guidance ('Pending means resume the same refund, never send a replacement transfer'), which tells the agent what to do when status is pending. However, it does not state when to use this tool versus pipeline_refund, pipeline_refund_prepare, or pipeline_status, so broader usage context remains implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_statusA
Read an existing pipeline, including cached signed result, without broadcasting payments or invoking providers. No wallet signer or blockchain RPC required. Inspect recovery.action for unresolved work.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | ||
| access_token | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the safety profile itself and does it well: it is a pure read, does not broadcast payments, does not invoke providers, and needs no wallet signer or blockchain RPC. That is meaningful behavioral context for a mutation-adjacent domain. It stops short of stating whether access is scoped or whether the cached result can be stale.
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?
Three short sentences, purpose front-loaded, each adding distinct value: what it does, the constraints under which it runs, and a pointer to the actionable recovery.action field. 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?
No output schema, but the description compensates somewhat by naming the cached signed result and the recovery.action field. However, for a tool with two fully required, wholly undocumented parameters and no annotations, it leaves the auth token's origin and the run_id's source unaddressed.
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 0%, so the description must compensate for two undocumented parameters and does not: neither run_id nor access_token is explained, nor is where the access_token comes from or the paid_ hash format. The schema's regex and length bounds partially cover the gap, but the text adds nothing.
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 a specific verb (Read) and resource (an existing pipeline), and the read-only framing implicitly distinguishes it from the pipeline_prepare/pipeline_invoke siblings. It never names those siblings, so an agent must infer the routing rather than being told it.
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?
"Inspect recovery.action for unresolved work" hints at the retrieval use case, and 'without broadcasting payments or invoking providers' implies when to prefer this over an execute-style sibling. There is no explicit when-not or named alternative, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
- First observed
market_invoke - First observed
market_search - First observed
pipeline_invoke - First observed
pipeline_prepare - First observed
pipeline_refund - First observed
pipeline_refund_prepare - First observed
pipeline_refund_status - First observed
pipeline_status
TDQS
Scored across 8 tools
market_search vs market_invoke and the three pipeline_* tools have clearly distinct actions, and the refund trio is likewise separable. The only friction is that pipeline_refund_prepare vs pipeline_prepare and pipeline_refund_status vs pipeline_status look similar at a glance, but descriptions make the boundary clear.
All names are snake_case with a consistent prefix_action shape (market_*, pipeline_*, pipeline_refund_*). The addition of _status and _refund_* variants is slightly irregular but still fully predictable and readable.
Eight tools is well-scoped: two for marketplace discovery/invocation and three each for the pipeline and refund lifecycles, with no redundant entries.
The surface covers search, invoke, and full prepare/invoke/status lifecycles for both pipelines and refunds, with clear recovery via status tools. Gaps are minor (no listing of a caller's runs/purchases or explicit cancellation), which agents can largely work around.
Maintenance
Related MCP Connectors
The agent-to-agent capability exchange β rent memory, reasoning and safety, settled per call.
Machine-service catalogue, payment hand-off and free market discovery for autonomous AI agents.
Discover, compare, route, and execute machine-accessible capabilities for AI agents.
Procure governed AI capabilities: machine-readable price, scope, trust, gateway-delegation terms.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables agents to discover and pay for AI services per call via USDC on Solana, supporting marketplace search, listing details, on-chain reputation, wallet info, and paid calls.1 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables any MCP client to discover live MeshKore agents, see their current operational status and pricing, and directly invoke their skills without an SDK, account, or API key.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to discover and rank compatible external capabilities via natural language, with optional execution through a payment-safety-aware gateway.MIT

GateCoreofficial
AlicenseNot gradedqualityDmaintenanceEnables AI agents to discover governed capabilities, inspect machine-readable contracts, and request policy-checked procurements with signed receipts and audit trails.Apache 2.0