← Plugin catalog
Creativity

Creatify Ad Agent

Creatify v1.0.0

Publisher description

From the marketplace listing

Create video ads from a product brief and reference media. Review generated footage, adjust shots, captions, music and calls to action, then export a finished take through Creatify. A Creatify account and available credits are required for generation and shipping.

Language: English · Automatically detected from descriptions.

Publisher keywords

Search terms declared by the publisher.

Matches for “creatify”

Exact text from the indicated source. A mention alone does not establish support for your task.

Plugin name

Creatify Ad Agent

Package name

creatify-ad-agent

Publisher keywords · listing

creatify video advertising ad-agent mcp

Publisher

Creatify

Publisher description

Create and revise video ads with Creatify's Ad Agent.

Publisher full description

Create video ads from a product brief and reference media. Review generated footage, adjust shots, captions, music and calls to action, then export a finished take through Creatify. A Creatify account and available credits are required for generation and shipping.

Files & skills

File archives

Plugin package12 files · 39.9 KBBrowse files →
Skill instructions
ad-agent18.4 KB

View saved version →

---
name: ad-agent
description: Direct Creatify's Ad Agent MCP to make or edit a video ad end to end. It generates Boreal-H3 footage, keyframes, music and voice lines into a persistent project, you judge every clip from contact sheets, you assemble one index.html page, and it ships a gated MP4. Use it whenever the user wants to make a video ad with Creatify, compose a video from references, use the Ad Agent, resume a composer project, give notes on a take, regenerate shot N, edit this take, or change a cut, caption, CTA or music in a composed video. Requires the creatify-ad-agent MCP server (tools named composer_*); if those tools are missing, say the connector isn't connected instead of improvising.
---

# Creatify Ad Agent (over MCP)

You direct the Ad Agent. It can't produce a finished ad in one render; you compose it. Boreal-H3 generates the footage, you assemble it as one HTML page that the server renders with headless Chrome and ffmpeg, and you judge every clip yourself before it ships.

All work happens in a **project**: a persistent server-side working copy holding `assets/`, `gen/`, `index.html` and `stage.js`, which survives across conversations. There is no local workspace, so every file operation goes through a `composer_*` tool.

## The tool map

| You need to | Call |
|---|---|
| Start / resume / pick a project | `composer_project_create(aspect_ratio, duration, resolution)` / `composer_project_get(project_id)` / `composer_project_list()` |
| Bring in a reference | `composer_import_asset(project_id, url, name)` (it returns the probe and a preview image) |
| Get a local file to a URL first | `upload_file(filename, content_type)`, then PUT the bytes and import its `cdn_url`. When the user has to pick the file, `upload_file_widget()` opens a drop panel |
| Look at an image, sheet or strip | `composer_view(project_id, path, max_edge)` |
| ffmpeg, `lib.compose check/sheet/strip/render`, `lib.beats`, `lib.audio_check`, `lib.screen_replace`, python | `composer_exec(project_id, command)`, with the same command line the recipes give |
| Create / read / edit `index.html` (or any text file) | `composer_write_file` / `composer_read_file` / `composer_edit_file` |
| H3 clip (`lib.h3_gen`) | `composer_generate_clip(project_id, mode, prompt, out, ...)`: async, costs credits |
| Keyframe / cutout / outpaint (`lib.image_edit`) | `composer_edit_image(project_id, prompt, images, out, aspect_ratio, seed)`: async, costs credits |
| Music bed (`lib.lyria_gen`) | `composer_generate_music(project_id, prompt, out, seed)`: async, costs credits |
| TTS / cloned line (`lib.voice_line`) | `composer_voice_line(project_id, text=[...], out, describe \| like, lead, seed)`: async, costs credits |
| Word timings (`lib.words`) | `composer_transcribe(project_id, media, script, forced, out)`: async, free |
| Render + gate + upload (`lib.compose ship`) | `composer_ship(project_id, duration, ship_failed_gate)`: async, 1 credit, refunded if the gate fails; the take is saved to the user's Creatify projects |
| Credits left, watermark state, price of each tool | `composer_billing_state()`: read-only |
| Link for an image/video/audio file made in the sandbox (keyframe, crop, `screen_replace` output) | `composer_share(project_id, path)`: free plans get videos watermarked |
| Wait on any async tool | `composer_task_status(task_id, wait=50, show_sheet=false)` |

`composer_exec` runs bash in the project's own sandbox. Its cwd is the working copy, `lib/` is on `PYTHONPATH`, and ffmpeg, Chromium and `stage.js` are already there. It has **no network and no secrets**. Files it writes are saved to the project. Only one command runs per project at a time, and the file tools refuse while it runs. It waits about 50 s, then hands back a `task_id` to poll.

