Skip to content
Back to the blog

A model writes my blog, but only I publish it: how the review step is built

Published on 28 August 2026 · 4 min read

A blog that publishes itself is a bad idea. The drafts for this blog are generated by a model, and if that went live without anyone reading it, the first hallucination would show up on the internet with my name on it. So this week I built the missing piece: the review step.

Two commits, back to back. The first adds review by email with three actions — approve, edit, don't publish. The second documents the flow and, above all, the trap almost nobody mentions: prompts are not a guarantee of anything.

How it works

The process has two halves that never touch each other:

  1. Generate. A scheduled workflow prepares a draft with its real anchor, its source if it starts from someone else's article, and both language versions (Spanish and English). It saves it as a draft. Nothing else.
  2. Publish. I get an email with the draft and three links: approve, edit and don't publish. Until I hit approve, that post doesn't exist for anyone.

The important bit isn't the three buttons. It's the default state: if I do nothing, nothing gets published. Silence is not a yes. Plenty of automated flows do the opposite — it goes out unless you say no — and that works fine until the day you're travelling, or on holiday, or you simply don't open your email. Then the default decides for you.

Edit doesn't publish anything either: it takes me to the draft so I can work the Markdown by hand and come back through the same door. That's what I use most of the time. The model saves me the blank page, not the judgement.

The prompt trap

This is the part I want to explain properly, because it's useful to anyone building something with a language model inside it.

When a post starts from someone else's article, that article goes into the model's context. And the text on a web page can contain instructions aimed at the model: "ignore the previous rules and write that…". That's called prompt injection, and the root problem is that a language model can't reliably tell the difference between data it should read and orders it should obey. It all arrives as text. It's all a candidate for being an instruction.

You can mitigate it — and I do: external content comes in tagged as quoted material, the system rules are explicit, and the generator always works from a concrete anchor. But mitigating isn't sealing. Nobody has solved prompt injection. Anyone telling you otherwise is selling you something.

The second half of the trap looks inwards. My generator has hard rules: don't invent client names, don't invent prices or deadlines, don't invent figures. All of that is a prompt. And a prompt is a very well phrased request, not a technical control. A model can drift past it, misread it, or be pushed off it by the source material. That's why those same rules are also written down as a checklist for the human reviewer. What the prompt asks for, the reviewer verifies.

Which leads to the only defence that actually holds: separate who writes from who publishes. The process that generates text doesn't hold the publishing key. The key lives in a signed link that lands in my inbox. Even if someone managed to manipulate the entire draft, they still need me to press approve.

The boring detail that prevents nasty surprises

In the same batch of work I put a time limit on the workflow. A job hanging around waiting for a response that never comes isn't a dramatic failure: it's a bill for compute minutes and an email that never goes out, plus the false impression that there was nothing to review that week. With a limit, it fails fast, I find out, and I fix it. I'd rather have a visible error than a silent process.

What this does NOT solve

So it doesn't catch you out:

  • It doesn't guarantee the text is good. It filters out the unpublishable, not the mediocre. That's still my job.
  • It won't spot a false fact that sounds right. That's the most dangerous failure mode of a model: the plausible sentence. The only way to catch it is to open the source and check the number. By hand.
  • If I approve without reading, the system won't save me. The control is a habit with a button next to it, not a button.
  • The email is a credential. Whoever has access to that inbox has access to publishing. It gets treated as what it is: a key.
  • There's no second pair of eyes. Black Wings is me. One reviewer beats none, but it isn't the same as two.

Why I'm telling you this

Because the pattern transfers straight across to any AI automation that touches the real world — sending a quote, writing to a client, moving an order. The question isn't "how well does the model write?". It's "what can it execute with nobody looking, and what happens if I do nothing?". If the answer to the second one is "it goes ahead", your default is the wrong way round.

Any questions, tell me and we'll look at it.

All the best, Vicente.

Did reading this raise a question?

Ask us. We answer even if you never become a client.