Disambiguation note. "AgentOracle" / "npb-win-probability-oracle" is a congested name in 2026. This article is about
npb-win-probability-oracle— a sports prediction oracle on Solana mainnet, focused on Japanese pro baseball (NPB). It is unrelated to two other projects that share variations of the name:
- TKCollective's AgentOracle (github.com/TKCollective, agentoracle.co) — a trust/verification layer for AI agents, powered by Perplexity Sonar, x402-native on Base mainnet. Different concept (claim verification), different chain.
- aiagentoracle.ai — a separate on-chain crypto token data API on Base. Different concept (crypto market data), different chain.
I picked the
npb-win-probability-oraclerepo name before realizing the namespace was this crowded. Treat the three as distinct services; this article is only about the Solana / NPB / sports-prediction one.
Why I built this
The x402 protocol layer is decided. Coinbase, Cloudflare, and the Linux Foundation co-launched the x402 Foundation; the spec is settled; SDKs in TypeScript, Python, Go, and Rust exist; the CDP facilitator processes settlements on Base, Polygon, Arbitrum, World, and Solana. The interesting question is no longer "will agent-native payments work?" It is "what does the application layer on top look like?"
I had a useful asset for that question: a Python NPB (Nippon Professional Baseball) prediction tool I have been running privately for a while. XGBoost model, 28,968 historical games (2008–2025), 61 features, AUC 0.5622 on out-of-sample data, three OOS strategies that survive backtests. Not earth-shattering numbers in isolation, but enough edge to feed a paid prediction oracle, and the domain (Japanese pro baseball with Asian Handicap integration) is essentially uncovered by English-language sports oracle services.
The Renaissance-style approach: keep the bleeding-edge model private, ship the 1–2 generation-older version as the commercial product. That tool is npb-win-probability-oracle.
Architecture
Stack:
-
oracle-api: Hono on Node.js, deployed on Railway. Twelve paid endpoints under
/v1/npb/*. Pricing $0.001–$0.10 per call (USDC, Solana mainnet,exactscheme). -
orchestrator: dockerized Node.js worker pool. Runs eleven bot processes that hit oracle-api on cron schedules, settle payments, log results. Also hosts the
bazaar-watchdaemon (external payer detection) androyalty-distributor(90/10 platform/creator split for Marketplace). - predictor: FastAPI services for NPB. Internal HTTP from oracle-api, no x402 (private RPC).
- dashboard: Next.js 14 App Router on Vercel.
- DB: Supabase Postgres. Polling, not WebSocket, because Docker for Windows VPNkit blocks the realtime channel (ADR-013 in our repo).
- facilitator: We started on PayAI, migrated to corbits.dev after ADR-022/023-class incidents (more below), and now use the CDP facilitator for mainnet x402 settlement.
Every paid endpoint emits a v2 Bazaar discovery extension on its 402 response. The paymentRequirements.extensions.bazaar block contains info.input, info.output (with format text and an example), the JSON Schema, a custom metadata object (category, tags, quality signals), and the route template. When the CDP facilitator processes a settlement on one of these endpoints, it extracts that block and catalogs the resource into the public Bazaar discovery API.
Operational data — transparent disclosure
This is the part that deserves honesty rather than marketing.
- Eleven bots in parallel, more than one hundred hours of continuous uptime on Solana mainnet.
- Cumulative settlement: 7,108 paid x402 transactions, roughly 70 USDC settled on-chain.
- All of that traffic is self-funded. Every paying wallet is one of mine — eleven mainnet bots plus a handful of legacy faucet wallets and smoke-test addresses. External paying customers: zero.
Why call this out instead of leaning on the "7,108 mainnet transactions" line as social proof? Two reasons.
First, the AI agent ecosystem is small enough that anyone curious can verify the funding flow on-chain in about ten minutes. Posting big numbers without disclosure is wash-trading optics, and dev communities sniff that out fast.
Second, when I queried the CDP Bazaar discovery API directly, my own service appears with l30DaysTotalCalls=22 and l30DaysUniquePayers=11 — those eleven payers are precisely my mainnet bots, individually accounted for in our WALLET_REGISTRY. The Bazaar's own quality signals already tell the story; pretending otherwise to readers would be pointless.
The number that matters is uptime, not call volume. The pipeline survived a Railway build break (force flag deprecation), a facilitator migration, a wallet-role conflict triage, a marketplace dynamic-price design failure, and a payment-required cache layer redesign — and it has been processing settlements continuously since.
What is actually novel
When I pulled the full CDP Bazaar resource catalog and grouped by category metadata, the result was striking.
- 47,146 total resources in the Bazaar.
- Of the 1,000 I sampled in detail: 994 have no
categoryset on their Bazaar metadata. Five use"Data". One uses"sports-prediction"— npb-win-probability-oracle.
We are the only sports-prediction service in the entire Bazaar today. That is a fact about the catalog, not a marketing claim. The Bazaar v2 metadata fields are recent, and most service operators have not adopted them yet. Whoever ships first in a category effectively defines it.
The NPB-specific edges:
-
Asian Handicap integration. Daily AH snapshots scraped from a Japanese pipeline, exposed via
/v1/npb/ah/:date. English-language sports oracle services rarely cover AH at all. - XGBoost v8 with documented AUC 0.5622 OOS on 28,968 historical games. Three OOS strategies survive the cut.
- 12 paid endpoints with the full Bazaar v2 manifest: win probability, daily list, post-game results, full box scores, AH movement, forecast (win prob + expected runs), per-season pitcher / batter / fielder rankings, and individual player lookups.
- Quality signals (
model_auc,oos_strategies_passed,coverage_seasons,training_set_size,mainnet_tx_count) are declared inextensions.bazaar.metadata.qualityand surface in the Bazaar discovery response.
Discovery layer — what actually works and what doesn't
I have spent enough time inside the discovery layer to share the honest map.
What works:
- The CDP facilitator does index v2 Bazaar manifests automatically. After Phase 11 of our build, every paid settlement refreshed our catalog entry; the metadata block round-trips intact.
- The paginated catalog endpoint (
GET /v2/x402/discovery/resources) is fast and unauthenticated. You can fetch your own indexed entry, audit which endpoints are catalogued, and watch yourl30DaysTotalCallsandl30DaysUniquePayersmove in near real time. - The Bazaar's own
lastUpdatedtimestamp moves the instant a settlement clears, which means you can detect downstream breakage in seconds.
What doesn't (yet):
- The semantic search endpoint (
GET /v2/x402/discovery/search?q=...) currently returns the same top results regardless of the query string. I tested withq=oracle,q=npb,q=baseball,q=sports+prediction, andq=win+probability— the top five resources are identical across all five queries, and they happen to be the same top five from the popularity-ranked default. Theqparameter appears to be accepted but not yet wired to a semantic backend. - This matters because the implicit assumption — "ship rich metadata and AI agents will find me" — does not hold today. Discoverability is currently popularity-bootstrapped, not metadata-driven. The top-ranked services have
l30DaysTotalCallsin the tens of thousands. A new service ships at 0 and has to climb. - Category filtering exists in the API surface but the response did not include our entry when I queried
category=sports-prediction. Either it's not fully wired or our entry was excluded by a default sort I haven't reverse-engineered.
The practical implication: do invest in the metadata (it costs little and is correct in the long run), but do not expect Bazaar discovery to deliver organic external traffic in 2026. Outreach, partnerships, and direct integration deals are still the primary growth surface.
ADR / engineering takeaways
A few cuts of scar tissue from the build:
-
ADR-022: The CDP facilitator requires
schemeandnetworkat the top level of payment requirements, not just nested inside SDK-emittedaccepts[]. The TypeScript SDK happily emits a structurally-valid request that the facilitator's business logic rejects. We learned this the hard way after a wave of 402 errors with empty bodies in production. -
ADR-023: The CDP
/verifyendpoint rejectsinstructionsin the payment memo (Solana memo program). PayAI had accepted this; CDP did not. The cleanest path was migrating to corbits.dev as the facilitator and dropping memo content entirely. - ADR-080: Wallet roles need to be separated (creator vs distributor vs platform vs oracle revenue receiver), even if the same key signs all of them for a while. The orchestrator now warns when role pubkeys collide. We will rotate the creator/distributor split before β release.
-
WALLET_REGISTRY: External payer detection needs a single source of truth for "internal" wallets. We cross-checked three sources (env, Supabase
botstable, HANDOFF history) and emit a typedINTERNAL_WALLET_REGISTRYof 25 entries with role labels. Thebazaar-watchdaemon polls Supabase every five minutes; the moment a payer outside this registry appears, it fires a Telegram alert with the tx hash and Solana Explorer link. We dry-ran 7,108 historical paid tx against the registry: zero false positives, which gives us confidence that "first external customer" will be a clean signal.
These are the kinds of things you only learn by shipping into mainnet and letting bots hammer the pipeline for a month.
What's next
- β release on 2026-05-21 JST. Marketplace UI public — strategy listings, royalty distribution on-chain with a 90/10 creator/platform split.
- External-customer detection wired. When the first non-internal wallet pays for an endpoint, the daemon Telegram-pings me with the payer pubkey, endpoint, amount, and explorer link. That moment is the actual goalpost; everything before it is just keeping the lights on.
-
x402.org/ecosystem submission open at
github.com/x402-foundation/x402/pull/2303. Single signed commit, two files: ametadata.jsonpartner entry and an SVG logo. Review window expires 2026-05-22. -
Endpoint coverage: only
/v1/npb/games/:date/win-probis currently indexed in the Bazaar because that is the only endpoint my internal bots hit. The other eleven endpoints will catalog as soon as a paid settlement clears against them. Forcing this with self-funded calls would be cheap, but I would rather wait for an actual external request to drive the first indexing event on each surface.
Closing
If you are building an AI agent that needs sports data — predictions, schedules, post-game results, batting/pitching stats, AH movements — the endpoints are live and payable in mainnet USDC via x402, priced between $0.001 and $0.10 per call. You can hit /v1/npb/games/2026-05-21/win-prob today and the bazaar-watch daemon will tell me you exist.
- Production API:
https://oracle-api-production-766f.up.railway.app - x402 ecosystem PR:
https://github.com/x402-foundation/x402/pull/2303 - I'm
@AsaiShotaon GitHub.
Honest take to leave you with: the AI agent economy in 2026 looks like infrastructure people running their own bots through their own services to test their own infrastructure. Real external customer flow — the kind that justifies the "agentic commerce" framing — is still the hard part, and it's not visible yet in the Bazaar's own quality signals. The infra is the easy part. The customer is the work.
Top comments (0)