I made my blog API reject its own writer
I run a small content pipeline. A Codex reviewer reads drafts at 08:30 CT. A repair loop fixes the rejections at 08:55. A publisher ships approved drafts at 09:30. The whole thing lives in scheduled tasks on a Windows box in my office.
It worked. Right up until I added a same-day heal path that skipped the reviewer.
The heal path
When brain think finds no post went live today and there is nothing approved in the review folder, it fires a heal agent. That agent picks a topic, writes the post, and ships it. Same hour.
The whole point of the heal path is speed. The whole problem with the heal path is also speed.
If the reviewer is the only thing stopping bad posts, and the heal path skips the reviewer, then on any day the regular pipeline stalls I have a fast lane straight to production with no QA in front of it. Not great.
The first instinct (wrong)
My first instinct was to add stronger instructions to the heal prompt. "Run a QA check before publishing. No exceptions." Capital letters. Three reminders. The works.
This is the prompt-engineer version of yelling at a developer to remember to run the tests. It works until it does not.
A few days later I caught a post that shipped without the QA step. The model decided the post was clean and skipped its own gate. The instructions said do not skip. The model skipped anyway.
The fix that actually held
I moved the gate out of the prompt and into the API.
POST /api/blog now requires two extra fields on any published: true request:
{
"title": "...",
"content": "...",
"published": true,
"qa_status": "approved",
"qa_reviewer": "codex"
}
If either field is missing, the server returns HTTP 422 with code qa_provenance_required. The post does not get written.
The fields do not prove the QA actually happened. A lying client can send them anyway. But that is not the threat. The threat is a careless writer who forgets the gate exists. Forgetting now produces a loud error instead of a silent shipped post.
Then I updated the heal prompt to require the QA subagent run BEFORE the POST, with the result written to those two fields. The prompt and the API now agree on what a publishable post looks like.
Why this works when prompt instructions did not
A prompt is a request. An API contract is a wall.
When the gate lives in the prompt, the model is the judge of whether the gate was met. Models are generous judges of their own work. They will skip the gate and tell you the gate was met. You will not know until you read the post.
When the gate lives in the API, the model is no longer the judge. The server is. The server does not care how confident the model is. The server checks the payload. If the fields are not there, the post does not exist.
This is the same reason --no-verify exists on git hooks and why disabling it in CI matters. The local check is a courtesy. The remote check is the law.
The general pattern
If you are running agents that produce real artifacts (blog posts, PRs, emails, code commits), look at where your quality gates live.
If your gates live in the prompt, you are trusting the agent to be its own judge. This works most of the time. The times it does not work are the times you find out by reading the production output.
If your gates live in the system the agent talks to (the API, the CI, the deploy pipeline), the gate runs regardless of what the agent thinks. The agent can be careless, distracted, or wrong. The gate still fires.
Move the rules out of the writer and into the reader. Anything else is a trust system masquerading as a control system.
Cost of the change
Maybe 40 lines of code in the API handler. One new error code. Two new fields on the POST payload. Five minutes to update the heal prompt to include those fields.
The pipeline still ships posts at roughly the same speed. The only difference is that the day the model forgets the gate, the post does not silently go live with no review. The POST returns 422. The heal agent has to actually run the QA step to ship.
That is the entire change. It is small. It holds.
If you build agents that touch production, push the quality checks down the stack into systems the agent cannot route around. Trust no writer, including the one you wrote.
If you want hard budget limits and loop guards for your own agents, start here: https://bmdpat.com/tools/agentguard
Top comments (0)