Retail Therapy Unplugged is the coaching business I co-founded with my family, built around a course that helps people change their relationship with shopping. The course and its short-form videos rely on a recurring cast of illustrated characters — people a viewer can recognize from one lesson to the next. That only works if a character looks like the same person in every image: from the front and in profile, happy and anxious, at home and at work.
The problem
Through late 2024 and early 2025, I made those characters by hand in Midjourney and a few other image tools, saving the results into a folder per character. It worked, but slowly. When I sat down to design something better, I wrote the pain points down first:
- Inconsistent appearance — the same character drifting between images.
- Inefficient prompt engineering — too many iterations to get one usable image.
- Poor tracking — no record of which prompt produced which image, or how images related to each other.
- Hard-to-apply feedback — "the smile looks forced" had to be turned back into a new prompt by hand, every time.
The design
Before building anything, I wrote a full requirements document for the workflow (it reached version 2.1 in June 2025). It defines 23 workflow nodes of four types — human-in-the-loop checkpoints, AI agents, integrations, and control-flow logic — and 20 structured documents that pass between them. Every agent reads a defined JSON input and writes a defined JSON output, so each step can be tested, versioned, and swapped out on its own.
The key design decision is the reference portrait. Nothing fans out until a human has approved one portrait of the character. After that, every prompt in every branch cites that portrait and reuses the character's seed, so the emotion, angle, and clothing images all start from the same face instead of from a fresh interpretation of the text.
One agent per job
Rather than asking one model to do everything, each AI step has a single responsibility and a persona written for it — a creative lens that tells the model what kind of expert it is and what it cares about:
Expands a short description into a full character profile and fixes the technical parameters — seed, camera, lighting — every later image inherits.
Writes the one prompt that establishes the character's baseline look for everything downstream.
Changes the expression — happy, anxious, sad, relieved — while holding every other facial feature steady.
Front, three-quarter, profile, and back views, for the face and for the full figure, on separate paths.
Picks wardrobe that fits the character's profile and context — formal, home, work, outdoors — without changing who they are.
Turns a reviewer's structured feedback on a rejected image into a new, versioned prompt.
The prompt engineering
Each agent has its own instruction file, roughly 1,000 to 2,500 words long. Every file covers the same ground: the persona, where the agent sits in the workflow, the exact JSON it receives and must return, and the rules it can't break — always cite the reference portrait, keep the seed fixed, and increment the version number when a prompt changes.
The refinement agent shows the idea best. Here's the worked example from its instructions: a "happy" portrait rejected for two reasons, and the prompt it's expected to produce in response.
consistency (medium): "Hair appears too dark compared to reference portrait"
expression (high): "Smile appears forced rather than genuine"
// Before (prompt v1)
... black hair with slight greying, ... happy expression with genuine smile, ...
--ar 1:1 --q 2 --style raw --seed 42 --cref <reference portrait>
// After (prompt v2)
... black hair with noticeable greying at temples::1.2, ... relaxed genuine smile::1.3,
subtle crow's feet around eyes, warm expression, ...
--ar 1:1 --q 2 --style raw --seed 42 --cref <reference portrait>
Each piece of feedback maps to a specific change — more grey at the temples, a weighted "relaxed genuine smile" plus the crow's feet that make a smile read as real — while the seed and the reference portrait stay untouched. The output also records which feedback it addressed and links back to the prompt version it replaced, so nothing gets lost between rounds.
Building it
I built the workflows in n8n, using its LangChain agent nodes with structured-output parsers so each agent's JSON is validated before the next step runs. Image generation goes through the PiAPI Midjourney API, with polling for finished jobs; approved images and their metadata go to Supabase and Cloudinary. I also started a small Next.js and Supabase review app whose chat route hands messages to the n8n webhooks.
The workflows went through several versions, and I tried different models along the way — OpenAI's GPT-4 and o3-mini, and Anthropic's Claude 3.5 Sonnet and Claude Sonnet 4 — to see which followed the JSON contracts and consistency rules most reliably.
| Hand-made (late 2024) | Pipeline design (2025) | |
|---|---|---|
| Consistency | Depended on each hand-written prompt | Approved reference portrait + fixed seed in every prompt |
| Prompt writing | One prompt at a time, by hand | A specialized agent per image category |
| Feedback | Rewrite the prompt manually | Structured feedback → refinement agent → new version |
| Tracking | Image files in per-character folders | Metadata in Supabase, linked to the prompt version that made each image |
Key takeaways
Anchor everything to one approved artifact. A single human-approved reference portrait did more for consistency than any amount of descriptive text.
Give each agent one job and a contract. Narrow roles with defined JSON in and out made every step testable on its own.
Make feedback structured, and version everything. Typed, rated feedback is something an agent can act on; version numbers make every change traceable.
Keep humans at the decisions that matter. Automation handled the repetitive prompting; people still decided what was good enough.
Want an AI workflow with guardrails built in?
Agent pipelines, n8n automation, and prompt design with clear contracts and human checkpoints from day one.