ModelRig Docs Leaderboard Console ↗ GitHub Sign up

Template: creative approval

(needs modelrig 0.12.0 or newer) Approve or reject generated images, video and audio the way a creative lead reviews a batch: on brief, safe for your brand, any text legible, no visible generation defects, and usable without another round. This page is one of the use-case templates — a starting point, not a finished grader. Unlike the text templates, the thing being judged is a generated asset: an artifact of type image/, video/ or audio/* saved in the step whose rig.recordCall({ ..., units }) made it. The machine-readable source is node_modules/modelrig/templates/creative-approval.json.

Does this task fit?

Creative approval fits the shipped loop when four conditions hold. (1) Each generation call is recorded with rig.recordCall({ ..., units }) — images, seconds or characters — so it is priced per unit from a sourced rate (or flagged unpriced, never guessed), and each asset it produced is saved as an artifact of type image/, video/ or audio/* in the same step. (2) Someone on your creative team can write down what on brief and on brand mean for your work, which is the grading guide below. (3) That person approves or rejects assets in the Grade queue's Media approval tab, so the approval rate per dollar on Costs is measured from real verdicts; it is withheld until a model has ten approvals. (4) You accept that generated media is stored UNSCREENED: ModelRig's PII/PHI scrub reads text only, so do not generate or store images of real people's documents or other regulated content through it. There is no automated image scoring in this template; the verdicts are human. It is a starting point, not a claim that any model produces usable creative — fill in your brief and brand rules before you rely on it.

Starter schema

Replace every TODO with your own taxonomy; the enum slots ship without values on purpose, so an unfilled template refuses to look finished.


{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$comment": "STARTER SCHEMA for the RECORD of one generated asset (the brief and what was produced), not for the media bytes themselves — the asset is saved as its own image/*, video/* or audio/* artifact. Replace every TODO with your own values before use. The template runs as-is: free-text fields validate immediately.",
  "title": "CreativeAsset",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "brief",
    "format",
    "asset_artifact_id"
  ],
  "properties": {
    "brief": {
      "type": "string",
      "description": "The creative brief or prompt the asset was generated from — what the reviewer checks on-brief against."
    },
    "format": {
      "type": "string",
      "description": "The placement the asset is for (a hero banner, a social square, a voice-over). TODO(enum): constrain this to YOUR own placement names by adding an \"enum\": [ ... ] here. It runs as free text immediately.",
      "$comment": "TODO(enum): add your placement names as the enum for this field."
    },
    "asset_artifact_id": {
      "type": "string",
      "description": "The id of the image/video/audio artifact this record describes (the handle rig.artifacts.save returned)."
    },
    "required_text": {
      "type": "string",
      "description": "Optional: any words that must appear in the asset exactly (a headline, a product name), so legibility can be checked against them."
    }
  }
}

Starter grading guide

The starter criteria run as written — sharpen each one in your team's own words as you grade. They are in the exact jsonb shape the set_task_settings write path validates — binary checks, each with a one-sentence pass and fail. There is no pass_threshold here: that lives in the route's grade: block.

on_brief — Matches the brief

brand_safe — Safe for your brand

legible_text — Any text is legible and correct

no_artifacts — No visible generation defects

usable_as_is — Usable without another round

The guide's escalation band starts at epsilon: 0.1: a grade within that distance of the route's pass threshold is treated as judge-uncertain and sent to a human. It is a starting band — tune it as your grader calibrates.

Golden checklist

Roughly twenty examples that cover:

Escalation starter

Start by sending to a second reviewer every asset destined for a paid or high-visibility placement, every asset with text in it, and every asset a reviewer approved with a comment. The machine-side band lives in starter_guide.escalation.epsilon: a grade within that distance of your task's pass threshold is treated as grader-uncertain and sent to the human queue. The 0.1 here is a starting band — widen it while you build trust, narrow it as your grader calibrates.

Using it

By hand: record each generation call with its units — rig.recordCall({ provider, model, usage: { tokensIn: 0, tokensOut: 0 }, units: { images: 4 }, latencyMs, stepKey: "hero" }) — and save each asset it produced with rig.artifacts.save(bytes, { name, type: "image/png", stepKey: "hero" }). Write the starter criteria into your team's own words, then approve or reject the assets in the console (Grade queue → Media approval). Costs shows the approval rate per $ by model once a model has ten approvals; below that the rates are withheld and the reason is shown. Generated media is stored unscreened — the PII/PHI scrub reads text only, and the console says so on every asset.

From a coding agent: set_task_settings (the task-settings scope) authors the grading guide as-is. There is no automated image scoring here: the verdicts are human. See the use-case templates overview for the full two-path walkthrough.