Case study · Generative AI production

A content production line with a human gate in the middle

Weekly production across three brands went from 40 hours to 8, and output tripled. The reason it kept working is the approval gate: a model drafts, a person approves, and only approved work can reach a live channel.

Generative AIPythonPublishing APIAsset tagging
40→8hweekly production time
output at the same headcount
3brands running on one pipeline
0posts publish without a person approving

Problem

Volume was the goal, and volume is how these systems fail.

Generating a lot of marketing copy is easy now. Generating a lot of copy that a subject expert would put their name on is not, and the gap between the two is where most AI content projects die. They ship fast for six weeks, someone notices the quality, and the whole thing gets switched off.

So the interesting design question was never how to generate more. It was where to put the human, and how to stop anything getting past them.

The line

Content production pipeline from brief to published post, with an approval gate before publishing Brieftopic, angle, pillar Draftmodel writes copy Assetimage to template Review gateHUMANapprove or send back Publishscheduled by API changes requested, with written feedback
Only the gold path reaches a live channel. Nothing publishes on a model's say-so.
  1. BriefEach piece starts from a planned topic with a pillar and a format already assigned, not from a blank prompt.
  2. DraftThe model writes to a house style with hard rules: no em dashes, first person plural, end on a real question rather than a call to action.
  3. AssetThe image is built from a fixed template at a fixed size, with copy lifted from the post so the two cannot drift apart.
  4. ReviewThe draft lands in a queue as "needs review". A person marks it approved, or requests changes and writes why.
  5. PublishA scheduled job picks up only approved items and posts them through the platform API, then records the returned ID.

The gate

The publish job reads a flag it cannot set.

The approval flag is a field only a person can change. The publishing job runs daily, picks up everything marked approved, schedules it, and flips it to scheduled. If nothing is approved, it does nothing and exits.

Two details make this hold up:

  • It publishes the live text, not the text it was drafted with. An earlier version scheduled from the copy held in the script, which meant an edit made during review was silently thrown away. Now the job re-reads the approved record at publish time.
  • It is safe to run twice. Anything already published carries an ID and gets skipped. A cron that can double-post is worse than no cron.

The generation step deliberately stays manual. It needs a logged-in session and produces work that needs judgement. Publishing is mechanical, so publishing is what runs on a schedule.

Keeping it organised

Tagging is what makes reuse possible.

Every piece carries its format, its pillar, its planned date, its approval state, and its published ID. That is what turns a pile of assets into something you can query. It answers the questions that actually come up: how many days of scheduled posts are left, which pillar has gone quiet, which format performs, what can be reused.

A runway check runs against the same records and warns when the queue drops under about two weeks. Nobody has to notice.

Any team can generate three times the content. Keeping it good enough to publish for a year is the harder problem, and that comes from making approval a required step in the code rather than a habit people are supposed to keep.

Post copy, brand names, channel identifiers, and account credentials are withheld. The pipeline, the gate, and the tagging scheme are the transferable parts.