How MiroShark works
A deep walkthrough of the engine, by category.
MiroShark is a universal swarm-intelligence engine. You bring a scenario; it builds the world around it - a temporal knowledge graph, hundreds of grounded personas, three platforms running in lockstep, and a citing report at the end. Here is exactly how each layer is wired.
Last updated · July 23, 2026
MiroShark ships fast - this page is a snapshot, not a contract. For the latest features, env vars, model defaults and breaking changes, check the repo directly: recent commits, open & merged PRs, README and docs/. When in doubt, the code on main is the source of truth.
The five-step pipeline
Document in, world out. Every simulation walks the same five stages: build a graph, ground the personas, run three platforms in parallel, write a citing report, and let you interact.
1 · Graph build
2 · Agent setup
3 · Simulation
4 · Report
5 · Interaction
Output surfaces
document ─▶ graph build ─▶ persona grounding ─▶ 3× platform loop ─▶ report
│
├─ Director Mode (inject)
├─ Fork (branch)
└─ Persona Chat (DM)Knowledge graph & memory pipeline
A Neo4j-backed temporal graph - NER, entity resolution, contradiction detection, fused retrieval, and Leiden community clusters - inspired by Hindsight, Graphiti, Letta and HippoRAG.
Ingestion
Text flows through NER into a batched embedding call (OpenRouter text-embedding-3-large or local Ollama). Entity resolution fuses fuzzy matching, vector similarity and an LLM reflection step; a contradiction adjudicator invalidates stale edges instead of stacking them.
text → NER (with ontology)
→ batch embed (text-embedding-3-large | Ollama)
→ entity resolve (fuzzy + vector + LLM reflection)
→ MERGE entities (canonical UUIDs)
→ contradiction adjudication (invalidate old)
→ CREATE RELATION {valid_at, invalid_at, kind, source_type, source_id}Retrieval
Each query fans out into three parallel searches - vector edge search (Neo4j HNSW), BM25 fulltext and BFS traversal. Candidates are fused, filtered by valid_at / kind, and re-ranked by a BGE-reranker-v2-m3 cross-encoder.
query
├─ vector edge (Neo4j HNSW) ─┐
├─ BM25 edge (Neo4j fulltext) ─┼─ temporal + kind filters → fused top 30
└─ BFS traversal (from seed entities) ┘
↓
BGE-reranker-v2-m3 (MPS / CUDA / CPU)Communities (zoom-out)
Reasoning memory
What it buys you
Persona generation & grounding
Each agent is built from five layers of context - graph attributes, relationships, semantic neighbours, BFS context and (optionally) live web research - then anchored to Nemotron demographics.
Five layers of grounding
Individual vs institutional
Web enrichment
Self-hosted search & scrape (SearXNG / Firecrawl)
Demographic anchoring (Nemotron)
entity ─┬─ attrs (Neo4j properties)
├─ relationships (1-hop edges)
├─ semantic (vector neighbours)
├─ BFS context (multi-hop)
└─ web enrichment (public figures only)
↓
persona prompt ─▶ Wonderwall agent loopCross-platform simulation engine
Twitter, Reddit and a Polymarket-style prediction market run simultaneously every round. Belief states track stance, confidence and trust; a sliding-window memory keeps prompts compact.
┌─────────────────────────────────────────────┐ │ Round memory (sliding window) │ │ old: compacted · prev: full · now: live │ └──┬──────────────┬──────────────┬────────────┘ ┌──▼──────┐ ┌────▼────┐ ┌──────▼────────┐ │ Twitter │ │ Reddit │ │ Polymarket │ │ posts │ │ comments│ │ AMM trades │ └──┬──────┘ └────┬────┘ └──────┬────────┘ ┌──▼──────────────▼──────────────▼────────────┐ │ Market-media bridge (prices ⇄ posts) │ └──┬──────────────────────────────────────────┘ ┌──▼──────────────────────────────────────────┐ │ Belief state (per agent) │ │ stance[-1,+1] · confidence[0,1] · trust │ └─────────────────────────────────────────────┘
Three platforms, one round
Market-Media Bridge
Prediction market
Belief states
Sliding-window memory
Per-round frame API
Performance numbers (vs. naive baseline)
Neo4j writes 1 tx/entity → batched UNWIND (10×) Chunk + config sequential → parallel executors (3×) Memory compaction blocking → background thread
Live interaction - Director, chat, forks
Inject breaking news mid-run, fork the timeline with a counterfactual event, or DM any agent. Forks are first-class siblings; comparisons are diffable.
Director Mode (inject)
Counterfactual Branching (fork)
Persona chat
Reports, signals & analytics
A ReACT report agent cites real posts and trades, backed by a trajectory chart, signal JSON, consensus badge, per-run cost and quality diagnostics.
ReACT report agent
Signal JSON & direction
Trajectory chart (SVG)
Consensus badge (SVG)
Run cost (cost.json)
Quality diagnostics
Inputs - Smart Setup, Just Ask, Trending
Drop a doc, type a question, pick from RSS-driven trending news, or use one of nine preset templates - and run the full pipeline in EN / 中 / DE / FR.
Smart Setup
What's Trending
Just Ask
Preset templates
Locale - EN / 中 / DE / FR
Model routing - six slots, one key
LLM / Smart / Wonderwall / NER / Embedding / Reranker. One OpenRouter key, five env slots, full freedom to mix providers - including self-hosted vLLM or Claude Code with no API key.
MiroShark splits work across six model slots, so you keep the cheap loop cheap and spend only on the few prompts that steer the run.
LLM (default)
Smart
Wonderwall
NER
Embedding
Reranker
One key, five slots
Paste a single OpenRouter key into the five API-key env vars (LLM_API_KEY, SMART_API_KEY, NER_API_KEY, OPENAI_API_KEY, EMBEDDING_API_KEY). First run is ~10 min and ~$1.
Claude Code mode
Local Ollama
CoT toggle
MCP, webhooks, notifications
MCP server for Claude Desktop / Cursor / Windsurf / Continue. Signed webhooks with delivery log. Channel-native completion notifications on Discord, Slack, Email and Telegram. PWA push.
MCP server
Webhooks
Completion notifications
History database
Export, embed & provenance
37 published surfaces - provenance (reproduce.json, on-chain DKG, BibTeX), data exports (notebook, archive, clone), oEmbed/Frame v2 auto-unfurl, gallery feeds, and a self-describing /api/surfaces.json catalog.
Provenance
Data exports
Auto-unfurl
Feeds & live watch
Surface catalog (surfaces.json)
Every export surface is built on pure stdlib and is opt-in via env flag. See the full reference in docs/FEATURES.md.
Ecosystem & integrators
Projects, agents and tools built on MiroShark - a human-readable ECOSYSTEM.md and a machine-readable /api/ecosystem.json catalog that integrators and registries crawl.
ECOSYSTEM.md (human-readable)
/api/ecosystem.json (machine-readable)
Who's building on it
Drive it from anywhere
GET /api/ecosystem.json
{ "success": true,
"data": {
"schema_version": "1",
"count": 14,
"ecosystem": [
{ "name": "Sparkleware", "category": "integration",
"x_handle": "…", "repo": "https://github.com/…" },
…
] } }Add your project with a PR to ECOSYSTEM.md - a square 40 px logo, one-line description, category and links. The machine-readable catalog stays in lockstep via a drift-guard test.
Run MiroShark over x402
x402 turns the dormant HTTP 402 "Payment Required" status into a real payment rail: the server answers a request with a price, the client pays stablecoin over HTTP, and the same request goes through - no account, no API key, no signup. MiroShark is a paid x402 endpoint - your agent POSTs a prompt, pays $1 USDC, and gets back a live URL where a full multi-agent simulation report appears in ~10 minutes.
What you get for $1
Flat price, one dollar
No account, no key
Three chains, one endpoint
POST /run ($1 USDC)
│
├─ ingest seed → entities (~8 s)
├─ ontology entity types (~10 s)
├─ graph_build Neo4j knowledge graph (~11 s)
├─ create simulation scaffold (~0 s)
├─ prepare ~25 grounded personas (~70 s)
├─ simulate 10 rounds · Twitter/Reddit/Market (~6-18 min)
└─ report cited markdown post-mortem
│
└─▶ share_url (auto-published, recap card, 7 panels)The /run endpoint - seeds & price
POST /run with exactly one seed - a prompt, an article URL, or raw text. The price is a flat $1.00 USDC, settled on Base, Solana, or Monad - the 402 advertises all three and your wallet picks the chain it holds.
One seed, three shapes
{"prompt": "<scenario or question, 4-4000 chars>"} ← most common
{"url": "<article / news URL - MiroShark fetches & simulates it>"}
{"article": "<raw document text, 4-200000 chars>"}Price
No gas needed
Where the $1 goes - pick the chain your wallet holds
Base mainnet network eip155:8453
USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
payTo 0x6cab485fc28ec70d3845113b704d4824e4d2b24f
amount "1000000"
Solana mainnet network solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
payTo 9vWbPNMvt8ui1cNN8jWWPUWT5LPmeXzq7nr3vry1vMPH
amount "1000000"
Monad mainnet network eip155:143
USDC 0x754704Bc059F8C67012fEd69BC8A327a5aafb603
payTo 0x0000CE08fa224696A819877070BF378e8B131ACF
amount "1000000"Always trust the live 402 response's PAYMENT-REQUIRED header (base64 JSON, field accepts[]) over anything hardcoded - the values above are just a head-start so you can pre-fund the right wallet.
The x402 payment flow
The standard x402 v2 flow: POST, 402 with a PAYMENT-REQUIRED header, sign the USDC transfer, re-POST with PAYMENT-SIGNATURE, 202 Accepted with your run_id and follow URLs. Gas is sponsored by the facilitator (CDP for Base + Solana, the Monad facilitator for Monad).
1. POST /run (no payment)
↓
2. 402 Payment Required + PAYMENT-REQUIRED header (base64 accepts[])
↓
3. client decodes accepts[], signs the USDC transfer authorization
↓
4. POST /run again + PAYMENT-SIGNATURE header (the signed payload), SAME body
↓
5. server settles on-chain → 202 Accepted + PAYMENT-RESPONSE (tx hash)What a v2 SDK does for you
The 202 response body
HTTP/2 202 Accepted
PAYMENT-RESPONSE: <base64 SettleResponse - tx hash + payer + network>
{
"success": true,
"data": {
"run_id": "run_86ead0ea7fa7",
"status": "queued",
"stages": ["ingest","ontology","graph_build","create","prepare","simulate","report"],
"wait_url": "https://x402.miroshark.xyz/wait/run_86ead0ea7fa7",
"status_url":"https://x402.miroshark.xyz/status/run_86ead0ea7fa7",
"payer": "0xYourWalletAddress",
"payment_chain": "base",
"payment_network": "eip155:8453",
"cancel_token": "q3V9...kZ0"
}
}Keep cancel_token private. It is the only way to cancel the run, it appears only in this response (and in an idempotent replay of it), and the server stores just a hash.
Pay from any runtime
Drop-in code for the official x402 SDK in Python (Base, Solana + Monad) and TypeScript, the awal CLI for shell agents, the payments MCP for Claude Desktop / ChatGPT, and an ERC-7710 sidecar for MetaMask Smart Accounts.
Python - Base (EVM), official x402 SDK
pip install 'x402[evm,requests]' eth-account requests
import os
from eth_account import Account
from x402.client import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm.exact.client import ExactEvmScheme
account = Account.from_key(os.environ["X402_BUYER_PRIVATE_KEY"])
client = x402ClientSync()
client.register("eip155:8453", ExactEvmScheme(signer=account)) # Base mainnet
session = x402_requests(client) # handles 402 → sign → retry automatically
resp = session.post(
"https://x402.miroshark.xyz/run",
json={"prompt": "How will developers react if OpenAI releases GPT-6 next month?"},
timeout=120,
)
data = resp.json()["data"]
print("Run ID:", data["run_id"], "| follow:", data["wait_url"])Fund the address with ~$1+ USDC on Base mainnet - no ETH needed, gas is sponsored.
Python - Solana (SVM)
pip install 'x402[svm,requests]'
import os, json
from solders.keypair import Keypair
from x402.client import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.svm.exact.client import ExactSvmScheme
from x402.mechanisms.svm.signers import KeypairSigner
SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
raw = os.environ["SOLANA_BUYER_PRIVATE_KEY"].strip()
kp = (Keypair.from_bytes(bytes(json.loads(raw))) if raw.startswith("[")
else Keypair.from_base58_string(raw))
client = x402ClientSync()
client.register(SOLANA_MAINNET, ExactSvmScheme(signer=KeypairSigner(kp)))
session = x402_requests(client) # picks the Solana accepts[] entry automatically
resp = session.post(
"https://x402.miroshark.xyz/run",
json={"prompt": "Your scenario"}, timeout=120,
)
print(resp.json()["data"]["run_id"]) # paid on: "solana"Python - Monad (EVM), official x402 SDK
import os
from eth_account import Account
from x402.client import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm.exact.client import ExactEvmScheme
account = Account.from_key(os.environ["X402_BUYER_PRIVATE_KEY"])
client = x402ClientSync()
client.register("eip155:143", ExactEvmScheme(signer=account)) # Monad mainnet
session = x402_requests(client) # picks the Monad accepts[] entry automatically
resp = session.post(
"https://x402.miroshark.xyz/run",
json={"prompt": "Your scenario"}, timeout=120,
)
print(resp.json()["data"]["run_id"]) # paid on: "monad"Fund the address with ~$1+ USDC on Monad mainnet - no MON needed, gas is sponsored by the Monad facilitator.
TypeScript / JavaScript
npm install @x402/fetch @x402/evm viem
import { x402Client } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
const signer = privateKeyToAccount(process.env.X402_BUYER_PRIVATE_KEY as `0x${string}`);
registerExactEvmScheme(client, { signer });
const res = await client.fetch("https://x402.miroshark.xyz/run", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "Your scenario" }),
});
const data = (await res.json()).data;Shell / CLI agents
npx awal x402 pay \
https://x402.miroshark.xyz/run \
--body '{"prompt":"Your scenario"}'MCP-only hosts
MetaMask Smart Accounts
Any x402 v2 client works - these are the common ones. To mint a throwaway EVM wallet locally (the key never leaves your machine): python -c "from eth_account import Account; a=Account.create(); print(a.address, a.key.hex())", then fund it with USDC on Base.
Tuning the run
Two optional fields ride along with any seed: prediction_market to pin the central market. A live-web deep-research sweep runs automatically for prompt seeds.
deep research - automatic for prompt seeds
{"prompt": "EU AI Act enforcement in 2026"}
// → live-web deep research runs automaticallyprediction_market - pin the market
{"prompt": "...",
"prediction_market": {
"question": "Will Argentina win the 2026 FIFA World Cup?",
"outcome_a": "YES", "outcome_b": "NO",
"initial_probability": 0.28
}}Follow the run & read the report
Reading needs only the run_id - no auth. Poll /status for JSON, open /wait for an auto-refreshing page, or pull the finished report as raw markdown or JSON from /report. Cancelling needs the private cancel_token from the /run response. Every run auto-publishes a shareable recap card.
status_url - JSON, for agents
wait_url - HTML, for humans
The status payload (declared in /openapi.json)
GET /status/<run_id>
{
"success": true,
"data": {
"run_id": "run_86ead0ea7fa7",
"status": "running", // queued | running | completed | failed | budget_exceeded | cancelled
"progress": 42, // 0-100
"current_stage": "simulate",
"current_round": 4,
"message": "Round 4/10",
"simulation_id": null, // set on completion
"share_url": null, // set on completion → https://<host>/share/<sim_id>
"budget": {"cost_usd": 0.11, "tokens_used": 184223, "calls": 57},
"payment_chain": "solana",
"payment_network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
}
}Poll until status is completed, failed, budget_exceeded or cancelled. Note stages here is an object keyed by stage name, whereas the stages in the 202 body is an array - don't reuse one parser for both.
Cancel a run
POST /cancel/<run_id>
X-Cancel-Token: <cancel_token from the /run response>
202 {"success": true, "data": {"run_id": "run_86ead0ea7fa7", "status": "cancelled", "signaled": true}}The run_id alone is not enough: run ids appear in share links and the public grid. Idempotent. Responses: 409 already_terminal if the run already finished, 401 cancel_token_required without the header, 403 invalid_cancel_token for a wrong token. Cancelling early stops LLM spend, so more of the $1 stays as your builder share.
Read the report without the website
GET /report/<run_id>?format=md → raw markdown
GET /report/<run_id>?format=json → {report_markdown, title, share_url, …}Before the run finishes these return 409 with the current status.The recap card (auto-unfurl)
GET /api/simulation/<sim_id>/share-card.pngGenerated on first request and cached, so it's cheap to hot-link.
Pre-flight & health checks
Three unpaid helpers: /suggest turns a vague topic into launchable prompts before you spend a cent, and /health + /ready tell you the service is up so your settle doesn't fail.
/suggest - ideas before you spend
POST /suggest {"prompt": "stablecoin regulation"}
→ {"data": {"ideas": [{title, pitch, prompt, angle}, …]}}/health & /ready - is it up?
GET /health → liveness, no downstream checks GET /ready → 200 when DB + Neo4j are reachable; 503 otherwiseThere are no chargebacks, so waiting for a green /ready is the cheapest insurance you have.
Discover & verify the service
MiroShark is cataloged across the main x402 directories - CDP Bazaar, agentic.market, x402scan, AgentCash, Ampersend - so an agent can find and vet it by semantic search before ever making a paid call.
Listed as “MiroShark”
Pick before paying
Where MiroShark indexes
- CDP Bazaar - indexes on each successful settle from the service metadata + bazaar schemas.
- agentic.market - mirrors CDP Bazaar automatically.
- x402scan & AgentCash - read GET /openapi.json (OpenAPI 3.1) as the canonical contract.
- Ampersend marketplace - curated catalog; maps /skill.md + /logo.png to its skillmd_url / logo_url fields.
# CDP discovery is read-only and unauthenticated: curl 'https://api.cdp.coinbase.com/platform/v2/x402/discovery/search?query=miroshark' curl 'https://api.cdp.coinbase.com/platform/v2/x402/discovery/merchant?payTo=0x6cab485fc28ec70d3845113b704d4824e4d2b24f'
Wire-format reference
If you don't use a v2-aware SDK, here are the exact bytes: the base64 PAYMENT-REQUIRED challenge with all three accepts[] entries, the PAYMENT-SIGNATURE payload shape, and the PAYMENT-RESPONSE that carries your tx hash.
1 · The 402 challenge (decoded PAYMENT-REQUIRED)
{
"x402Version": 2,
"resource": {
"url": "https://x402.miroshark.xyz/run",
"serviceName": "MiroShark",
"tags": ["Simulation","Research","Search","Crypto","AI"]
},
"accepts": [
{ "scheme":"exact", "network":"eip155:8453",
"asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount":"1000000",
"payTo":"0x6cab485fc28ec70d3845113b704d4824e4d2b24f",
"maxTimeoutSeconds":300, "extra":{"name":"USDC","version":"2"} },
{ "scheme":"exact", "network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount":"1000000",
"payTo":"9vWbPNMvt8ui1cNN8jWWPUWT5LPmeXzq7nr3vry1vMPH",
"maxTimeoutSeconds":300, "extra":{"feePayer":"<facilitator-sponsored>"} },
{ "scheme":"exact", "network":"eip155:143",
"asset":"0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
"amount":"1000000",
"payTo":"0x0000CE08fa224696A819877070BF378e8B131ACF",
"maxTimeoutSeconds":300, "extra":{"name":"USDC","version":"2"} }
]
}Three entries - Base (EVM), Solana, and Monad (EVM) - all $1 USDC. Pick the one matching your wallet's chain.2 · Retry with PAYMENT-SIGNATURE (Base / EVM example)
{
"x402Version": 2,
"accepted": { … the chosen accepts[] entry … },
"resource": "https://x402.miroshark.xyz/run",
"payload": {
"signature": "0x…",
"authorization": {
"from": "0xYourWalletAddress",
"to": "0x6cab485fc28ec70d3845113b704d4824e4d2b24f",
"value":"1000000",
"validAfter":"…", "validBefore":"…",
"nonce":"0x<random 32 bytes>"
}
}
}On Solana you build and sign an SPL Token transfer of the same amount, leaving feePayer to the facilitator - the SDK's SVM scheme handles it.3 · The settle (decoded PAYMENT-RESPONSE)
{
"success": true,
"transaction": "0x1f2ab48e…2ee06a", // on-chain USDC transfer
"network": "eip155:8453",
"payer": "0xYourWalletAddress"
}Verify the transaction on BaseScan (Base) or Solscan (Solana - a base58 signature), or MonadVision (Monad). The same payment_chain / payment_network ride along in the 202 body and every /status response.Full reference: the x402 v2 specification.
Caveats - finality, refunds & errors
x402 is final - once USDC settles there is no chargeback. Design retries that never double-pay, know what 402 / 429 / 404 each mean, and understand there is no automatic refund if a paid run fails.
No chargebacks - ever
No automatic refund on failure
Runs take 15-20 min
404 on status_url
402 returned again after you sent PAYMENT-SIGNATURE?
Usually insufficient USDC, a signature mismatch, a reused nonce (EVM) or a stale blockhash (Solana). Check the balance on BaseScan / Solscan, mint a fresh nonce, confirm the EIP-712 domain matches extra.name / extra.version, and make sure you signed the right chain's accepts[] entry.
Heads-up for pay / pay.sh users: the CLI only routes x402 for endpoints in its catalog. MiroShark's listing is pending; until it merges, pay falls back to MPP and won't settle here - use any direct x402 client above.
Revenue share - the x402aff kit
MiroShark pays the apps that drive paying users a cut - 10% of each $1 run by default - enforced on-chain at settlement. It runs on the open-source x402aff kit (MIT, on npm + PyPI as x402aff, repo github.com/MiroShark/x402aff), not a bespoke MiroShark mechanism, so any x402 seller can pay their own builders the same way.
Earn a cut - attach a Base Builder Code (builder side)
npm install @x402/extensions
import { BuilderCodeClientExtension } from "@x402/extensions/builder-code";
// on the same x402Client() you registered the scheme on, before paying:
client.registerExtension(new BuilderCodeClientExtension("bc_yourcode"));
// every payment you drive now carries your code on-chainWhere the money goes
Run it on your own API (seller side)
npm install x402aff viem # or: pip install x402aff
import { Affiliation } from "x402aff";
const aff = new Affiliation({ appCode: "bc_yourcode", sellerPayout: "0x…" });
// aff.payTo is a drop-in x402 DynamicPayTo callback:
paymentMiddleware(facilitator, {
"/api/data": { payTo: aff.payTo, extensions: aff.extensions },
});Set your route's payTo to aff.payTo and each payment settles into a per-builder split instead of your wallet. An unknown or unresolvable code falls back to your wallet, so a payment never fails - it just isn't split. Python is the same shape: pip install x402aff, then Affiliation(app_code="bc_yourcode", seller_payout=…).
Live dashboard
The x402aff dashboard is this kit running live against MiroShark - every split, balance and claim on it comes straight from the kit. Its All sellers view lists every split the kit has routed on Base, whoever runs it.
Your first simulation takes ~10 min and ~$1.
One OpenRouter key, one launcher. Clone, drop the key into the five slots, run ./miroshark, openlocalhost:3000.