Documentation Index
Fetch the complete documentation index at: https://docs.moda.app/llms.txt
Use this file to discover all available pages before exploring further.
Bulk variants
Problem: The user wants several versions of a design — personalized per persona, per customer, per channel, per brand. Bulk is the workflow that breaks the most “make one design” assumptions in the rest of this skill, so read this in full before fanning out. There are three valid shapes. Pick based on what the user already has and what they want:| User situation | Pattern |
|---|---|
| ”Make 10 LinkedIn ads, one per persona” — N independent designs from scratch | A — fan out start_design_task |
| ”Make 10 versions of this canvas” / “rebrand this template for each of our 5 clients” — N variants of a source canvas, with or without per-variant brand swap | B — fan out start_design_task with template_canvas_id (preserves structure; server auto-picks content-only remix vs full rebrand) |
| “5-panel IG carousel” — one post with multiple linked panels | C — single start_design_task with format_category="carousel" |
../references/gotchas.md#format-and-dimensions. The rest of this recipe is about A and B.
The single biggest gotcha — concurrency caps
start_design_task and remix_design share a per-team in-flight cap:
| Plan | Max concurrent tasks |
|---|---|
free / free_beta | 3 |
paid | 10 |
ultra / enterprise | 15 |
AgentJobRateLimitError partway through — surfacing as a tool error from start_design_task. The skill’s job is to never let the user see that error. Use a windowed launch: keep at most cap tasks in flight, slot in the next prompt every time one terminates.
Get the cap from whoami — its concurrency_cap field is the exact number for the user’s plan. If you haven’t called whoami yet, default to 3 (safe everywhere) and bump up after the first batch confirms headroom.
Pattern A — fan out start_design_task (N independent designs)
Best when each variant has fundamentally different content: per-persona ad copy, per-customer pitch decks, per-region landing pages. There is no source canvas to preserve structure from.
User: “Create 10 LinkedIn ads for our automation tool — each tailored to a different ICP persona: CFOs, CTOs, heads of ops, …”
Agent (after the gate, before fanning out):
Kicking off 10 LinkedIn ads, one per persona. I’ll run them in batches of 3 (concurrency cap) and post each canvas URL as soon as it’s ready — you can open them while the others are still rendering.
list_tasks(status="running", ...)is one RPC for the whole pool. Beatsget_task_status× N per tick.- Post each canvas URL when the task is queued, not when it finishes. The user can open it immediately — they’ll see the agent’s progress in the canvas itself.
- Deliver each result as it terminates. Bulk feels much faster when 1/10 done shows up in 90s than when all 10 land together at 8 min.
post_done(persona, s)surfacess["error"]if the task failed. Don’t let one bad persona block the rest.
What goes in the prompt vs the parameters
- Per-persona detail belongs in the prompt — rewrite the pain point, metric, and CTA for each. Don’t just template
{persona}into a generic sentence. - Dimensions and
format_categorystay constant across the batch. They’re parameters. - One brand kit for all unless the user says otherwise. Omit
brand_kit_idso each task picks up the team default. Don’t fetch the kit per task — fetch once before the loop.
Pattern B — fan out start_design_task with template_canvas_id (N variants of a source canvas)
Best when the user has an existing canvas they’re happy with and wants variations of that design — same structure, different copy, different brand. The server copies the source, applies the resolved brand kit on the copy, then runs the agent against the copy. The original is never touched.
Skill selection is automatic from brand-kit comparison:
- Same brand kit as the source → content-only remix (preserve design, swap content)
- Different
brand_kit_id→ full rebrand (rework colors, fonts, copy, imagery) skip_brand_kit=True→ no forced skill; the curator decides
template_canvas_id over start_design_task(canvas_id=source_id, ...):
canvas_idedits the original. Five resellers, one canvas — the last one wins. The user loses their template.template_canvas_idduplicates first. Original stays clean; you get N independent copies.- Layout / structure carry forward automatically. You only specify what changes in the prompt.
- Per-variant brand swap is first-class. Pass a different
brand_kit_idper call to produce the same design rebranded for each client.
template_canvas_id is mutually exclusive with both canvas_id and conversation_id — passing either combination raises a tool error. See ../references/gotchas.md#conversations-vs-canvases-vs-remixes for the full matrix.
When to use remix_design instead
remix_design(canvas_id=…) without a prompt is a synchronous plain duplicate — useful when the user just wants a copy they’ll edit themselves. With a prompt, it’s an older async path that pre-dates template_canvas_id; prefer template_canvas_id for new bulk flows (cleaner brand-kit handling, automatic skill selection, no wait default asymmetry).
Recovery: a task in the batch fails
get_task_status returns {status: "failed", error: "…"} for that task. Common cases:
- Rate limit (
AgentJobRateLimitErrortext inerror) — your window is too wide. Drop it by one, retry that persona/reseller. - Billing (out of credits) — stop the whole batch. Tell the user; the remaining queued items would all fail the same way.
- Validation — bad prompt or parameters for that one task. Skip it, continue with the rest.
- Upstream model error — retry that one task once. If it fails again, skip.
failed unless you specifically know the error is transient. Surface the persona/reseller that failed so the user can decide.
Aborting a bulk run mid-flight
If the user changes their mind (“never mind, kill them”) or you spot a systemic issue (every task failing the same way), callcancel_task(task_id) on each in-flight handle. Already-terminal tasks are no-ops.
See also
../references/gotchas.md—waitasymmetry, concurrency caps, format defaults, carousel cap,not_readyretry, and the rest of the silent-fail set../references/tools.md— full signatures forstart_design_task,remix_design,list_tasks,cancel_task