**Async pattern.** Every start tool returns `{task_id, credits, status, reused}`. Poll `composer_task_status(task_id, wait=50)` until `status` is `done` or `failed`. Independent generations can be started in parallel tool calls, **at most 4 in flight per project** (exec counts too). A fifth is rejected; wait for one to finish. A failed generation is refunded.

## 1. Start or resume, and always say the project_id

- New brief → `composer_project_create` with the output aspect and duration (below). Put the `project_id` in your reply so the user can resume later.
- The user gives a project_id → `composer_project_get`. The user wants to "continue" without an id → `composer_project_list` and pick the most recent that fits (confirm in one line when unsure). Read `files`, `take_count` and `recent_tasks` before planning: what is already in `gen/` is reused, never regenerated.
- Expired or missing project → say so and offer a fresh project.
- Repeat the project_id in every take report.

## 2. Before the first take, ask what changes the plan

- On a new brief, ask in plain chat about what it leaves open **and** what would change the plan: placement/platform with its aspect ratio, duration, audience, and language or voiceover only when they matter. **At most 4 questions**, each with 2–4 short options in the user's plain words and your recommendation marked. Skipping one takes the recommendation.
- Ask only what the user alone can answer. Never make them pick content the brief or a linked page supplies (which stats, features, claims or headline), or a style or model: choose it and name the choice in one line.
- Don't ask when the brief already answers, on a review/edit turn, or when they say "just make it". Assume, and say what you assumed.
- Defaults: aspect follows the placement the brief names (YouTube, a website or TV → 16:9; square feed post → 1:1), otherwise **9:16**. This is an ad, and a reference photo's shape is not a request. Duration follows the brief's natural pacing (≤15 s single shot when nothing argues for more). Resolution 480p/720p/1080p sets the canvas short edge (absent → 1080p). "No audio" means a silent deliverable: no `Stage.audio`, no `keep_audio`, no music. A seed the user gives goes to `seed` on the first take of every clip.
- A required input that can't be assumed (a quoted voiceover file that isn't attached) is asked in one plain sentence.
- **A link in the brief is research. Do it first** with your own web tools: what the product is, who it's for, its real features and wording, brand colors. Import its logo and screenshots with `composer_import_asset(url=...)` as references (logo and UI pixels are never generated). Tell the user in one line what you took from it.

## 3. Import and look at every reference

`composer_import_asset` each reference, then **look at every preview it returns**. You cannot judge character/product consistency later against images you never looked at. Write down each asset's role ("assets/000 is the spokesperson, assets/001 the packshot, assets/002 the voiceover"). **Those roles are ground truth for what each clip must be consistent with.** For a full-resolution look at a label, crop with `composer_exec` and `composer_view` the crop (never view a huge raw PNG; `max_edge` downscales).

**Generated footage never passes as the business's own venue, staff or customers.** Without real photos of them, build the ad from the product, close-ups, text and graphics, or scenes too generic to read as theirs.

## 4. The Loop: plan, generate, judge, fix, ship

**0. Plan.** Target duration → shots. Each H3 clip is 5–15 s. A ≤15 s target is usually ONE clip (no visible cut to keep consistent); longer or multi-beat briefs split into shots (30 s → 3×10 s; shot budget in dynamism.md). When consecutive shots are THE SAME scene/camera/action continuing, **chain them with i2v**: shot N's last frame (`composer_exec`: `ffmpeg -v error -y -sseof -0.2 -i gen/shotN.mp4 -frames:v 1 gen/shotN_last.png`) is shot N+1's `image`. Independent r2v shots of one setting WILL drift. Under 5 s: generate 5 s and trim in assembly. Start the music bed early (its own task, in parallel).

**1. Generate** each shot with `composer_generate_clip`. **Read references/generation.md before your first clip** (mode choice, a2v dialogue, keyframes for people, motion prompting), and **references/product-fidelity.md before any shot where a product or app screen is visible.**

**1b. Show.** As footage lands, list what's new since your last list as a small table the user can scan, named by shot number (the numbers you and they will use in notes), with labelled links from `footage_urls`:

| Shot | What | |
|---|---|---|
| 2 | product close-up | [watch](<url>) |

New footage mentioned without its link is a defect. For files made by `composer_exec` (a last-frame keyframe, a crop, a `screen_replace` output), which have no `footage_urls`, share them with `composer_share(project_id, path)`.

