Carousel Workflows
The carousel workflow generates an ordered deck of slides for a single-topic carousel post. The LLM drafts a per-slide outline (slide 1 = hook, last slide = CTA, middles = distinct points), then one image is generated per slide using a prompt derived from that slide’s outline entry. The output preserves slide order so consumer UIs can render the deck as a swipeable group rather than a grid of unordered thumbnails.
carousel/generate
Section titled “carousel/generate”Workflow: carousel/generate · Aliases: carousel, image/carousel
Produces a single carousel post — outline + N rendered slides in narrative order, plus a post-body caption.
Submit either the canonical name or the image/carousel alias (Socialite uses the latter from its bundle dispatcher so it can swap from image/generate without changing the input shape).
Quick Start
Section titled “Quick Start”fab run carousel/generate \ --input topic="AI productivity tips" \ --input slide_count=5 \ --input audience="busy founders" \ --input tone="punchy"curl -X POST "$FABRIC_URL/v1/workflows/run?name=carousel/generate" \ -H "Authorization: Bearer $FABRIC_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "input": { "topic": "AI productivity tips", "slide_count": 5, "audience": "busy founders", "tone": "punchy", "channels": ["instagram"], "aspect_ratio": "1:1" } }'import { FabricClient } from "@fabric-platform/sdk";
const fabric = new FabricClient({ apiKey: process.env.FABRIC_API_KEY });
const run = await fabric.workflows.runs.submit("carousel/generate", { input: { topic: "AI productivity tips", slide_count: 5, audience: "busy founders", channels: ["instagram"], },});Pipeline
Section titled “Pipeline”draft_outline (LLM) → derive_aesthetic (LLM) → render_slides (image-per-slide, parallel) → write_caption (LLM)- draft_outline asks the LLM for a
[{title, body}, ...]plan withslide_countentries. Slide 1 is the hook; the last slide is the CTA. Titles are short (≤ 6 words) and ALL CAPS-ready. - derive_aesthetic drafts a single concrete aesthetic brief (palette, lighting, composition, medium) for the whole deck so every slide reads as part of the same set. Skipped when the caller passed an explicit
visual_style. - render_slides generates one image per outline entry in parallel. Each prompt combines the slide title (on-image hero text), the deck-wide aesthetic, and tone-driven visual directives (e.g. “punchy” → saturated complementary colors, hard rim lighting, dynamic composition).
- write_caption drafts the post-body caption (2–4 sentences, soft CTA) referencing the realized slide titles, so the caption matches what the deck actually says.
| Parameter | Type | Default | Description |
|---|---|---|---|
topic | string | required | Subject of the carousel — drives outline + image prompts. |
slide_count | int | 5 | Number of slides (3–10). |
num_thumbnails | int | null | null | Legacy alias for slide_count (accepted so callers swapping from image/generate don’t have to rename the field). |
audience | string | "general" | Target reader persona. |
tone | string | "" | Voice/tone hint (e.g. "punchy", "warm", "luxurious"). Drives both narrative voice and the image model’s visual direction (palette, lighting, energy). |
industry | string | "" | Industry/vertical hint passed through to outline + caption prompts. |
keywords | list[str] | [] | Topical keywords woven into the deck’s narrative. |
channels | list[str] | [] | Distribution channels; shapes prompt guidance. |
visual_style | string | "" | Optional override. When empty, the workflow derives a deck-wide aesthetic brief from topic + tone + audience (recommended). |
aspect_ratio | string | "1:1" | Aspect ratio for slide images. Imagen accepts 1:1, 9:16, 16:9, 4:3, 3:4. Avoid 4:5 — Imagen rejects it and the run silently falls through to a lower-quality provider. |
Output
Section titled “Output”{ "kind": "carousel", "topic": "AI productivity tips", "caption": "AI won't take your job — but the founder using it will. Swipe through 5 ways to claw back two hours a day, starting with the meeting you can already kill.", "slides": [ { "order": 0, "title": "AI WON'T REPLACE YOU", "body": "But someone using it will.", "image_path": "/tmp/carousel_slide_00.png", "image_asset_id": "018f..." }, { "order": 1, "title": "TIP 1 — DELETE BUSYWORK", "body": "Automate the meetings nobody asked for.", "image_path": "/tmp/carousel_slide_01.png", "image_asset_id": "018f..." } ]}| Field | Type | Description |
|---|---|---|
kind | string | Always "carousel" — consumers route on this. |
topic | string | Echoed input topic. |
caption | string | Post-body caption summarizing the deck — what the consumer renders as the Instagram post copy under the swipeable images. |
slides | list[CarouselSlide] | Ordered slide list. slides[i].order matches the index. |
slides[].order | int | Zero-based slide position. Stable across the run. |
slides[].title | string | On-image hero text. |
slides[].body | string | Optional supporting copy (may be empty for visual-only slides). |
slides[].image_path | string | Local or signed-URL path to the rendered slide. |
slides[].image_asset_id | string | null | Fabric asset ID when uploaded server-side. |
Failure semantics
Section titled “Failure semantics”If a single slide’s image generation fails, the slide is dropped from the output but the run still succeeds. If every slide fails, the run fails with a clear error. Consumers should iterate slides (which may have gaps in order) rather than assuming a contiguous index.
Use with the bundle dispatcher
Section titled “Use with the bundle dispatcher”Pair carousel/generate with bundle/ad-hoc to produce a multi-format deck — carousel + video + text post — for the same brief in one submission:
{ "bundle": [ { "workflow": "carousel/generate", "input": { "topic": "...", "slide_count": 5 } }, { "workflow": "video/ai-shorts", "input": { "topic": "..." } }, { "workflow": "global/content-generate", "input": { "topic": "...", "content_types": ["text"] } } ]}