Production notes · Autonomous newsroom

The Gatekeeper Log

An AI newsroom has published 105 posts without a journalist. This is every fact it invented along the way, and the agent whose only job is to disbelieve it.

105posts published
16killed by the gatekeeper
463model calls a day
$0.69cost per post
4subscribers

I built a newsroom that runs without me. Eight agents, about 460 model calls a day, ten posts a day to Telegram and Threads. I approve or reject. I don't write, edit, fact-check or lay anything out, and I haven't since the first week.

The part I expected to be interesting was the writing. The part that turned out to be interesting is the agent that reads the writing and refuses to let it out.

The pipeline

harvest dedup screener trend factcheck editor designer gatekeeper me publish

Everything before the editor is classification. The editor is the only agent that produces prose, and prose is where fabrication lives. So the gatekeeper is the only agent whose job is to disagree with another agent — and it is the only one that has ever caught anything that mattered.

In the six days I have full records for, it killed 16 posts against 105 published. Here is what it killed them for.


What it caught

Entries are verbatim from the rejection log, translated where the reasoning was written in Russian. Wavy underline marks the part the model invented.

1 · Invented precision

The most common failure by a wide margin. The model supplies a specific number, name, date or jurisdiction that the source did not contain. Not a distortion of a fact — an addition where there was no fact at all.

22 Augkilledgithub project story

roughly 2,800 GitHub stars this week

That number appears in neither the source article nor the factcheck. Both mentioned the project's traction in words only.

27 Augsent back, fixedopenai agents / hugging face

… according to the 37-page report

The report's length is not stated anywhere. It appeared in the hook, in the body and in the Threads variant — one invention, three surfaces.

21 Augkilledlitigation story

… filed in a New York federal court

Neither the source nor the factcheck named any jurisdiction.

24 Augkilledproduct dating

… on 20 August 2026

The source said “20th August”. The model supplied the year, and the year was the part that mattered.

2 · Entity substitution

A proper noun replaced by a plausible neighbour from the same category. These are the most dangerous, because the sentence around them is otherwise correct and the substitute is the kind of name a reader expects to see.

27 Augsent back, fixednvidia quarterly

… its biggest customers — Amazon, Apple and Walmart

The Verge named Amazon, Apple and Alphabet. One member of a memorised triple swapped for another large American company.

26 Augsent back, fixedthe witcher 3 remaster

… handled by third-party studio Yigsoft

No such company appears in the source, in CD Projekt Red's press release, in Gematsu, in RPGSite, or in the factcheck. The studio was invented whole.

24 Augkilledhugging face funding

Hugging Face hired a bank to sound out investors

Present in neither the source nor the factcheck. A standard funding-story clause attached to a story that didn't have one.

3 · Arithmetic that contradicts itself

Rarer, and easy to miss on a read-through, because each individual number is correct.

21 Augkilledrobotaxi permits

body: 5,000 (Tesla) + 1,000 (Waymo) + 1,000 (Uber), against a stated total that is not 7,000

Every component figure was sourced. The sum was never computed, and the total came from somewhere else.

4 · Image and text describing different things

A structural failure rather than a linguistic one: the designer picks the image and the ALT text is written against the story, not against the picture that actually got attached. Two agents, no shared ground truth.

20 Augkilledfda story

attached: photo of an FDA headquarters sign · ALT text: describes something else entirely

Caught only because the gatekeeper is given the image alongside the copy.

21 Augkilledsmart glasses

attached: stock photo of broken sunglasses · ALT text: Ray-Ban …

A generic stock image described as a specific branded product.

5 · Borrowed authority

The factcheck returns caveats — an explicit list of claims that are circulating but unverified, which the writer is told not to assert. Several kills are the editor asserting them anyway.

23 Augkilledmodel release

a top-tier model

The factcheck had explicitly forbidden presenting the circulating benchmark figures as established. The post presented the conclusion instead of the figures.

Not everything it catches is a hallucination. On 21 August it killed a post for two runs of mojibake where em dashes should have been — costs up to 384 tokens ext and model reads in one go and — an encoding bug that had survived every stage before it.


What I take from this

Every one of these is fluent. None is a grammar failure, a topic drift or an obvious confabulation. The model is not losing the thread. It is finishing the sentence the way a journalist would finish it — with the specific detail a journalist would have looked up.

The failures cluster exactly where journalism demands specificity: numbers, proper nouns, jurisdictions, dates, page counts. Precision is a register, and the model produces the register whether or not it has the facts to fill it. What looks like lying is closer to style transfer.

Retrieval did not prevent any of this. The factcheck agent had already searched the web and handed over confirmed facts and explicit caveats. Every fabrication above happened downstream of retrieval, in the writing step, with the correct facts sitting in the context window. Grounding the writer is not the same as grounding the text.