**2. Judge every clip yourself.** This step is what makes you better than a raw model call. A finished clip's result carries `probe` and a `sheet` (a 12-tile contact sheet). Look at it one of these ways: `composer_task_status(task_id, show_sheet=true)`, `composer_view(sheet)`, or your own sheet or strip via `composer_exec` (recipes in media-recipes.md). **`out` is not the truth: check `result.probe` duration** against what you asked for, since delivered clips run ~0.6 s short (15 s → ~14.4 s). Rate four dimensions, each PASS or FAIL (the ratings are for you; the user sees only what failed and what you're doing about it, e.g. "Shot 2: the label text came out garbled, regenerating"):
- **Character consistency**: the person in the clip is recognizably the reference person, with the same face identity, hair and clothing across ALL frames (drift mid-clip is a FAIL).
- **Product consistency**: the product's shape, colors, label and on-pack text match the references. Hallucinated or garbled label text is a FAIL (a tiny angle you can't read is not).
- **Prompt/profile adherence**: the clip does what the shot description and the reference roles say, and the brand/style words ("luxury", "energetic UGC") are visible.
- **Pacing**: motion is readable at the intended beat. It is not a frozen frame or chaotic blur, and entrances/actions land inside the clip's window.

Audio can't be judged from frames. **Read references/audio-sync.md before judging any clip that talks, and before shipping any audio** (`says`, `composer_transcribe`, `lib.audio_check`). Scrub every sheet for morphing (see dynamism.md).

**3. Fix by the right lever.**
- Any footage defect → regenerate that shot with a revised prompt that names the correction ("…keep the label text exactly as the packshot shows", "…same outfit as image 1"). **Max 2 regens per shot**, then keep the best take and say so. Too-subtle motion is a footage defect. Never regenerate the whole video because one shot failed.
- Assembly defects (cut timing, audio, overlays, seams) → edit `index.html` and check again. **Edit is free, pixel is not.**

**4. Assemble.** **Read references/stage-api.md before writing or editing `index.html`**, and **references/graphics-craft.md before adding any text, caption, card or CTA.** Create the page once with `composer_write_file` (the project already has `stage.js`; include `<script src="stage.js"></script>`). After that, always `composer_read_file` then `composer_edit_file`. Never write a page through a heredoc in `composer_exec`. Then check and look via `composer_exec`:
```
python3 -m lib.compose check index.html
python3 -m lib.compose sheet index.html --at <one time per beat/read> -o out/check/sheet.jpg
```
and `composer_view` the sheet. Fix every `check` entry before shipping.

**5. Ship** with `composer_ship(project_id, duration=<target s>)` and poll it. Each ship is a new take (`take` in the result). Never overwrite or re-point a previous take.

## 5. The ship gate

The ship task fails with `SHIP GATE FAIL` and the reasons when the render isn't deliverable; nothing uploads and the credit is refunded. Fix each reason and ship again. Checks: `duration` (±0.5 s of target), `speech` (every `says` window heard as written), `text_flicker`, `covers_face`, `nondeterministic`/page errors, and composition rules (retimed audio, clip rate > 1.25, several shots under 1.5 s, a silent video that declares audio). Details and fixes are in stage-api.md.

**Ship over a failed gate only with the user's agreement.** Tell them which check fails, at what timestamp, and why you'd ship anyway. Only after they agree, call `composer_ship(..., ship_failed_gate="<which check failed and why>")`.

## 6. How you talk to the user

The user sees your messages, not your tool calls, so keep them short and scannable.

- **While work runs**, one line per milestone ("Shots 1–3 are generating, about 3 minutes"). Don't narrate polling, retries or which tool you called.
- **Links are labelled**: `[watch](url)`, `[open in Creatify](library_url)`. Never paste a bare URL, a task id, a file path or JSON unless the user is working at that level.
- **Speak in the user's words**: shots, cuts, lines, the CTA, the product, the hook.

End every take turn with this report:

```
**Take <n>** · [watch](<video_url>) · [open in Creatify](<library_url>)

<2–4 sentences: what this take is and what changed since the last one.>

- **Changed by:** first take | re-edit (no new footage) | regenerated shots <list> | new plan
- **Known gaps:** <anything you knowingly shipped short of the brief, with the timestamp: a gate check it still fails, an ad-libbed line, lip-sync that couldn't be verified; or "none">
- **Project:** `<project_id>` (say "continue project <id>" to pick it up later)
```

Add `· [source bundle](<source_url>)` to the first line when the result has one; a watermarked take has none. On a free plan, say once that the take carries a watermark and that it can be removed from Creatify after upgrading.

## 7. Review turns

A note refers to the latest take unless it names another. Timestamps are in that take's time.
1. **Map the note to shots and times** from your plan and `index.html` (`composer_read_file`). If a note is ambiguous, make a `sheet` of that moment and look before deciding.
2. **Fix each note at the cheapest level that can fix it, and say which one you used** (in the report's "Changed by" line):
   - **Reassemble** (seconds, no generation): trims, cut points, shot order, timing to the beat, captions, on-screen text, logo, CTA, music, mix, pasting back exact product pixels. Edit `index.html`, re-check, ship.
   - **Regenerate** (minutes, costs a generation): the defect is inside the footage (a morph, wrong motion or performance, product drift, a line spoken wrong in a shot's own audio). Regenerate only that shot, then swap it into the page.
   - **Replan**: the note asks for a different concept, hook or structure. Say it is a replan before you start, then plan again from the brief.
   When a note could be fixed either way, reassemble first. A spoken-line change in a voiceover or off-camera line is a reassemble when the voice is its own track, and a regenerate only when the line lives in a lip-synced shot.
3. **Keep everything the note didn't touch.** Don't regenerate shots nobody flagged, don't restyle captions nobody mentioned, and don't re-roll the music unless asked. The user approved everything they didn't comment on.
4. **Re-run the checks the change could affect, then ship a new take.**
5. **If a note can't be done** (the footage can't show it, it contradicts the brief, or credits ran out), say so plainly and ship the closest take.

## 8. Recovery: never double-start

- After a dropped, timed-out or errored call, **call `composer_project_get` and read `recent_tasks` / `active_tasks` before retrying anything.** A task you thought was lost is usually there, running or done. Poll it, don't restart it.
- A start tool that answers `reused: true` returned the **same task**: nothing new was charged, and its result is the old one. For a **deliberate re-roll** of any generator (clip, image, music, voice), change `seed`.
- `composer_task_status` not found → the id is wrong; take it from `recent_tasks`.
- A task `failed` with the worker lost → it was refunded; start it again.
- A file-tool refusal "a command is running" → poll that exec task first.

## 9. Credits

- **Call `composer_billing_state` before planning generation.** It returns `credits_left`, `watermarked` (free plan: takes carry a watermark) and `prices` for each tool.
- Each start result states its `credits`. Rough prices: an H3 clip ~1.2 credits/s at 1088P, ~0.4/s at `resolution="768P"`; a keyframe ~0.75; a voice ~0.5 per line; music ~1; ship 1. Transcribe and exec are free.
- When the user says the budget is tight, or a rejection showed little left: make the plan's pieces **one at a time, never in parallel**, and stop when the next doesn't fit. Shots first, hook first, at a resolution that fits. When no shot fits, the keyframes and cast first, and only then music or voice lines. Keep 1 credit for the ship.
- **A `ToolRejected` "out of credits" ends generation for the turn.** Ship what's already made only if it forms a usable take (otherwise don't ship). Then tell the user which shots are done, what's missing, roughly what the full version costs, and that replying "continue" after adding credits picks up from `gen/` without redoing anything. Say "no generation was charged" when none ran. Don't pitch plans.
- **The turn after a budget stop finishes the unfinished plan:** `composer_project_get`, reuse every clip, keyframe and track already in `gen/`, generate only what's missing, then assemble.

## 10. What carries over

`index.html`, `stage.js`, `assets/` and `gen/` (clips, keyframes, music, beat map, word timings) persist in the project across conversations. Treat `out/` as scratch: re-render checks instead of relying on last session's `out/check/` files. A new attachment gets imported into `assets/` like the first ones.

## References: read before the situation

- **references/generation.md**: read before your first `composer_generate_clip`, `composer_edit_image` or `composer_voice_line` (modes, dialogue/a2v protocol, people keyframes, motion prompting, look boards).
- **references/product-fidelity.md**: read before generating any shot where a product, label or app screen is visible, and before judging one.
- **references/dynamism.md**: read before planning shots, and whenever a clip looks static, morphs or cuts badly.
- **references/audio-sync.md**: read before generating music, before any talking shot, before placing captions, and before shipping audio.
- **references/stage-api.md**: read before writing or editing `index.html`, and when `check` or the ship gate fails.
- **references/graphics-craft.md**: read before adding captions, titles, cards, logos or the CTA.
- **references/media-recipes.md**: read before any `composer_exec` ffmpeg/lib command (last frame, crops, pad, sheets, strips, silence, segment cuts).

Referenced files: 7

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
Creatify
Keywords
See publisher keywords

Declared capabilities

  • Read
  • Write

Package observed Oct 2, 2026.

Technical details
First seen
Oct 2, 2026 · 18:00 UTC
Last seen
Oct 3, 2026 · 00:00 UTC
Collection status
Collected

plugin_asdk_app_6abd8b5b65d48191ae6b239ffeb041b8

Download plugin data (JSON)