An autonomous on-chain storyteller. Every address holds a story. Render it. The ledger remembers; chainbard retells it. Paste a Solana identifier — a wallet, a transaction signature, an NFT, or a token mint — and chainbard discovers tools on the Synapse Agent Protocol (SAP), pulls live context from Ace Data Cloud + Synapse RPC, and renders a permanent, shareable story page. It runs two ways with no manual step in between: a reactive flow (a buyer pays 0.30 USDC over x402 for a story) and an autonomous daily curator tick (a cron agent picks a subject, researches it, and publishes — funded from its own treasury). Every Ace Data call is paid through the Ace Data Cloud x402 facilitator.
Live: https://chainbard.vercel.app · Tick log: https://chainbard.vercel.app/activity
Submission for the Superteam Earn bounty Autonomous Agent Bounty: OOBE × Ace Data Cloud.
Competing in Category 2 — Ace Data Cloud Usage (x402 Facilitator). The project targets AceData x402 USDC volume only; there is no Cat-1 escrow path. All buy-side Ace Data spend settles through the agent's own x402 self-broadcast rail on Synapse RPC (ADR 0016).
The agent identity rows below are fixed. The on-chain settlement and memo proofs are live-truth — they render fresh on
/judgefor reviewers to verify, so the standing proof surface is the page, not a static signature pinned here.
| What | Where |
|---|---|
| Deployed app | https://chainbard.vercel.app |
| On-chain proof surface (settlement sigs, memo trail, service provenance) | https://chainbard.vercel.app/judge |
| Public tick log (neutral story feed) | https://chainbard.vercel.app/activity |
| Registered agent (Synapse Explorer) | https://explorer.oobeprotocol.ai/agent/9cssRtj1tpo8juYMKVw4BLonEXnSH2e6bfc9Qp88fN48 |
Agent PDA (SAP AgentAccount) |
7WES6mSvsw3YnMBBvFQotK2GczLMgUCCiKxJFgRXUbYh |
| Settled x402 payment (agent → AceData) | live on /judge |
| SAP Memo v2 audit entry | live on /judge |
The /judge page is the on-chain proof surface — memo trail, settlement sigs,
and service provenance, all verifiable on Solscan. /activity is a neutral story
feed for discovery (timestamp, kind, story link only); spend posture and receipt
internals never leak on it (ADR 0016 §F).
Two paths, one public output (a story page at a permanent URL). Neither path has a manual step between trigger and published story. The whole system, top-level:
trigger SAP discovery execution x402 persist
{ reactive buyer ─▶ { AgentAccount PDAs ─▶ { Synapse RPC reads ─▶ { AceData x402 ─▶ permanent story page
| autonomous cron } via getProgramAccounts + Ace SERP/Chat/Image settlement; + /activity feed
+ Video/Audio } agent buys } + SAP Memo v2
buyer pastes input ──▶ POST /api/mint/story
│
├─ detectKind(input) wallet | tx | nft | token
├─ 402 + accepts[] server demands 0.30 USDC
├─ buyer signs X-Payment Ace Data x402 facilitator settles the sell-side on-chain
├─ x402-verifier amount + dest ATA + mint + slot freshness + sig dedupe
├─ spotlight-fetcher Synapse RPC + Ace SERP enrich
├─ story-renderer Ace Chat (structured) + multi-SERP + Ace Image (inline)
├─ persist ──▶ permanent story page at /[input], published immediately
└─ enqueue media-attach durable QStash job: video + audio generated out-of-band,
patched onto the story; the share page late-hydrates them
The story (chat + multi-SERP + image) publishes synchronously. Video and audio
are generated by a durable QStash media-attach job (/api/workflow/media-attach)
on the agent's own x402 rail and patched in afterward — the page is
eventually-consistent for media (ADR 0016 §D).
The primary autonomous trigger is an hourly Upstash QStash schedule that
POSTs the durable Workflow route (/api/workflow/autonomous-tick, resumable,
gated by QStash signing keys). An alternate synchronous trigger is available at
GET /api/cron/autonomous-tick (Vercel Cron endpoint, Bearer auth). Both execute
the same 5-step brain — no human, no buyer:
1. Ace SERP/news gather the day's on-chain signals
2. Ace Chat (structured) decide { kind, identifier, rationale }
3. Ace SERP enrich the chosen subject (multi-SERP)
4. Synapse RPC enrich on-chain (balances, asset data, history)
5. story-renderer Ace Chat + Ace Image + Video + Audio → publish + post URL to operator webhook
Each tick writes one SAP Memo v2 audit entry — a trimmed on-chain trail of
the render (render id, kind, public identifier, and service-provenance receipt;
rationale and source headline are deliberately dropped). The agent pays Ace Data
from its own treasury and consumes only third-party services — no self-dealing
(see CONTEXT.md).
- Agent network — chainbard enumerates every
AgentAccountPDA on the SAP program (getProgramAccountsagainst the on-chain IDL) atGET /api/agents/discover. This is the live capability network: who's registered, their capabilities, pricing, and x402 endpoints. The endpoint is read-only and public; it powers operator inspection and future UI surfaces.
- Always x402, never bypassed. Every Ace Data call — the reactive buy-side (chat / multi-SERP / image) and the autonomous tick's full pipeline — routes through the agent's x402 self-broadcast rail on the Ace Data Cloud x402 facilitator. There is no bearer/API-token fallback; the facilitator plane is the only path (ADR 0016 §A, ADR 0001).
- Synapse-first settlement. Each paid call settles through Synapse RPC
for Cat-2 compliance; if Synapse hasn't confirmed within ~15s, the same signed
tx is re-broadcast through
solana_send(a generic RPC) so an unreliable Synapse doesn't block settlement. Identical signature ⇒ the network executes it at most once — never a double-spend (ADR 0016, ADR 0012). On-chain reads (balances, asset data, history) also route through Synapse RPC. - Real sell-side verification. When a buyer pays the reactive flow, the
x402-verifiermodule checks payment amount, destination ATA, mint, slot freshness, and signature dedupe before serving — not just "is the signature confirmed." - Spend guard. The cost-guard is always-on with a hardcoded daily cap (ADR 0016 §G, ADR 0004) — a cheap runaway breaker, not an opt-in toggle. The agent wallet's USDC balance is the real ceiling; the in-memory daily cap is a safety secondary. Its breach is logged without dollar amounts on any public surface.
- Buyer-funded, agent-subsidised. The buyer's 0.30 USDC pays for the
synchronous story render (chat + multi-SERP + image). Video and audio are
enqueued asynchronously (the QStash media-attach job) on the agent's own x402
budget, subsidising media enrichment beyond the sell-side price — by design,
because buy-side volume is the Cat-2 metric (ADR 0016 §B).
Demo runs (
provenance='demo') are excluded from volume accounting (ADR 0005).
Every story carries a provenance tag — one of four values — so judge-relevant
volume can be read honestly, never inflated by self-dealing or demos:
provenance |
Wax-seal label | What it is |
|---|---|---|
seed |
curator seed | hand-seeded starter content |
buyer |
buyer render | someone paid 0.30 USDC over x402 through the reactive flow — including the smoke/test-loop wallet below, so buyer alone isn't proof of an external buyer |
curator |
curator pick | the autonomous tick paid Ace Data services via the agent's own x402 self-broadcast from treasury — legit Cat 2 consumption, counts |
demo |
demo run | the operator self-funds a demo-buyer that pays the agent's own ATA (self-dealing) — excluded |
listRecent filters with WHERE provenance <> 'demo', so demo and seeded
content never enter the real volume read (ADR 0005). The labels above are the
wax-seal text rendered on each story page.
A second exclusion lives at the wallet level, and it takes precedence over the
provenance tag: a continuous smoke / test-loop wallet
(4HtB4QCubGYpqUnY6DDiZY8WvtyAXbNveRagVSVNuYUf)
runs synthetic transactions to keep the pipeline warm. Because that wallet has
also been driven through the homepage reactive flow, some of its stories carry
the buyer tag — so reading honest external volume means excluding this wallet
regardless of provenance, not trusting the tag alone. As noted on
/judge, its transactions are synthetic —
exclude it from the memo trail to read the actual judge-relevant volume.
The daily curator tick runs on a schedule with no human and no buyer: it
decides its own subject, researches it, pays for the AI services it needs,
publishes the story, posts the URL to an operator webhook, and writes a trimmed
on-chain audit entry (service provenance only, no spend/rationale details).
Trigger → agent discovery → execution → payment → publish, end to end. The
/judge page is the on-chain proof surface (memo trail, settlement sigs, service
provenance); /activity is a neutral story feed for discovery.
The autonomous tick is always x402 — every call settles USDC through the agent's own x402 self-broadcast client (the agent is the SPL fee-payer/broadcaster, so it funds tx fees with a dust amount of SOL). Both the autonomous tick and the reactive mint use the same rich pipeline. The agent pays for all buy-side Ace Data consumption from its own treasury; there is no bearer-token fallback (ADR 0016 §A/§B). Per run, the tick books six-plus distinct Cat-2 services:
| Service | Ace surface | Role on the tick |
|---|---|---|
| SERP (Google) | ace.search.google |
The agent's eyes — multi-layer subject research (events, origin, price, sentiment, listing). |
| Chat (heavy) | ace.openai.chat.completions.create |
The brain — daily subject decision + narrative write, on ACE_CHAT_MODEL_HEAVY. |
| Image | ace.openai.images.generate |
Hero infographic (nano-banana → seedream), under CONTENT_POLICY (ADR 0002). |
| Video (primary) | ace.video.generate (veo / veo3) |
Abstract data-motion clip — kinetic typography / animated data card, no beings. |
| Video (fallback) | ace.video.generate (kling) |
Provider-chain fallback when the primary video provider fails. |
| Audio | ace.audio.generate (fish) |
Spoken-word narration of the story subtitle + lede. |
Call count per tick: Chat ≈ 1 (Director + write), multi-SERP up to 5 deterministic
queries (events / origin / price-analysis / sentiment / listing), Image 1, Video
primary 1 async task, Video fallback 1 (only if primary fails), Audio 1 async task
— up to 9+ paid calls. Video and audio are async (wait: false → a task id,
polled via the free ace.tasks.get), so the tick stays short while still booking
real Ace Data volume. Each is optional enrichment — a media failure never fails
the tick.
On the reactive mint, media is enriched post-publish via a durable QStash job
(/api/workflow/media-attach) that patches story.videoUrl/story.audioUrl
out-of-band, keeping the mint fast and the page eventually-consistent.
Cadence. The durable trigger runs hourly via Upstash QStash
(CRON_CADENCE_CRON defaults to 0 * * * *), which POSTs the Workflow route
(/api/workflow/autonomous-tick); QStash signing keys gate the endpoint.
Drain-to-zero by design. The agent is autonomous and unmaintained — it
burns until its treasury USDC is exhausted, then goes dormant by design. There
is no pre-flight balance gate: dormancy is triggered only when a paid call fails
at runtime due to insufficient USDC or SOL (on-chain 0x1 / SPL
InsufficientFunds). isFundsExhausted() classifies the error, setDormant()
persists an opaque reason code (no balance/floor numbers leaked), and the tick
short-circuits silently — no tick_log row, no webhook. While dormant the tick
stays quiet until the operator re-funds and clears the flag. There is no
auto-top-up: the burn is the point.
- Fund the agent — send USDC (the spend) and SOL (the agent is the x402 fee-payer/broadcaster, so it needs lamports for fees) to the agent wallet.
- Probe the rail — use the unified debug CLI to walk every stage:
bun run ace:debug <input> --liveruns detect → spotlights → director → multi-SERP → render → image → video → audio → persist → memo and prints, per stage, the provider + model in use, the output/link, and on failure the error- root cause. In
--liveit also prints the on-chain USDC settlement tx (Solscan link) for every successful paid call. For a fast service sanity-check,bun run scripts/spikes/x402-probe.tsstill fires one minimal paid call per service (chat, search, image, videoveo, videokling, audiofish) plus a freetasks.getretrieval, printing per-service OK / FAILED and the settle txs.
- root cause. In
- Set env — the pipeline is always-on with sensible defaults; no toggle
gates. Mandatory:
QSTASH_TOKEN,QSTASH_CURRENT_SIGNING_KEY,QSTASH_NEXT_SIGNING_KEY,WORKFLOW_URL,CRON_CADENCE_CRON(default0 * * * *),AGENT_SECRET_KEY_BASE58(required — the rail fails without it),SYNAPSE_RPC_URL(settlement compliance; falls back toSOLANA_RPC_URLif unset, losing the Synapse-in-execution benefit). Optional enrichment + config:ACE_CHAT_MODEL_HEAVY(heavy write/decision model; defaults toACE_CHAT_MODEL),VIDEO_PROVIDER/VIDEO_MODEL,VIDEO_FALLBACK_PROVIDER/VIDEO_FALLBACK_MODEL,AUDIO_PROVIDER/AUDIO_MODEL,IMAGE_PROVIDER/IMAGE_FALLBACK_PROVIDER,MEDIA_COLLECT_TIMEOUT_MS,SOLANA_SEND_RPC_URL,BLOB_READ_WRITE_TOKEN(Vercel Blob mirror for media). - Schedule it —
bun run scripts/setup-qstash-schedule.tsregisters the hourly QStash schedule (QSTASH_TOKEN,WORKFLOW_URL,CRON_CADENCE_CRON) that POSTs the Workflow route. From here the agent runs itself until the treasury runs dry.
| Requirement | Status |
|---|---|
| Registered on SAP mainnet | ✅ agent live on Synapse Explorer (see Proof) |
| Complete automated workflow | ✅ daily curator tick (QStash) + reactive flow |
| Ace Data Cloud account | ✅ |
| x402 with AceData facilitator + Synapse RPC in execution | ✅ always-x402 plane (ADR 0016) + Synapse-first settlement |
| ≥3 distinct Ace Data services | ✅ SERP (×5) + Chat (heavy) + Image + Video (primary + fallback) + Audio — 6+ total |
Two lanes — verify everything from the browser, or go deeper from the CLI.
Frontend (no wallet needed)
/judge— the on-chain proof surface: a live 402 probe against the reactive flow (see the real402and itsaccepts[]payment requirements, settled live), agent discovery, the SAP memo trail, and the curator history./activity— a neutral story feed of autonomous picks (timestamp, kind, story link). On-chain proof lives on/judge.- Home — paste any Solana identifier (wallet, tx, NFT, token mint) for a free read-only preview, no payment.
CLI
bun run demo # simulate the full flow, spends nothing
bun run demo -- --send # real mainnet writes: fund → pay → mint → publish → recover
bun run ace:debug <input> # debug the ACE flow (simulate by default, --live for real x402 spend)
bun run test-x402 # exercise the AceData x402 facilitator settlement
bun run check-agent # confirm the registered SAP AgentAccount on mainnet- Next.js
16.2.6(App Router, Turbopack,src/), React19.2.4, Tailwind^4.3.0, Bun, Biome (not ESLint) - Neon Postgres + Drizzle — story + activity repos
@oobe-protocol-labs/synapse-sap-sdk0.19.8— SAP register / discovery / memo@oobe-protocol-labs/synapse-client-sdk^2.0.6— Synapse RPC + x402@acedatacloud/sdk^2026.504.2+@acedatacloud/x402-client^2026.507.2— Ace Data APIs + x402 payment@solana/web3.js^1.98.4,@solana/spl-token,@coral-xyz/anchor,bs58,bn.js
SAP SDK note. The published
synapse-sap-sdk0.19.8 bundled IDL drifts from the deployed v0.18 program. chainbard uses the on-chain IDL (Program.fetchIdl+ Anchor coder) as the source of truth for account layouts and raw instruction discriminators. See ADR 0001.
bun install
cp .env.example .env.local # fill in keys (see comments in .env.example)
bun run check # biome + tsc
bun dev # http://localhost:3000Watch the full flow end-to-end without juggling a funded wallet:
bun run demo # simulate: read-only preview + real 402 probe, spends nothing
bun run demo -- --send # real mainnet writes: fund → pay → mint → publish → recover
bun run ace:debug <input> # walk every ACE stage with provider/model + error causesOther operator scripts: register-agent, check-agent, test-x402,
close-agent, fund-buyer, seed-mint, seed-featured, ace:debug. See
package.json.
The mark is a bard's plumed cap with a gold feather/quill (PlumeMark) on
warm near-black ground — "the bard sets a quill to your chain." Palette,
typography, asset files, and usage rules live in docs/brand.md.
- Glossary —
CONTEXT.md(every term used precisely) - ADRs —
docs/adr/(0001–0016): payment plane (0001), content policy (0002), virality-first / autonomous deprioritization (0003), cost guard (0004), demo self-funding exception (0005), payment-gated live render (0006), t3-env strict typed config (0007), two-tier brand mark (0008), streaming verbose mint console (0009), brief director no orchestration SDK (0010), token narrative-first (0011), synapse-primary x402 paid legs (0012), durable payment-intent idempotency (0013), token two-tier truth and infographic (0014), x402-cron conversion (0015), always-on pipeline Cat-2-only redacted surfaces (0016) - Integration notes —
docs/sap.md,docs/acedata.md,docs/synapse.md - Brand —
docs/brand.md(palette, typography, assets)
MIT — see LICENSE.
