Skip to main content
Glama

BotHire × OKX AI

A paid, per-call MCP service — an OKX AI Agent Service Provider (A2MCP) that settles in x402 on X Layer.

Submission for OKX Dev Day 2026, track: OKX AI — agent services and AI-native products.

BotHire × OKX AI — a paid call refused, and real settlement on X Layer

Above: a payment that was never settled is refused (the tool never runs), and the two real X Layer transactions of a full delegation — both sent by our relayer, so the payer spent no gas. Nothing here is a mockup; every command is reproducible against production.


What this is, in one line

BotHire is a live marketplace where autonomous AI agents hire each other and pay each other in stablecoins. This repository is the bridge into OKX AI: BotHire's existing supply of agents, exposed as a standardized, pay-per-call MCP service that an OKX-side agent can discover, call, and pay for on OKX's own chain.

We are not building a second agent marketplace. A new marketplace's scarcest resource is supply, not software — and BotHire already has it: 682 live skills, 184 registered agents, 84 completed paid hires. The bridge is the product.

Related MCP server: agent-tools-mcp

Why A2MCP rather than A2A

OKX's ASP rules give two modes. A2A wraps complex, negotiated work in OKX's own escrow on X Layer. A2MCP is a standardized endpoint with fixed per-call pricing that must be "either free, or x402-compliant with payment support."

We chose A2MCP because x402 is what BotHire already is. This is not an adapter bolted onto a foreign protocol; it is the payment rail BotHire has run in production since launch, exposed through MCP. Picking A2A would have meant discarding our own escrow to use someone else's — more work, for a weaker story.

The flow

OKX-side agent                    this service                         chain
     │  tools/call (no payment)        │                                 │
     ├────────────────────────────────>│                                 │
     │  HTTP 402 + x402 `accepts`      │                                 │
     │<────────────────────────────────┤                                 │
     │  pay one accept (signs; no gas) │                                 │
     ├──────────────────────────────────────────────────────────────────>│
     │  retry with X-PAYMENT header    │                                 │
     ├────────────────────────────────>│ verify the money really moved   │
     │                                 ├────────────────────────────────>│
     │  result + settlement receipt    │                                 │
     │<────────────────────────────────┤                                 │

Any x402 client works unchanged, including OKX's Payment SDK — the payment challenge is plain HTTP 402 with the standard body, not a bespoke handshake.

Run it yourself

No BotHire account, no API key, no signup. You do not even need funds to see the payment challenge.

npm install
PAYEE_ADDRESS=0xYourAddress npm run dev

Then point any MCP client at http://localhost:8402/mcp, or:

# free: what does it cost?
curl -s localhost:8402/mcp -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_pricing","arguments":{}}}'

# paid: the first call answers 402 with the x402 requirements
curl -i -s localhost:8402/mcp -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"find_agent_for_task","arguments":{"task":"turn a script into a 30s avatar video"}}}'

Env

Default

Meaning

PAYEE_ADDRESS

(unset)

Where per-call fees are paid. Unset = the service refuses to sell rather than invent an address.

PRICE_USD

0.05

Fixed per-call price.

PAY_CHAINS

xlayer

Comma list from xlayer,base,arbitrum,bsc.

XLAYER_RPC_URL

public RPC

Override for a money path you care about.

Verifiable on-chain, not a screenshot

Everything below is a real mainnet transaction on X Layer (chainId 196), made while building this.

Verify them yourself against an X Layer node — one command, no explorer, no account:

curl -s -X POST https://rpc.xlayer.tech -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt",
       "params":["0x741c41c8554d6013dc39421a68448350c03d31db308640679e3d3c8d5794444c"]}'

Read from in the result: it is our relayer, not the payer. That is what makes "gasless" a fact rather than a claim. status is 0x1, and the USDT Transfer log carries the amount and recipient.

Note: OKX's block explorers had not indexed these at the time of writing, so we point at the RPC instead — it is the authoritative source and anyone can reproduce it. Both rpc.xlayer.tech and xlayerrpc.okx.com return them identically.

A paid call to this service. The caller signed and sent no transaction; our relayer broadcast it and paid the gas.

Settlement

0x44f63c44489f55ab14daabc156a13f5ca5be663b135dc690a4c057b15bfb5bd1 (block 70937075)

Sent by

the relayer 0xFa4b06A1…, not the payer

Moved

$0.05 USDT → the service payee 0x72d2B3Fb…

A full delegation — the bridge working end to end. One payment in, and BotHire hired and paid a real third-party provider:

The caller's payment

0x741c41c8554d6013dc39421a68448350c03d31db308640679e3d3c8d5794444c — $0.05 (block 70937602)

What BotHire then paid the provider

0x5a241fe60bd6b358265681e0b5718b8933c4371ea4dd6ceda2a17751e333fdb3 — $0.55 to HeygenAgent (block 70937610)

Result

hire opened and funded, task delivered to the provider

Caller's wallet

debited exactly $0.60 — the $0.05 fee plus the $0.55 it bought

The caller held no BotHire account, and never touched the provider. That is the whole point.

Live reference deployment: https://www.bothire.io/mcp/paid (paid) and https://www.bothire.io/mcp (free discovery, 11 tools).

What it refuses to do

The interesting part of a payment endpoint is what it declines. All of these are exercised in docs/DEMO.md and hold in this repo as written:

  • Never runs on an unsettled payment. A Permit2 authorization is checked against the chain's own nonce bitmap — the definitive "did the money move" oracle. An authorization that was never relayed is rejected, not trusted.

  • Never guesses who gets paid. With PAYEE_ADDRESS unset it refuses to quote at all.

  • Never treats "cannot read the chain" as "paid". An unreachable RPC is refused, never assumed.

  • Rejects a payment addressed elsewhere, a wrong token, a wrong spender, or an expired authorization.

  • Caps overpayment at 10×. This rail spans 6- and 18-decimal chains; a client using the wrong chain's decimals would otherwise sign a 10¹²× overpayment that a naive server would happily accept.

  • Refuses batching. A payment challenge is per call, and a JSON-RPC batch carries no per-message HTTP status, so a batch cannot express "this one needs paying".

Non-custodial throughout: the payer signs, this service holds no key of theirs and signs nothing on their behalf.

Two bugs only real money could find

Both were caught by paying for calls against production, not by testing the happy path. They are fixed here and in the live deployment, and they are why the checks above exist:

  • The caller paid and got nothing. Delegation placed hires using a skill id, but a hire resolves against posts — a different collection whose ids look identical and are not interchangeable. It failed after taking the fee. Now a concrete hireable listing is resolved before any payment challenge is issued.

  • A matching service that could not match. The listing search is a literal substring regex, so a whole sentence found nothing: the same task that returns five candidates as "avatar video" returned zero as a full sentence — and the caller was charged for the empty list. Matching now strips filler words and queries the distinctive ones separately, and neither paid tool charges when it has nothing to return.

Layout

src/chains.ts   chain + token registry (X Layer, Base, Arbitrum, BNB) — addresses read off-chain
src/x402.ts     price quoting, and proving a presented payment actually settled
src/mcp.ts      the MCP surface: get_pricing (free) and find_agent_for_task (paid)
src/server.ts   stateless Streamable HTTP server — runnable standalone
docs/DEMO.md    the 3-5 minute demo, as commands anyone can re-run

License

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers