Inspiration
Independent print-on-demand sellers lose weeks and ad money on designs nobody buys. They can't afford a researcher, a designer and a media buyer, so they guess: which idea will sell, who would buy it, what competitors charge, and whether the phrase on the shirt is someone's trademark. Then they write the listing and the ads by hand. We wanted one agent that does the research and the drafting, shows its evidence, and still lets the seller approve every product and every dollar of ad spend.
What it does
You pick an idea wovain found, or type a brief. wovain then:
- Asks Qloo's taste graph who would buy it and what else those people love.
- Calls Tavily live, at runtime, for each theme: Search for news (why now) and marketplace crowding, Extract for competitor prices, a Research dossier, and a trademark search for every printed phrase.
- Ranks ideas by evidence. Nemotron names each idea only from what the tools returned.
- Has Nemotron 3.5 Super VL write the design brief from your chosen tone, colours and the research; fal draws the art.
- Has Super VL look at the drawn PNG (garment as subject, background, cropping, wrong words, art that vanishes on the shirt colour), and Nemotron 3 Ultra gives the verdict, score and fixes. A rejected design is redrawn from the judge's fixes.
- Lists the approved design on Fourthwall with a computed price, writes ad copy, and builds the Meta campaign aimed at Qloo's demographics.
Media buying is built: approving launches the campaign behind spend rules. It was not run against a live Meta account in the demo, because the judge account has no Meta connection. The code:
- Builds the campaign, ad sets, creatives and ads through Meta's Ads MCP, aimed at a Qloo audience.
- Sets up the shop's pixel and sends a Conversions API test event.
- Every 30 minutes applies spend rules: stops at the daily cap, the monthly cap or a $50 loss limit, kills ads that spend their target cost per sale without a sale, and raises a winning campaign's budget by at most 20%.
- Mirrors the kill and stop rules into Meta's Automated Rules, so Meta pauses spend even if wovain is down, and refuses to launch until those rules are in place.
How we built it
- Next.js 16 web app and a ChatGPT MCP app on one backend (oRPC, Better Auth), on Google Cloud Run and Cloud SQL, managed with Pulumi.
- Mastra agents on Nemotron through Nebius Token Factory's OpenAI-compatible endpoint, with one key and one base URL. Each agent asks for a job (default, reasoning, vision, fast, safety), and an env var per job names the model:
- Nemotron 3.5 Super VL (
nvidia/Nemotron-3.5-Super-VL): design briefs, idea naming, listings, ad copy, research summaries, and the vision check on the drawn art. - Nemotron 3 Ultra (
nvidia/Nemotron-3-Ultra-550b-a55b): the design judge's verdict, autopilot's decisions and the ads optimizer review. - Nemotron 3.5 Lightning (
nvidia/Nemotron-3_5-Lightning): brief term extraction, ad judges, Mastra scorers, prompt-injection and PII guardrails, moderation, and the docs chat.
- Nemotron 3.5 Super VL (
- Every reply is validated JSON (
response_format: json_schema). A grounding guard rejects ad copy that states a number or claim the tools didn't return. - Runs are durable Mastra workflows on Inngest. Each model call is a PostHog
$ai_generationevent, and the "Which model did what" page shows step, model and time. - Tavily is the runtime evidence layer: Search, Extract and Research on every run, plus trademark checks.
Challenges we ran into
- Lightning reasons by default. On a short extraction step it spent thousands of reasoning tokens per call and often hit our 90-second timeout. We turned reasoning off for the fast job: the step went from a median of 68 s (24 of 59 calls timing out) to 0.9 s on staging and 1.1 s on nebius.wovain.com.
- Nebius removes
nemotron-3-super-120b-a12bandNVIDIA-Nemotron-3-Nano-30B-A3Bon 2026-11-09, and we used both. We moved every model ID into per-environment config and switched to Super VL and Lightning. - Token Factory has no Nemotron content-safety model, so moderation runs on Lightning through Mastra's moderation processor.
- Web text from Tavily is untrusted, so it passes the injection and PII guardrails before any writer agent reads it.
Accomplishments that we're proud of
- The judge looks at the actual art instead of trusting the prompt.
- Routing by job is one config change per environment, with the same code everywhere.
- Every number in an ad traces back to a tool result.
- A measured 75x latency win on one step from a single setting.
What we learned
Giving each job its own model is mostly a cost and latency decision, and the reasoning setting matters as much as the model choice. A small model that reasons by default can be slower than a large one that doesn't.
What's next
Running the judge evals on Ultra and Lightning, a mobile app for approvals, and opening Meta to more merchants after App Review.
Built With
- nvidia-nemotron
- qloo
- tavily
- typescript
Log in or sign up for Devpost to join the conversation.