Generators
A Generator is a saved recipe: a form and a fixed pipeline of steps that turn your answers into a
finished deliverable, every time, without re-planning from scratch.
{ id, ownerId, name, slug, description, icon, inputsSchema: Json, // JSON Schema for the input form steps: GeneratorStep[], outputKinds: OutputKind[], // 'text'|'markdown'|'docx'|'pdf'|'image'|'code'|'react-app'|'fullstack-app'|'html'|'scene3d'|'data'|'zip' priceCredits: number, isPublic: boolean, runs: number, createdAt,}GeneratorStep = { id, title, role, // e.g. role: 'researcher' skills: string[], // built-in skill names this step is allowed to use instruction: string, // templated: {{inputs.x}}, {{steps.id.output}} tier: 'cheap' | 'standard' | 'strong', dependsOn: string[], outputKind: OutputKind,}GET /api/studio/generators → Generator[] (public ones + your own)POST /api/studio/generators → GeneratorGET /api/studio/generators/:idOrSlug → GeneratorPUT /api/studio/generators/:id → Generator (owner or the world owner only)DELETE /api/studio/generators/:idThe input form
inputsSchema is plain JSON Schema, built with a small authoring kit
(apps/api/src/studio/generators/define.ts): str/text (single-line vs. multiline), num,
bool, pick (enum), each carrying a human title, help text, placeholder, and validation
(minLength, min/max, etc.). The Studio’s generator form (schemaForm.tsx) renders this schema
directly — a new field type in the schema is a new field in the UI with no extra frontend code. A
few non-standard hints steer the form without breaking any other JSON Schema consumer:
x-multiline (textarea), x-placeholder, x-advanced (folded under “Advanced”), x-showWhen
(conditional on another boolean field — e.g. the email campaign’s “test recipient” field only
appears once “send a test” is checked).
Templating
Two placeholder forms are interpreted when a step’s instruction/title is rendered
(renderTemplate() in packages/agents/src/graph.ts):
{{inputs.<field>}}— the value you typed into that form field.{{steps.<id>.output}}— the text output of an earlier step in the same run; using this implicitly makes the current step depend on that one.
Running one
POST /api/studio/projects { generatorId: "gen_blog", inputs: { topic: "...", tone: "Direct and opinionated", wordCount: 900 } }Because a generator’s steps are already a complete, valid task graph, plan() skips the model call
entirely for this path — it renders the templates and hands the result straight to the same repair
pass (research-task guarantee, cycle check) that a free-text brief goes through. This is why
generator runs are cheaper and more predictable than free-text briefs: the only model calls are the
steps themselves, never a planning call.
Validation, structurally enforced
Every generator — seeded or user-created — is checked against real constraints before it can run
(validateSeedGenerators() in apps/api/src/studio/generators/index.ts, asserted at API boot for
the seed catalogue): unique ids/slugs, every referenced skill exists in BUILTIN_SKILLS, every
dependsOn points at an earlier step, every {{steps.x.output}} reference is backed by an actual
dependency, every declared outputKind is produced by at least one step, and — enforced
structurally, not just by convention — no step may use the strong tier. strong is reserved
for the planner and the QA reviewer only; a generator step that tried to request it would fail
validation before ever reaching a user.
Saving your own
POST /api/studio/generators takes the same shape (minus id/ownerId/runs/createdAt); a
slug is derived from the name if you don’t supply one.
You do not have to write that JSON by hand. GeneratorBuilder.tsx in the Studio is a real visual
builder: pick an icon, name and description; design the input form field by field (text, long
text, number, yes/no, a choice, a list — with labels, descriptions, defaults and required flags);
then build the pipeline as a stack of reorderable steps, each with a role, a model tier, an output
kind, the skills it may call, what it depends on, and its instruction template. An earlier version
of this page described it as a raw JSON editor; that is no longer true.
Once saved (and made public), your generator appears in the Studio’s generator gallery alongside the eleven seeded ones and can be listed on the Marketplace.
A run can also author one for you — studio.author_generator, driven by the
Agent crew & pipeline generator — which is the same thing arrived at from
the other direction: describe the work, get back a crew and a pipeline that names it.
The eleven seeded generators
Every fresh install ships with ten generators, upserted idempotently at boot
(seedGenerators()) — see the Generators catalogue for one page per generator with
its exact fields and pipeline.