One invention reached the hook, the body and the Threads variant. Because a single pass produces every surface, a single hallucination is copied into all of them — and anything that checks one surface passes the rest.

Self-review would not have caught these. The gatekeeper works because it is a separate call with a different job, holding the factcheck and the finished text side by side, with no stake in the prose. Asking the writer to check its own work asks it to re-derive the same plausible detail.


Killing costs more than fixing

A kill at the last stage is the most expensive failure in the pipeline. The factcheck, the editor and the designer have all been paid for — about 55 cents — and the post dies one step from publication.

So the gatekeeper now returns its specific objections and the editor rewrites against them. One retry, then the kill stands. A retry costs one editor call plus one gatekeeper call, about 13 cents.

26.08 10:09  humanoid robot games   sprint time didn't match Al Jazeera
26.08 13:55  the witcher 3 remaster  invented developer "Yigsoft"
27.08 08:14  openai / hugging face   "37-page report", unverified
27.08 13:40  nvidia quarterly        Walmart substituted for Alphabet

Four fires in two days, four posts saved. I am not going to put a monthly figure on that yet: rejections ran at 2.8 a day for six days and then zero for two. Two days is not a trend, and one of those six days was a run of Apple rumours where there was unusually much to embellish.


The money

Cost per published post, from the first full day of operation:

2.29
2.97
1.22
0.55
0.68
0.84
0.71
0.69
19202122 23242526
US dollars per published post, 19–26 August 2026. Ten posts a day throughout.

$2.97 at the peak, under a dollar since the 22nd, sitting around $0.70. What moved it was not prompt trimming, which is where I started and which achieved almost nothing.

Prompt caching is not free, and its price is per agent

Anthropic charges 1.25× the input rate to write a five-minute cache entry and for a one-hour entry. Reads cost 0.10×. So a one-hour cache only pays for itself above roughly 1.11 reads per write; below that you are paying double for nothing.

I had caching on globally, at one hour, because that is the obvious default. But three agents — editor, designer, gatekeeper — run once per post on context unique to that post. They never got a single cache read. Every call was paying twice the input rate to write an entry that would never be read.

Setting the TTL per agent instead of globally — off for those three, five minutes for the factcheck, an hour for the screener and trend agents — cut the day's bill by 14.4% with no other change. Same models, same prompts, same output.

AgentCallsCost ShareCache
factcheck13$2.8842.0%5 min
trend100$1.6824.5%1 hour
gatekeeper12$0.7911.5%off
editor12$0.7611.2%off
screener298$0.446.4%1 hour
designer10$0.263.8%off
dedup18$0.050.7%1 hour
total463$6.85100%

The screener does 64% of all calls for 6% of the money: it runs on Haiku and its system prompt is stable enough to returns 297 cache reads per write. The factcheck is 42% of the budget on thirteen calls, because each call accumulates web search results — about 18,400 cache-write tokens apiece. Volume is cheap. Context is expensive.


Two bugs that had nothing to do with AI

A moderation card sat unanswered for four days and held a slot in a five-deep queue. Production stopped completely — “queue full (5)” — and I didn't notice, because the system went on reporting normally about doing nothing. Nightly summaries arrived, costs were logged, health checks passed. Cards now expire after 24 hours.

The producer counted finished posts rather than started ones, and started them concurrently. Asked for four, it launched seven and paid for all of them. The check and the increment now happen with no await between them.

Ordinary concurrency and queue bugs. What makes them expensive is that an autonomous system keeps running, keeps spending and keeps reporting success while it does the wrong thing. Anything that would have been obvious to a human sitting in the loop is invisible when nobody is.


The part that doesn't work

The newsroom works. The channel has four subscribers.

The 55 posts I have measurements for drew 199 views between them — four per post, which is exactly the subscriber count. Zero reactions. Zero forwards, ever. Every view is one of the four people already there, and one of them is me.

This is not a content problem, and it took me an embarrassingly long time to accept that. Telegram has no feed. A new channel gets zero impressions; the platform will never show a post to anyone who has not already subscribed. There is no discovery to optimise for. Growth is imported from somewhere else or bought, and that is the whole list.

The same posts on Threads, where there is an algorithm, average 297 views against 46 followers. The best one did 5,068.

I have a fact-checked newsroom producing ten stories a day at sixty-nine cents each, and a distribution problem I had not thought about for one minute, because building the pipeline was the interesting part.

I spent a week on cache TTLs to save two dollars a day, and no time at all on the question of whether anyone would read the output. The engineering was tractable and the distribution was not, so I did the engineering. I suspect that is the most common shape of this mistake.

The channel is t.me/TechSynapse, if you would like to be subscriber number five. The same posts go to Threads, where the algorithm has been considerably kinder.