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.

Built
Retired
Written
Author
Okavyx
Status
Retired · read-only archive
Audience
Technical owners and anyone curious how it 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.

15external services and APIs
8AI model calls per article
5different language models
118nodes across 6 live workflows
583articles published

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.

PrincipleWhat it meant
Facts firstEvery rewrite is built only from the extracted fact list, never from the original article.
Show the seamsThe loaded words are highlighted, and the prompts were published.
No sideThe centrist version is the baseline; the site takes no position.
Run unattendedA scheduled pipeline finds, writes and publishes without a person in the loop.
Right model, right stepCheap 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.

Triggersschedule, email, adminNews sourcesRSS feeds, web searchn8n pipeline6 workflows, 118 nodesAI modelsOpenAI, Anthropic, xAIContent fetchcontent + transcriptsImage sources5 APIs, vision judgeSearchPerplexity SonarMySQLarticles, tags, sharesObject storagechosen imagesPHP siteread-only renderCloudflareDNS + proxyReaderany browser
Figure 1. Architecture. Dashed boxes are supporting infrastructure.

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.

1 DiscoverRSS + keyword filter2 De-duplicatelast 500 links3 Fetchscrape or transcript4 Length gatestop if under 6005 Factsheadline, facts, tags6 Centristneutral baseline7 Framing briefsleft and right angle8 Rewritesleft and right article9 Quality gatelength + bias phrases10 Imagebattle royale11 Storeone upsert + tags12 Notifypush alert
Figure 2. The article pipeline. The two dark steps are gates that stop weak work before it is published.

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.

#StepModelRoute
1Headline, facts, tagsGPT-4.1 nanoOpenAI
2Centrist articleGPT-4.1 nanoOpenAI
3Left framing briefClaudeAnthropic
4Right framing briefClaudeAnthropic
5Left articleGrok 4.3OpenRouter
6Right articleGrok 4.3OpenRouter
7Image search termGPT-4.1 nanoOpenAI
8Image judge (vision)GPT-4o miniOpenRouter

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

GroupServices
Language modelsOpenAI, Anthropic, OpenRouter (routing to xAI and OpenAI models), Perplexity
Content fetcha content-extraction service, a video transcript service, YouTube (metadata)
Image sourcesWikimedia, Pexels, Unsplash, Pixabay, Openverse
Storage and alertsAWS 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.

Headline+ tagsArt Directorwrites search termWikimediaPexelsUnsplashPixabayOpenverseMergeall candidatesVision judgelooks at picturesStore + creditcopy to bucket
Figure 3. Five sources enter, one image leaves.

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.

ProblemApproach
Pages that could not be readA 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 parallelResults normalised into one shape, merged, judged by a vision model, with a first-candidate fallback if the judge fails.
Controlling costSmall models for mechanical steps, large models only for framing, one article per run in the early version, a cap on retries.
Getting distinct voicesCentrist cold, left and right hot; a separate brief step so the writer commits to an angle.
DuplicatesEvery candidate checked against the last 500 stored links before any paid call.
Curating the news feedA 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 pointsSchedule, email, admin button and a research hand-off all feed one shared tail, so the data shape must match exactly.
Shared building blocksScraping and image selection are sub-workflows called by others, so each is built and fixed once.
Silent failuresA step that substitutes placeholder text on error lets later steps pay for garbage. Review work recommended failing loudly instead.
Wasted spend after late failuresA 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 websiteAdmin buttons triggered the pipeline through authenticated webhooks, fire-and-forget.
Keeping exports honestLive 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.

ConcernDefence
Source or secrets exposedPublic web root limited to one folder; source, configuration and environment files outside it; secrets never committed.
SQL injectionPrepared statements with emulation off, everywhere.
Cross-site scriptingOutput escaped once; highlighting inserted by a helper that only wraps matched phrases.
Admin takeoverHashed password, hardened cookies, private session store, session rotation, inactivity logout.
Request forgeryRotating token, constant-time comparison, required on every admin write.
Pipeline abuseAuthenticated webhooks for admin-triggered runs.
Error leakageGeneric 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.

A retirement is finished when the live system says so, not when the repository does. Deployment tooling that copies files in but never deletes them would have left the admin panel running indefinitely without an explicit delete step.

12Appendix: facts and figures

ItemValue
Built13 November 2025; live 19 November 2025
Retired11 September 2026 (read-only archive)
Articles published583
StackPHP 8, vanilla JavaScript, MySQL or MariaDB, one Composer library
Pipelinen8n: 6 live workflows (main 52 nodes, image 29, scout 15, harvest 10, curator 9, researcher 3)
Model calls per article8, across 5 models and 3 routes
External services15, plus RSS feeds, DNS and search console
Image sourcesWikimedia, Pexels, Unsplash, Pixabay, Openverse
Peak SEO audit score99

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.

← All white papers Log a job →