Technical white paper · v1.0
BiasFeed: an unattended AI newsroom built from off-the-shelf parts
How a pipeline built with AI assistants turns a news story into three framings, a picture and a published page. Retired on 11 September 2026 and kept here, read-only, as a record of what was built.
01Executive summary
BiasFeed took a news story and showed it three ways. A neutral list of facts came first. From those facts alone, the system wrote a centrist article, a left-leaning article and a right-leaning article, set them side by side and highlighted the loaded words. The aim was media literacy: to make framing visible.
This paper describes what was built, and it is written as a demonstration of capability. BiasFeed has since been retired (section 11). The system ran unattended from November 2025, published 583 articles and is a complete example of an AI content pipeline built from off-the-shelf parts with AI assistants.
02The problem and the design principles
Bias is hard to see from inside a single article. A reader gets one framing and tends to mistake it for the facts. BiasFeed removed that by decomposing the story to facts, then showing what each side could build from the same facts.
| Principle | What it meant |
|---|---|
| Facts first | Every rewrite is built only from the extracted fact list, never from the original article. |
| Show the seams | The loaded words are highlighted, and the prompts were published. |
| No side | The centrist version is the baseline; the site takes no position. |
| Run unattended | A scheduled pipeline finds, writes and publishes without a person in the loop. |
| Right model, right step | Cheap models for mechanical work, stronger models where quality shows. |
03System architecture
Two halves joined by a database. The pipeline does all the thinking and writing. The website only reads what the pipeline stores.
The site is PHP 8 with no framework: small entry-point scripts, templates that only render, and a few shared helpers. The front end is plain HTML, CSS and a single JavaScript file. Source, configuration and secrets live outside the public web folder.
The pipeline is n8n, a visual workflow tool where steps are boxes and data flows along lines. The pipeline ran on its own server. The database is the contract between the two halves: the pipeline writes articles, tags and links in one pass, and the site never calls the pipeline to render a page.
04From news article to three framings
The main workflow has 52 nodes. Figure 2 shows the path of one story.
Finding stories: our own news aggregator
Rather than use a third-party aggregator, we built one as a small web service inside n8n. A request to its address runs a nine-node workflow: it reads a list of source feeds from national and international publishers, pulls an editable keyword allow-list from the database, keeps only items whose title or summary matches a keyword, sorts them newest first, builds a fresh RSS document by hand and returns it. The main pipeline consumes that curated feed like any other, and so could any other tool. Editing the allow-list in the admin panel changes what the newsroom covers on the next run, with no workflow edit. Keeping it as its own service meant the filtering logic lived in one place and the main workflow stayed simple. A second workflow, the Scout, asks a search model for trending topics and hands rich research to the main pipeline. Stories can also arrive by email or from an admin button. Everything is checked against the last 500 stored links so nothing is covered twice.
Fetching the text
Article text was fetched through a commercial content-extraction service. YouTube links go through a transcript service instead. If the extracted text is under 600 characters, usually a paywall or a dead page, the run sends an alert and stops, so a model is never asked to write from nothing.
Writing the three versions
One call extracts a neutral headline, a numbered fact list and one to three tags from an approved list. A centrist article is written from the facts at a low temperature (0.2) for steady, neutral prose. For the left and right versions, one model first writes a framing brief describing the angle, then a second model writes the article to that brief at a higher temperature (0.7) so it commits to a voice. Each version also returns the specific words and phrases that carry the slant, which drive the Show Bias toggle. A rule checks every rewrite for length and at least three flagged phrases before it is allowed through.
Storing and telling the owner
One upsert writes the article keyed on its URL slug, then a loop creates and links tags. A push notification reports each success or duplicate.
05AI model calls and external services
Eight model calls are made for each published article, using five different models routed through three paths: OpenAI directly, Anthropic directly, and OpenRouter, a gateway to many providers.
| # | Step | Model | Route |
|---|---|---|---|
| 1 | Headline, facts, tags | GPT-4.1 nano | OpenAI |
| 2 | Centrist article | GPT-4.1 nano | OpenAI |
| 3 | Left framing brief | Claude | Anthropic |
| 4 | Right framing brief | Claude | Anthropic |
| 5 | Left article | Grok 4.3 | OpenRouter |
| 6 | Right article | Grok 4.3 | OpenRouter |
| 7 | Image search term | GPT-4.1 nano | OpenAI |
| 8 | Image judge (vision) | GPT-4o mini | OpenRouter |
Discovery adds two more calls to a search model (Perplexity Sonar): one to find trending topics and one to gather researched facts with citations. The first version of the system used a single large model (GPT-4o) for every step; the split above is what it evolved into.
The 15 external services
| Group | Services |
|---|---|
| Language models | OpenAI, Anthropic, OpenRouter (routing to xAI and OpenAI models), Perplexity |
| Content fetch | a content-extraction service, a video transcript service, YouTube (metadata) |
| Image sources | Wikimedia, Pexels, Unsplash, Pixabay, Openverse |
| Storage and alerts | AWS S3 (image storage), Pushover (push alerts), IMAP email (inbound links) |
Add the news RSS feeds, Cloudflare for DNS and proxying, and Google Search Console for index monitoring, and the system touched about eighteen outside systems in total.
06The Image Battle Royale
Every article needs a picture, and generated images were too costly and too risky for news. The Art Department workflow, nicknamed the Image Battle Royale, lets every source compete and has a model look at the actual pictures.
An art director model decides whether the story is about a named person or place, or about a concept, and writes a search term. Five image libraries are searched in parallel, results are normalised to one shape and merged, and a vision model reviews all the candidates and picks the best fit. The chosen image is stored with its credit and source shown on the page. If the judge fails, a code step falls back to the first valid candidate. The workflow was later reused as a public demonstration of the pattern.
07Working with n8n: the problems we solved
n8n makes the happy path quick to build and easy to read. The hard problems appear when the system runs unattended.
| Problem | Approach |
|---|---|
| Pages that could not be read | A content-extraction service, a transcript service for video, and a minimum-length check that stops the run rather than let the model invent a story. |
| Five image searches in parallel | Results normalised into one shape, merged, judged by a vision model, with a first-candidate fallback if the judge fails. |
| Controlling cost | Small models for mechanical steps, large models only for framing, one article per run in the early version, a cap on retries. |
| Getting distinct voices | Centrist cold, left and right hot; a separate brief step so the writer commits to an angle. |
| Duplicates | Every candidate checked against the last 500 stored links before any paid call. |
| Curating the news feed | A purpose-built aggregator service: source feeds, a database keyword allow-list, newest-first sort, hand-built RSS output. It degrades poorly if one feed is down, a gap the review flagged. |
| Different entry points | Schedule, email, admin button and a research hand-off all feed one shared tail, so the data shape must match exactly. |
| Shared building blocks | Scraping and image selection are sub-workflows called by others, so each is built and fixed once. |
| Silent failures | A step that substitutes placeholder text on error lets later steps pay for garbage. Review work recommended failing loudly instead. |
| Wasted spend after late failures | A persistence design was written: store each paid response before parsing it, resume rather than repeat, and queue weak articles for review rather than discard them. |
| Triggering from the website | Admin buttons triggered the pipeline through authenticated webhooks, fire-and-forget. |
| Keeping exports honest | Live changes are re-exported to the repository in the same change, so the files describe what actually runs. |
The pattern across all of these: the visual builder gets a working pipeline in days, while resumability, cost tracking and failure attribution have to be designed in deliberately.
08The website
Readers get a tabbed article view (Facts, Centrist, Left, Right), a side-by-side compare mode with synchronised scrolling on desktop and a wipe slider on mobile, a Show Bias toggle that highlights the loaded words, dark mode, search, a tag index, clean URLs, an RSS feed and a generated sitemap. Share links deep-link to a chosen viewpoint, and a small beacon records which viewpoint and platform were shared. A search-optimisation pass in 2026 lifted our own audit tool's score from 58 to 99, adding structured data and a plain-text summary for AI crawlers.
A password-protected admin panel allowed article editing, image replacement, keyword management, share analytics and one-click pipeline runs.
09Security approach
Everything public is probed, so the design assumed hostile input from day one.
| Concern | Defence |
|---|---|
| Source or secrets exposed | Public web root limited to one folder; source, configuration and environment files outside it; secrets never committed. |
| SQL injection | Prepared statements with emulation off, everywhere. |
| Cross-site scripting | Output escaped once; highlighting inserted by a helper that only wraps matched phrases. |
| Admin takeover | Hashed password, hardened cookies, private session store, session rotation, inactivity logout. |
| Request forgery | Rotating token, constant-time comparison, required on every admin write. |
| Pipeline abuse | Authenticated webhooks for admin-triggered runs. |
| Error leakage | Generic error pages in production; failures logged without secrets. |
Credentials for third-party services belong in the workflow tool's credential store, not inside workflow settings, and anything exported should be scanned first. That rule is applied throughout.
10How it was built
The first working version took one day on 13 November 2025, built with AI assistants (Gemini and Cursor, then Claude). The site went live six days later. Within two weeks it had clean URLs, share analytics, images, pagination, an admin panel and full automation including the RSS feed. In its first fortnight the repository gained more than fifty commits.
Two habits mattered most. First, deliberate clean-up passes in which the AI was told to act as a strict reviewer rather than a builder, which found real problems every time. Second, a documentation audit in 2026 that reconciled the repository with what was actually running, recorded every workflow, and produced a specification. In hindsight that audit belonged in the second week.
The pipeline was later extended with a research stage, a framing-brief stage and a persistence design, and the site gained an interactive demonstration of how personalised persuasion works.
11Lessons and retirement
What we learned
- Facts-first decomposition works. Building every version only from a neutral fact list was the cleanest design decision.
- Match the model to the step. Cheap models for mechanical work, strong models where quality shows.
- Let sources compete. Five image libraries and a vision judge beat trusting any single search.
- Unattended is not unmonitored. Scheduled work needs checks that go red when it stops.
- Design for failure first. Resume points, loud errors and a review queue are cheap before launch and expensive after.
- Unattended publishing was the riskiest choice. Publishing AI-written news with no person in the loop is a risk we would not take again; later systems put a person before anything public.
- Keep production and the repository identical. Live edits drift quickly.
- AI builds fast and forgets faster. Write the documentation from the live system as you go.
Why it was retired
The site answered the question it was built to answer. The generated left and right rewrites never reached the quality hoped for, the same pipeline would be built differently today, traffic stayed very low, and it carried a monthly API cost with no return. In September 2026 it was retired deliberately: a rollback tag first, then all workflows switched off, the site kept online as a read-only archive behind a notice, search engines told through a noindex while crawling remained permitted so the delisting could be seen, databases and workflow exports archived, and a 14-point automated check run against the live site to prove the end state.
12Appendix: facts and figures
| Item | Value |
|---|---|
| Built | 13 November 2025; live 19 November 2025 |
| Retired | 11 September 2026 (read-only archive) |
| Articles published | 583 |
| Stack | PHP 8, vanilla JavaScript, MySQL or MariaDB, one Composer library |
| Pipeline | n8n: 6 live workflows (main 52 nodes, image 29, scout 15, harvest 10, curator 9, researcher 3) |
| Model calls per article | 8, across 5 models and 3 routes |
| External services | 15, plus RSS feeds, DNS and search console |
| Image sources | Wikimedia, Pexels, Unsplash, Pixabay, Openverse |
| Peak SEO audit score | 99 |
Our work is always evolving, and so are the AI vendors and their products. Nothing described here is set in concrete. Each paper describes its system as it stood in October 2026, when it was written; the date shown is when the app was first built.