Ask once. Get the best of many models.
Inspired by OpenRouter's Fusion.
Asking several LLMs the same question usually leaves you to reconcile N different answers. Synth does that part for you: your question fans out to several models in parallel, a judge model compares their answers — where they agree, where they differ, what each one misses — and a synthesiser model fuses everything into one answer that's better than any single response. Every stage streams live to a 3‑step UI.
It runs entirely on Cloudflare — Workers, Durable Objects, the env.AI binding (AI Gateway + Unified Billing), D1, and R2 — so one account reaches OpenAI, Anthropic, Google and Workers AI models with no per‑provider keys and no secrets to manage.
All model traffic goes through the Workers AI binding (env.AI.run), which routes both
third-party models (OpenAI / Anthropic / Google / …, billed via Unified Billing) and @cf/*
models (Workers AI pricing) through AI Gateway. The binding authenticates via the account itself —
no API token, no account id, no per-provider keys.
A single Worker serves the React SPA and the API/WebSocket:
**POST /api/runs**mints a run id; the client opens**GET /ws/:runId**, which upgrades to a per-run Durable Object (SynthesisRun).- The DO drives the pipeline: parallel fan-out of the panel models → quorum check → judge (structured JSON) → synthesiser (streamed), broadcasting progress over a hibernatable WebSocket.
- In-flight runs are resumable — the DO keeps a live snapshot, so you can navigate away and back.
- Completed runs are persisted (metadata in D1, full bodies in R2) and listed in the sidebar.
**Stack:**Cloudflare Workers · Durable Objects · D1 · R2 · AI Gateway · React 19 · Hono · Zustand ·
Tailwind v4 · @cloudflare/kumo · Vite.
- Node 20+ and npm
- A Cloudflare account (you'll
wrangler login— no API token to create) - An AI Gateway (Dashboard → AI → AI Gateway → create one; note its id)
- Unified Billing credits on the account — required for third-party (non-
@cf/) models. Without credits, only the Budget preset (@cf/*Workers AI models) will work.
# 1. Install + authenticate
npm install
npx wrangler login # if your token sees multiple accounts: export CLOUDFLARE_ACCOUNT_ID=<id>
# 2. Create the local D1 schema (Miniflare simulation)
npm run db:migrate:local
# 3. Run it
npm run devOpen http://localhost:5173. D1 / R2 run as local Miniflare simulations; the env.AI
binding (remote: true) connects to the real AI service via your wrangler login. There are no
secrets and nothing to fill in — wrangler.jsonc is committed and account-agnostic (the deploy
button or wrangler provisions the real D1 id).
One click clones the repo to your Git account and provisions everything — the Worker, the D1 database, the R2 bucket, and the Workers AI binding — into your Cloudflare account. The deploy script applies D1 migrations automatically. There are no secrets to set.
Two things to know:
- Unified Billing credits — third-party models (the Quality preset) need credits on your account. Without them, only the Budget preset (
@cf/*Workers AI models) works out of the box. - No built-in auth — the deployed app is unauthenticated. Put it behind Cloudflare Access (or add your own gate) before sharing the URL — every run spends your account's credits.
npx wrangler login # multi-account: export CLOUDFLARE_ACCOUNT_ID=<id>
npx wrangler d1 create synth-db # paste the id into wrangler.jsonc → d1_databases[0].database_id
npx wrangler r2 bucket create synth-artifacts
npm run deploy # builds, deploys, and applies D1 migrationsThe picker offers Quality (frontier third-party models), Budget (Workers AI) (@cf/* only,
no Unified Billing credits needed), and Custom (pick any panel/judge/synthesiser). Defaults live
in [src/worker/lib/models.ts](src/worker/lib/models.ts) (PRESETS); the panel catalog combines the
live Workers AI list with a curated set of third-party slugs.
| Command | Purpose |
|---|---|
npm run dev |
Vite dev server (SPA + Worker + local D1/R2 via Miniflare) |
npm run build |
Production build (client + worker) |
npm run deploy |
Build and deploy to Cloudflare |
npm run db:migrate:local |
Apply D1 migrations to the local dev DB |
npm run db:migrate:remote |
Apply D1 migrations to the deployed DB |
npm run cf-typegen |
Regenerate worker-configuration.d.ts after editing wrangler.jsonc |
node scripts/test-run.mjs |
End-to-end smoke test over the WebSocket protocol (dev server must be running) |
src/
worker/ Hono routes, the SynthesisRun Durable Object, AI Gateway client, prompts, persistence
client/ React SPA (Zustand store, components)
shared/ WebSocket protocol + domain types (imported by both worker and client)
migrations/ D1 schema
MIT — inspired by OpenRouter's Fusion; not affiliated with OpenRouter or Cloudflare.

