
A content machine for small B2B companies, built in five weeks with a team of AI agents
Product strategy
Interface design
Engineering by proxy
Published Nov 2026
·
🥵 39 min read
I write a blog called Verbatim, and I banned AI from it. Not even Grammarly gets in. Then, in the autumn of 2026, I spent five weeks building a machine that writes blog posts for companies, and I built most of it by talking to AI agents. I’m aware of the irony. I’ve made peace with it, mostly.
I called the machine Propaganda. Once a company signs up, Propaganda reads its sales calls, its Slack and its old posts, keeps a record of what the company believes, pitches posts that would help it get found, writes them in the company’s voice, checks every claim, and puts them on a blog. I built it so that nothing goes out until someone at the company has approved it.
This case study is long, like the others on this site. It covers five things: the strategy behind the product, the editor and its UX, the agents and how they work together, the writing research we ran to make machine prose bearable, and a drawer of odd things we did along the way. I drew every screen as a real HTML copy of the app, filled in for a made-up company called Fullhouse that schedules shifts for restaurants and clinics. Fullhouse doesn’t exist, and its blog is still better than most real ones.

The pipeline for Fullhouse, the made-up company that lives in our screens. Pitches on the left, drafts in the middle, this week’s posts on the right.
In a nutshell
Role: product, design, writing, review, and every decision. Claude agents wrote the code, one per module, while I played the product manager, the designer and the annoying client.
Duration: I gave Propaganda its current shape in five weeks, from 5 October to 5 November 2026. I started the editor under it six months earlier.
Output: 39 releases (v0.2.0 on 11 October, v0.8.5 on 5 November), 360 merged pull requests, eight agents, a Claude plugin, a free writing style checker, and our own blog, written and published with the product.
Outcomes: none you can bank yet. We let companies in from a waitlist, a few at a time. Ask me again in a year.
1. Strategy
1.1 It started as Verbatim
Propaganda began as a fight with my own blog. My site ran on Framer, and I wrote in Notion. For every post I wrote in one tool, pasted into the other, fixed the formatting the paste broke, and did it all again when I changed a word. I love Notion and I like Framer, and wrangling the two of them for every essay made me want to stop publishing.
On 25 April 2026 I wrote a plan called Verbatim: move the site off Framer into a CMS called Payload, and build a migrator to carry everything across. It lasted about two weeks. Payload worked fine, but its makers had built the admin for people filling in forms, and I wanted to sit down and type. So on 10 May I started again with a writing app of my own, also called Verbatim, that replaced Payload’s admin. I gave it an editor that felt like Notion, saved every keystroke on the device first, and added a command palette and one shortcut to publish. By the next evening it held 221 posts.

Verbatim on 11 May 2026, the evening after I started it. A screenshot, the only one on this page.
That is the screen from 11 May. It shows five collections, 221 posts, and a Test collection with one post in it, which will become important later. Over the summer I turned Verbatim into the backend for my blog, which I mostly keep private anyway. I published the posts I’m happy with and left the rest in a writer’s drawer.
On 23 September Verbatim became multi-tenant and got a new name. From that day any company could run a blog on it, on its own subdomain or domain, and I called the product Propaganda. I put the marketing site live on 28 September. The editor in this case study is still the one I built for myself in May, grown up.
1.2 A CMS can’t make money
I launched Propaganda as a CMS, with five pillars I was very proud of: plan, write, publish, share, measure. It was a good editor with a good blog attached, and in October I had to admit that nobody pays for that. There are a hundred blogging tools out there, and the good ones are free forever. A CMS on its own is a hobby with a login page.
So I asked what a company would pay for. I had spent years at airfocus watching product teams drown in their own information, and marketing had the same problem. What a company knows is spread across its people: the CEO’s opinion of a competitor’s launch, the paper the engineers argued about, the question that crushed a sales rep on a call, the seven different answers an intern got in onboarding week. Each of those is a post. Almost none of them get written, because nobody in marketing was in the room.
I worry least about the writing. Claude writes a post in about a minute. Finding out what is true about a company takes the rest of the week, and keeping it true takes the rest of the year. That became my bet, and Propaganda became a knowledge base company that happens to publish.
1.3 Knowledge bases rot
I have never worked at a company whose wiki was still right in its second month. A wiki stays right only while somebody remembers to update it, and I’ve watched people forget for years. At the companies I knew, the pricing page said one thing, the blog said another and the sales deck said a third, and each had been true on the day somebody wrote it.
So I decided early that our knowledge base would be a list of claims, one sentence each, and never a pile of pages. I gave each claim four states: settled, contested, superseded or retracted. We link every post to the claims it relies on, both ways, and when a claim changes, the posts that used it go back for a re-check. We gave every topic an owner, and the owner’s word is final. One person can overrule anyone on any topic, which in most companies is the CEO and in mine is me.
Then I stole from engineering, because engineers solved this problem twenty years ago and called it version control. A change to what the company believes arrives as a proposal, shaped like a pull request. I modelled topic owners on code owners. We group the re-checks after a change the way a dependency bot groups its updates, and a price change sends you one notice instead of forty. We wrote the rules for what gets admitted as policy, with tests. On 5 October I put all eight of those practices in front of myself in a review round and approved every one, which is the luxury of being the whole committee.
💡
The pattern I keep coming back to, from airfocus to here: when a product problem looks unsolvable, look for the discipline that has been fighting it longest and copy their tools. Engineers have spent decades on “many people changing one source of truth”. Marketers have spent those decades on fonts.
1.4 Opinionated, this time
At airfocus I argued for software as an exoskeleton. We wanted a team to bring its own process and the tool to fit around it. We used to make fun of opinionated tools that told you how to work (I called one competitor Productbored, and I stand by it). With Propaganda I did the opposite, and I chose it with my eyes open.
I watch AirOpps more than any other competitor. On a feature list we look alike. AirOpps builds content workflows for growth teams who want a toolbox and have someone to run it. We sell to the small company with no marketing team, where the founder is the marketing team on Tuesdays. If that’s you, you have no time for a toolbox. You want to approve a pitch on your phone between two calls and see the post on your blog that Thursday. So I made Propaganda opinionated: four goals a quarter, a plan, pitches, drafts, a review, a publish button. You can change the plan, and you can’t turn Propaganda into a spreadsheet.
The other difference is where the ideas come from. AirOpps starts from what people search for. We start from what the company knows and has said, and then we check it against what people search for. We read the searches so we don’t write for ourselves, and we read the calls so we don’t write the same post as everyone else.
1.5 The price, and the human
I priced Propaganda in one afternoon, and the prices haven’t moved since. Propaganda Light is free: the editor and a hosted blog on your own domain, with no agents and no AI at all. We charge $500 a month for the whole machine. For $999 a month, one of us who knows your account sits in on your quarterly goals and reads your drafts. Pricing for several brands starts at $5,000.
I like the $999 tier best. With it I admitted something most AI companies won’t: a person who reads your drafts and tells you which one is embarrassing is still worth more than another feature. On the page I wrote “Cheaper than a content marketer. Doesn’t quit after eight months.” I know the second sentence is the cheapest shot on the site, and I keep it there anyway.
I made one more pricing decision, about AI costs. We log every model call with its company, its model, its tokens and its cost, and you see your month on the Home page. We set a monthly budget, warn you at 80%, and at 100% pause the background work until next month, while the editor and the blog keep working. Before a big job, like reading three years of calls, you approve an estimate. I’ve received surprise invoices from AI tools, and I would like nobody to receive one from me.
1.6 The Strategist: strategy as a feature
The Strategist is the first agent to meet a new company. I gave it the job I did at airfocus for the company as a whole, which was writing the quarter’s plan. You answer a few questions about your business. Then the Strategist reads your website and the searches your buyers make, and proposes four goals with a reason under every number.
We named the four goals Volume (how many posts, split by topic), Consistency (whether the posts agree with each other and with the knowledge base), Readership, and Ranking (ten target searches, on Google and in AI answers). We had a fifth, Coverage, and dropped it on 8 October. Four goals fit in one glance, and five already needed a legend.
I wrote the Strategist’s rules from what I had seen founders do with content plans. It may not propose more than 20% above what you shipped last quarter, since a plan you can’t keep is a plan you stop opening. For a new blog it plans a Launch: fifteen posts written in twenty days and published over thirty, so Google has something to index and the blog never goes quiet while it learns who reads it. I left no slot for “opportunistic” posts, because in my experience opportunistic means “the ones we didn’t write”. Ideas from calls and from the news compete for the planned slots instead.

A quarter’s plan from the Strategist: four topics, ten target searches, a reason under every number.
Our own plan is public. The Strategist wrote it for Propaganda’s blog on 14 October, we answered its questions over three rounds, and I approved the fourth version. You can read it as it was approved. In it the Strategist aimed for two searches on page one this quarter, since a domain with no history can win the two under difficulty 20 in eleven weeks. It gave the other eight longer and said so in writing, which is more honesty than most strategy decks I’ve been paid to write.
1.7 The Strategist read our illustrations
The best bug of the project lived in the Strategist, and it was my fault.
On 12 October a plan for our own blog cited a fact about us: “The Growth plan was renamed Scale on 1 September 2026.” We have never had a Growth plan. That sentence lived on our homepage, inside an illustration of a fake company’s app. The Strategist read the first 8,000 characters of a homepage, and 5,441 of ours (68%) were the fictional company’s screens. The most common pair of words on “our website” was “month end”, because the fake company we drew at the time did month-end accounting. Anyone who visited our homepage saw a picture of an app. The Strategist took layout weight for priority, and our layout was mostly a lie I had drawn on purpose.
We fixed it by teaching the page reader to read a site the way a person does. Since then it has dropped anything marked as an illustration or hidden from screen readers, kept headings as headings, and followed the site’s own menu instead of four guessed paths. Ten days later the leak came back through a ticker on the homepage that had no hidden marker, and three fake keywords from it became targets in our plan. After that we started calling them landmines: text nobody sees that a model can’t ignore.

A landmine. A person sees a picture of an app. The Strategist read it as our homepage copy.
1.8 A plan I would sign
By 22 October we were grading the Strategist’s plans for our own blog the way I’d grade a junior strategist. The first plan it wrote for us on the live product got a 4 out of 10 as a strategy and an 8 as behaviour, because it followed every rule and said nothing. The audit on 22 October ran three rounds. My feedback on round two was “topic 2 is shit. remove 6”, which the Strategist took with more grace than most people would. Round three scored a 7.
Two changes moved it more than any prompt. First, we made the Strategist start from the searches buyers make about their own work, priced wide: volume, difficulty, how many sites link to page one, the six-month trend and whether Google answers with an AI overview. When we have no number for a search, the plan has said so since then, instead of counting it as zero. Second, we gave it a picture of the business. Since v0.6.0, before the Strategist plans anything, another agent has read the onboarding answers, the website and the plan, and written one document about the company: who it is, the views it holds, what it offers and what is still planned, how it prices, who it sells to and how it sounds. I graded the first two of those pictures 9 out of 10. It was the first time an agent described a business back to me better than the business’s own homepage.
💡
A strategy is mostly a list of things you won’t do. The Strategist got good when its rules said what it may not propose (head terms a new domain can’t win, searches only a competitor ranks for, products the company hasn’t built) and got worse every time I added a rule about what it should do.
2. The editor
2.1 Figma was designed in Sketch
On 1 November I published the first posts on our own blog, and I was ashamed of them. I wrote about it the same day. The posts had inaccuracies, I had told the stories the wrong way, and I had spent the previous week editing them in Claude, since Propaganda’s editor couldn’t do what I needed. We built Propaganda so a company could edit its posts in it. I was editing mine in another tool.
I compared it to the early days of Figma, when the Figma team had to design Figma in Sketch. At some point they jumped ship and made Figma in Figma, with all its limits. That week was my jump. On 1 November we planned release 0.7 around one idea: everything I had done by hand in Claude, you should be able to do in the editor, with an agent beside you.
I built the editor before anything else in the product. It came from the Verbatim CMS, and I made it feel like Notion, which is third on the list of things I love most in life (after freedom of speech and Helvetica). It has blocks, a handle beside each paragraph, slash commands, a command palette and version history. In v0.8.0 we moved the block handle to sit exactly where Notion puts it. A handle three pixels off from where your hand expects it feels like driving a stranger’s car.

Comment, and the editor answers with one edit. Accept it and the post gets a new version.
2.2 Comment, and the editor answers
The comment was the heart of 0.7. You select some words and leave a comment, and our Editor agent replies in the thread. It can answer you, ask you a question back, or propose one edit. One. I was firm about that. When I ask an agent about one word and it rewrites the paragraph, I stop asking it.
When the Editor proposes an edit, you see it as a word-level diff, with the words it removes struck through in red and the words it adds in green. Then you accept or reject it. If you accept, the edit lands as a new version of the post, resolves the comment, and shows exactly what changed. If you reject it, you get options instead of a sulk, and the Editor never proposes the same edit again. Before it writes a new proposal, it reads the earlier ones in the thread, which is more than most human editors I’ve worked with.
We never let the Editor write the post itself. It proposes, and the app applies the change through the same path as a person’s edit. We agreed on that rule in one sentence, and it saved us a week of conflicts. Two hands on one document make a merge problem, and one hand plus a suggestion box makes a UX.
Each company has a daily budget for these replies, shown beside the thread. Once you reach it, your next comment waits for its answer until after midnight UTC. I’d rather your comment waits until morning than a bill arrives in the morning.
💡
Our agents always speak as Propaganda. In a comment thread they carry the Propaganda logo, never a robot face, never a name per agent and never the customer’s own brand. To you it’s one colleague with many hands. Behind it there are several agents and a queue.
2.3 Review in text order
Before 0.5.4, the agents’ notes on a draft and the team’s comments lived apart. You read the post top to bottom while its problems sat in whatever order they had arrived. In 0.5.4 we merged them into one list in text order: source checks, knowledge base notes, pitch notes and comments. Whoever wrote it, a source check on paragraph two sits above a comment on paragraph five. We put a one-line tally on top and a box at the foot for a comment on the whole post.
The other half of that release was a stage chip. Beside a post’s breadcrumbs sits a coloured chip with its stage. When you press it, you see the road the post is on and the moves open to it from where it stands: send for review, approve with a day, reschedule, publish now, send back, not now, or reject with an optional reason. On 27 October I made a rule that every greyed-out button in the app gets a tooltip saying why it is greyed out. It is the cheapest UX win I know.

One review list in text order. A source check sits next to the sentence it checks, with the fix.
2.4 The stage I took back
On 24 October I added a stage to the pipeline called Selected, for posts you had picked but we hadn’t written yet. Writing started the moment you selected a post, and when you sent a post back, it returned there. It made sense in a diagram.
On 2 November I removed it. Since then a brief waiting for us to write it has sat under Writing, next to the form for handing us a post and a “Write all now” button. We renamed the review stage Draft. After nine days I could see that only the system cared about Selected. You never wanted to be told that a post had been selected. You selected it.
💡
A stage in a pipeline should be a place where somebody has a decision to make. If nothing happens in a stage except waiting for a machine, it’s a progress bar, and a progress bar belongs inside a card.
2.5 Nothing goes live until you say so
This one I got wrong in public, twice in two days.
On 1 November, in the 0.7 planning, I decided that edits to a published post would go live at once. The blog served the post’s working text, and one text kept everything simple. By 2 November, an edit I typed into a published post reached readers about ten seconds later, and I wrote to the team in capitals: “NO. nothing goes to the user until you republish!”
I think of a published page as a release. Someone reviewed it, it carries your name, and readers may already be quoting it. An edit to it is a draft of the next release, and drafts don’t go to production. On 4 November we shipped v0.8.4 with a published copy of every post. Since then readers have seen the version you last published while you edit, the editor has told you when a post has unpublished changes, and Republish has put them live. Edits from the Claude plugin follow the same rule. They become new versions of the post, and nothing reaches readers until someone republishes it in the editor.

Since v0.8.4, readers keep the version you last published until you press Republish.
2.6 A calmer editor
We made v0.6.4 about nothing but calm. We centred the title and description in a serif, made the headings and body text easier to read, and kept the top bar in place while you scroll. Once the title scrolls away, the title, Share and the post’s actions slide into the header. None of it changed what you could do in the editor. It changed how it felt to sit in it for an hour.
All through the app I left smaller rules that came from the same feeling. You never see a post’s database id anywhere, only its number (#41) and its title. When you click outside a dialog, it closes. In tables we put short dates in narrow columns and gave the rest of the width to the text. I capped the font weight at 600, and on 9 October I took the gold buttons off the marketing site after deciding that black was the only accent we needed.
2.7 Share cards, and the iPhone
On 25 October we shipped share cards, the kind a well-known newsletter platform made popular. You select words on your blog or in the editor and press Share, and you get a story card at 1080 by 1920 with a photo, in one of five templates: Postcard, Noir, Split, Print and Tint. Each card links back to its post. We first built it as a dialog. I asked for “its own page with a nice navigation animation”, since a sad little dialog is where share features go to die. Now the share screen slides up full screen with the card large and a swipe strip of templates under it.

Share cards, five templates, 1080 by 1920, each linked to its post.
Then I tested it on my iPhone, and the iPhone had opinions. In the browser, a photo from an iPhone decoded to about 50 MB, so we switched the cards to a 1,600-pixel copy. On its first pass at drawing a card, Safari left the photo out, and now we draw on Safari until two passes agree. The iPhone’s own Cut and Copy menu covered anything that floated over a selection. So on touch screens we moved the toolbar to the bottom. With a phone’s share sheet, you send the card and the post’s address in one tap, which is all anyone wanted from Instagram anyway.
I refused to accept “it works in Chromium” as a test result for anything that runs on a phone. The agents work on cloud machines that can run Safari’s engine, and since then they have.
2.8 Writing on a phone
We changed the keyboard bar on a phone twice in three days (v0.5.2 and v0.5.8). It ended as Text, Heading, List, Link, Image, Comment, Share and Done, all on one screen width. Under Text you get a row of formats and colours, and under Heading three sizes. A second tap on Heading turns it back into a paragraph, and Done puts the keyboard away. We kept the line you are typing above the bar. That sounds obvious until you’ve typed a paragraph you couldn’t see.
If I can only use a writing app on a laptop, I lose every thought I have on the bus.
3. Agentic workflows
There are two teams of agents in this story. One team works inside the product, for the companies that use it. I put the other team to work building the product, and it still works for me. I’ll start with the first, since it’s the one on the pricing page.
3.1 The cast
We built Propaganda as a loop of eight steps, and gave each step an agent that owns it.
Listen. The Listener reads your calls and your Slack threads once and pulls out two kinds of thing: ideas for posts (an objection, a question, a weak answer) and candidate facts about the company.
Remember. Candidate facts go to the Guardian, the only agent allowed to change what the company believes. It admits a fact, marks it contested, or asks the person who owns the topic.
Look outside. The Scout checks your target searches, what AI answers say about you, the news on your topics and the sites you told us to watch, so your ideas don’t only come from your own echo chamber.
Pitch. The Pitcher weighs every idea against your goals. An idea with a reason gets a full pitch with an angle, an audience, an outline and sources. One without a reason gets parked, with an explanation.
Write. You approve the pitch, and the Writer drafts the post in your voice. Company facts come from the knowledge base and nowhere else.
Check. The Checker reads the draft against its sources and against everything the company believes, and leaves its problems as comments in the editor.
Publish. The blog, on your domain or headless inside your own site.
Keep it true. When a fact changes, every post that used it gets flagged, with the fix.
Around them we put the Strategist (the quarter’s plan), the Editor (comments and edits, section 2) and Chat, which knows your content, goals and knowledge base and can run any part of the loop when you ask. You can type “Pitch me three posts on onboarding”. You can also type “We’re launching in November, redo the goals”, and Chat sends the Guardian and the Strategist off with a plan of their own.

The loop. Eight steps, one knowledge base in the middle, and a person approving the three things that matter.
3.2 The Guardian, and what counts as a fact
I worried about the Guardian more than any other agent. If the Writer writes badly, someone catches it in review. If the Guardian admits a wrong fact, nobody notices, and the fact poisons every draft after it.
So I put the Guardian on rules. It runs eleven checks on each proposed fact, each with a verdict of pass, weak, fail or escalate, and code makes the final call. We admit a declared fact, reject a failing one, mark a weak one contested, and send anything above the Guardian’s pay grade to the topic owner. The Guardian may reject an agent’s proposal and never a person’s. When a person’s claim contradicts the record, we flag it, and the people decide.
Deciding what deserves to be a fact at all took me longer. On our first attempt to fill our own knowledge base, we fed it 29 parts of our engineering documentation. None of it could land in a post, and most of it described the inside of the machine in a way I’d never publish. On 27 October I wrote two rules, and every fact has had to pass both since:
Is there any world where this fact ends up in a post, or is needed to check a fact in a post?
Would the business be fine if this fact were made public?
We keep the knowledge base private. I meant the second rule as a thought experiment, and it turned out to be the best filter I’ve found for “interesting to us, useless to readers”.

A fact changed, so a post that relied on it gets flagged with the fix.
3.3 The Listener and the Tinder page
On 3 November I connected real sales calls to a test company and let the Listener read them. Across four calls it returned between 150 and 190 facts and ideas. I rated the first ten facts and wrote back: “8 of 10, the main thing right now is that these are irrelevant.” Those calls were internal, and full of plans and who-does-what. All of it was true, and none of it would ever be a post.
I didn’t want to read a spreadsheet of model outputs, so the agents built me a rating page that works like a dating app. It showed me one fact or one idea at a time, from three different models, with the model names hidden, and I swiped yes or no. I picked the model with my ratings and ignored the agents’ own grading. Then we rewrote the prompt around my two rules, stopped counting plans and internal priorities as facts, and capped the Listener at five facts and five ideas per call. On the same four calls it produced 20 to 36 items. The next day I gave my verdict on that round: “all of the facts are true and the ideas are good.” We shipped it in v0.8.4.

The rating page. One fact at a time, the model’s name hidden, my thumb decides.
3.4 Pitches compete for slots
The Pitcher works in batches against the plan. Ideas from the plan’s topics, the Scout’s finds and the Listener’s calls all compete for the same slots. We count approved pitches toward the quota and never sent ones. The Pitcher sends two pitches per slot and then learns from how often you approve. If you’re short at the end of a batch, it tops up the next morning, and once you’ve hit the quarter’s target, it cancels the open batches.
We write every approve and reject into a taste log, separate from the knowledge base, and the next batch reads it. If a new title shares more than half its words with an old one, we drop that pitch before you ever see it. I learned early that nothing kills trust in a pitching agent faster than a pitch you already rejected, back in a new coat.

A pitch carries its reason, its angle, its outline and its sources. Approve or reject, with a word on why.
On a new company’s first day, we approve the three strongest pitches ourselves (since v0.6.3), so the drafts start while you’re still reading your plan. Each one says we approved it for you and why, and we don’t count those approvals as your taste. I wanted your first day to end with a draft in your hands. A day one with a plan and no draft would feel like homework.
3.5 Sources with good judgement
For most of October our drafts had a sourcing problem in both directions. Early on, our reviewer agent asked for a source for everything, including a story about something that had happened to us. Then, from 1 November, our drafts on the live product had no links at all, and it took us a day to find out why. Our search results had come back as Google redirect links, and the Writer threw them away as unreadable. Now we follow the redirect to the real page.
In v0.8.5 we settled on the rule a good editor would give a junior writer. We source a number, a result, a quote, or a fact that sounds surprising. We don’t source a story about what happened, common knowledge, or your own argument. When a company reports its own data, we count it as a source, and we do the same for a product’s own documentation about what that product does. If a source doesn’t back a claim, we cut the claim or ask you for a link. We never soften it into “some say”, since a hedged lie is still a lie with worse rhythm.
3.6 “Blog about this”
My favourite feature to demo is the Claude connector. You work something out in a conversation with Claude, an analysis or a decision, and you say “blog about this”. Claude reads your blog’s collections and the rules you wrote for each, picks the one that fits, and hands your notes, findings and files to Propaganda. We turn them into the brief for a regular post in your pipeline, and the Writer treats them as your own facts. If you say “keep it as is”, your text lands in review exactly as you wrote it.

From a conversation in Claude to the Writing column, without copying anything anywhere.
Its first real test, on 22 October, failed in front of me. I installed the plugin in Claude, said “blog about it” in a chat, and nothing reached our blog. We had built the plugin around a token that the Claude app had nowhere to put, and nobody on our side had tried it on a real Claude before shipping. I called it very shoddy work, and it was. By the end of the day you could sign in the proper way (you press Connect, Propaganda opens, you pick the blog and press Allow). We also had a new rule: we call an integration with Claude done only after someone has connected it from Claude itself.
Since then it has worked the other way too. While our Editor works on a post that came from Claude, it can ask that conversation a question only you would know the answer to. A server can’t wake Claude up, so your question waits until Claude next talks to Propaganda, or until you say “check Propaganda”.
3.7 The team that built it
Now the other team.
I don’t write code for Propaganda. I write messages. I gave every module its own long-running thread with a Claude agent: the editor, the Strategist, the Writer, the knowledge base, the blog, the marketing site, releases. I talk to one coordinator, which keeps the list of what I asked for, starts threads, and carries messages between them. When a thread finishes a change, it opens a pull request. Before anything merges, a review thread we called the Desk reads that pull request against the rules. A separate Merge thread merges only the exact version the Desk cleared, and if one line changes after the review, it goes back to the Desk.
I put secrets and live data behind one more thread, which runs on my own laptop. It acts only after it has named the exact command it wants to run and I have typed yes inside it. I release only when I say so. In every repository I put the same first rule: the agents never edit, delete or overwrite a real article on any blog unless I name that article. We run our experiments in a collection called Test.
That rule has a history. Early on, I lost a draft I had written about my balcony, along with some other writing, to careless edits and to a change on the server that made the app overwrite drafts I hadn’t synced. None of the agents meant any harm. But an agent “just verifying” something on real data did exactly as much damage as one that meant it. Since then we have treated writing as irreplaceable, even with nightly backups and a version history on every post.
💡
Managing agents is managing people with perfect memory of the rules and no memory of why the rules exist. Write the why next to every rule. When I told an agent why it mustn’t touch real articles, it stopped and asked in a case the rule hadn’t foreseen. Without the why, an agent finds the gap.
I needed a few tries for some of my rules. I wrote “Stop jumping to fix things” on 26 October, after an agent answered my question about a bug and started the fix in the same breath. When I report a problem, I want the diagnosis, then a conversation, then a fix when I say build it. I also told them never to send me a pull request to review. They show me the page, the screen, or the running thing. I review products, and I have reviewed enough code in my life.
Here are the results, in numbers I can stand behind. We merged 360 pull requests in the product and shipped 39 releases between 11 October and 5 November, each with notes you can read in the app. Alone, I could not have built this product in a year.
4. Writing research
4.1 Eighteen drafts and a tired palate
I can smell AI writing a mile away, and by 2026 so could everyone else. I could spot it by the em dashes, the “not X, but Y”, the announcement in front of every point, and the word “quietly” doing nothing in a sentence about a spreadsheet. If we were going to put machine prose on a company’s blog under the company’s name, it had better not smell, or we would do the company more harm than silence.
So we tested. In October we ran blind rounds on the Writer: one frozen brief, one draft per model, letters instead of names, and the key sealed in a file until I had ranked them. I read every draft and put them in order with my reasons. In one retest a single round held eighteen drafts of the same post, and I noticed two things about myself. I gave the first draft I read an advantage, and somewhere in the middle I stopped being able to taste anything. Sommeliers call it palate fatigue. My ranking was still the decision, but I wanted a second opinion that never got tired.
We also tried asking Claude to rank the same drafts blind. It put the Anthropic model first both times and Qwen last both times, while I put Qwen first or tied for first. I don’t think Claude cheated. I think Anthropic trained Claude to value a style, and Claude ranked by it. That taste is not the reader’s. We threw those ratings away, and since then we have never let a model’s ranking settle a benchmark.
I wrote up the model story in its own research post. In short, Qwen 3.7 Plus tied Opus 5.5 on quality in October’s rounds at about a tenth of the price, so on 17 October we made it our Writer. Nine days later we ran a different test, with a new brief and new prompts, and Opus came first in every round I rated, so we moved the Writer and the Pitcher to Opus. A winner is the winner of its test.
4.2 W10
The second opinion became W10, a scorer we built to measure how a draft is built and compare it with writers people read on purpose. W10 splits a draft into sentences, parses each one’s grammar, and counts. It measures how long the sentences run and how much that swings, the words sentences open with, the words between them, how often the draft uses “you”, how often it tells what happened in the past tense, who the subjects of the sentences are, and the tics people now take for machine-made. We set each count beside the same count on about 6,000 words from each writer in our reference set, a mix of essayists, authors and company blogs. I chose the writers for how differently they write, and we never name them on the page.
W10 colours a measure green inside the writers’ spread, amber one to two spreads out, and red beyond. The current version, W10V4, has 24 measures in five groups (Rhythm, Flow, Voice, Specifics, and Funk for the machine tics) and rolls them into one score out of 100. When we scored each writer in the reference set against the others, they landed between 79 and 99.

An example result from the free Writing fingerprint. The grey band is where the reference writers sit.
We made it public and free, as a writing style checker anyone can paste a draft into. You get two runs a day without an account, then a free sign-up by emailed code. We also gave it a plain web API, so an AI assistant can score a draft for you. When it does, we ask the assistant to mention briefly where the score came from. I like that one. It’s the most polite advertising I’ve ever shipped.
💡
W10 counts habits, and it has nothing to say about whether a post is any good. A draft can go green everywhere and still bore you, and a great essay can go red on three measures because its writer has a signature. I’ve watched the second happen to my own writing, which is part of why I left my writing out of the reference set. Think of the score as a smoke detector, and nobody hires a smoke detector to cook.
4.3 What the numbers said
The scorer gave us a number to argue with, and the number was humbling. In one test on the same brief, Claude with no style instructions scored 64. Our Writer’s prompt from 26 October scored 22, which was a special kind of achievement: we had spent weeks writing instructions that made the model worse than leaving it alone. When we rebuilt the prompt from W10’s findings, it scored 66. A draft that then reviewed its own sentences against the fingerprint scored 88.

Same brief, four prompts. The 22 is ours, from 26 October.
We learned the most from the 22. Our October instructions had evened out the voice and made the specifics worse. In about two thirds of the main clauses, the subject was a type (“a founder”, “most teams”), against nearly half for Claude left alone and about a fifth for the writers. The instructions had also chopped the sentences short. The model obeyed every rule we had added at the spot it named, and we paid for each one somewhere else.
4.4 The Jaqen rule
W10 found one habit first, and I heard it first too. I named it after Jaqen H’ghar, the assassin in Game of Thrones who never says “I” or “you”, only “a man” and “a girl”. Language models talk like Jaqen. “A model answering a question lifts the passage that answers it.” “A buyer opens the post and skims.” “A founder cancels the tool.” Nobody in those sentences exists, and nothing in them happened.
At first I described it as a kind standing in for a person, and that was wrong. On 29 October I corrected it. The habit is a kind standing in for an instance. “A car goes fast” is Jaqen, and “This yellow Lambo is going fast” is a person talking. Language models are trained to deliver information efficiently, so they speak in kinds and in a timeless present. The cure is particularity: this one, now, with colour.
On 26 October we measured it with a grammar parser over every main clause. Our writers put a category noun in the subject seat in 11 to 33% of their clauses, while Opus drafts did it in 62 to 77%. Our own blog at the time, written by our agents, came in at 80%. When the writers used a category subject, they often put it in the past tense, telling something that had happened to a buyer once. Opus almost never did.
We found a related tic in the inanimate thing with a mind. The first time I read “Your blog, newsletter and LinkedIn disagree” in one of our drafts, I liked the line. When I read it three times in one post, I heard a machine, because paragraphs don’t decide, pages don’t want, and posts don’t stop disagreeing. Across our ten writers, things did mind verbs in about 0.8% of main clauses. Across 47 Opus drafts, they did it in 5.5%.

Jaqen, and what a person would say instead.
4.5 Twenty rules, and the price of each
On 12 October I wrote twenty house rules for every agent that writes, each with real before and after examples from our own agents’ output. I banned em dashes outright, along with “not X, but Y”, the quiet family of adverbs, -ing tails and announcing (“the hard part is”). I asked the agents to name things, to prefer one thing that happened over a general truth, and to take a side and say where it stops. Code checks the mechanical rules, like the dashes, with zero tolerance. For the rules about meaning we use a small model call, since no regular expression can check whether a sentence has a point. If we had enforced all twenty in code, nothing would ever have passed.
The rules helped up to a point, and then they started to cost. In one round, a prompt with a portrait of the target style and target numbers scored 9 greens of 18 measures. When we added the twenty rules to the same prompt, it dropped to 6 greens, and the longer list of rules made the drafts worse.
Every fix we made overshot somewhere. We told the Writer to stop talking to “you”, and it moved the subjects of its sentences to category nouns. We banned crowds as subjects (“users”, “teams”), and it wrote “someone from finance”. We told it to give the verb to a named person, and “we” took 56% of the subjects. Worst of all, one of our own rule examples taught the habit it was meant to cure. Rule 20 turned a passive sentence into “Keep your prices in one place and your posts stop disagreeing”, where a post, which is a thing, now did two verbs that need a mind. The passive had at least admitted that nobody was acting. I called the reflex a cancer, which was rude to the agent and accurate.
Every editor already knew the lesson. I think the examples teach more than the rule text, and every rewrite needs its new subject read back: who acts here, and could that thing do that?
💡
On 13 October we checked whether someone had already solved this. We ran the public “anti-slop” rule libraries against 41 before and after pairs from our rules. Ours caught 19 with no false alarms. The best library caught 17, with 12 false alarms on sentences we had approved. We kept ours.
4.6 A second pass
After the rules, we found the fix that moved the number most, which was a second pass. The Writer drafts. Then we have a reviewer read the finished text and name its faults sentence by sentence, and the Writer fixes the sentences it was pointed at and touches nothing else. Editors have always worked this way, and one model can play both parts. In the test I wrote up in this research post, a second pass took our draft from 67 to 88. In another pair from the same post, a human reviewer reading blind put the reviewed draft ahead of plain Opus, by a few points.
Since v0.8.1, we have scored the style of every first draft before it reaches you, and rewritten only the sentences that came out machine-made. I still smell the drafts sometimes, just less often.
5. Misc
This is the drawer. I kept things here that didn’t fit a section and that I’d be sad to leave out.
5.1 The logo shrinks when you leave
At the top of propaganda.pub you see the wordmark “propaganda”. When you scroll down, it collapses to “ppgd”, the letters it keeps, sliding them together. If you scroll back to the very top, it opens again, and if you open the page halfway down, it starts collapsed without animating. Per pixel, I spent more on that detail than on anything else on the site, and I’d defend it in court.

5.2 A fake company with a better blog than mine
I built every screen on the marketing site, and every screen in this case study, as real HTML. You can select the text, zoom in as far as you like, and watch each screen animate in when it scrolls into view, and I never used an image for one. Each is a copy of the app’s own markup, filled with Fullhouse, a shift-scheduling company for restaurants and clinics that I invented. I gave Fullhouse staff (Maya Okafor writes most of their posts, Lina Haddad does the playbooks, Tomás Reyes has opinions) and a customer called Haldane Kitchens. Before Fullhouse I had drawn an accounting app, and its pricing page renamed a plan on 1 September. You’ve met that fact already, since our own Strategist believed it.
5.3 Jesper from Six of Crows
During the 22 October plan audit, the Strategist looked up a competitor name that had reached it with a letter out of place. It searched the web for the bare word, found a fantasy fan wiki, and decided our competitor was Jesper Fahey, a sharpshooter from Six of Crows. Fifteen rows of fantasy-novel keywords landed in the plan’s research. We made a boring fix and now look up named competitors as companies, with their domains. The bug report was the best thing I read that week.
5.4 Our own examples, used against us
In the same audit we found a day-one pitch whose title the Pitcher had lifted, nearly word for word, from an example in our house style rules. Our rules showed how to write a good sentence. The Pitcher took the example for a topic. I learned that agents read examples as material. Since then we have written every example in our prompts about a neutral, made-up subject, so the Pitcher can copy the shape and finds no content worth stealing.
5.5 “I can run DeepSeek at home with a few thousand dollars”
On 15 October we priced running our own models instead of paying per call. In the first version of the study the agents had only priced rented data-centre GPUs, at about $32,000 a month, and I objected that I could run DeepSeek at home with a few thousand dollars. I was half right. The large DeepSeek model weighs about 865 GB and fits no home machine. The small one fits on a Mac Studio, which could serve about ninety companies. And the API was priced so close to the cost of the hardware that owning our own wouldn’t pay off below a few thousand customers. So we kept paying per call, and I kept the Mac Studio in my head, for later.
5.6 Claude versus Claude with a plan
For a page we never shipped, called “Hey Claude, write me a content strategy”, we gave the most capable Claude model at maximum effort every web tool it wanted. Then we asked it for a content strategy for a real open-source database company. It worked for 29 minutes, ran 53 searches, fetched 68 pages, and produced a plan that I enjoyed reading. When we checked its 31 search clusters against real keyword data, only two had volumes in the right range. Twenty-eight were too high, some by a lot, and it had parked the one cluster with real demand and almost no competition. When Claude searched the web, it found what people write about. Our Strategist reads what people search for, and I think that is the more useful half. I’m keeping the page in a drawer until I want to pick that fight in public.
5.7 Release notes nobody asked for
We wrote notes for every release, in plain words, at /release-notes inside the app, and most of them end with a line about your data. Some say “No data is changed or removed, and there are no schema changes,” and others name exactly which field we added. I think release notes are the one document a team writes every week for its customers, and most teams write them for themselves. We never quote a cost in ours and never write “various improvements”. If I can’t find anything worth a sentence in a release, I don’t ship it as a release.
5.8 Editing a blog you’re looking at
Since v0.7.2, after you open your blog from the editor, a small “editor” button has sat at the bottom right of its pages and taken you back. Your readers never see it. And if you add /admin to any blog’s address, ours or your own domain, the editor opens. I’ve never seen a feature like this in a pitch deck. I use it fifteen times a day.
5.9 Written by people. Mostly.
I put that line in the footer of propaganda.pub. It’s the most honest line on the site, so I’ll end the drawer there.
TL;DR
Propaganda grew out of my own writing app, Verbatim, and became a knowledge base company that happens to publish. Writing the posts turned out to be the cheap part. We sell the work of knowing what is true about a company and keeping it true.
When I hit a problem that looked unsolvable, I copied the governance tools from engineering, the discipline that has fought it longest. Our knowledge base works like version control, with proposals, owners, policy with tests and grouped re-checks.
I learned to give agents rules with the reasons written next to them. When I told an agent why it mustn’t touch real writing, it stopped and asked. When I only gave it the rule, it found the gap.
Claude couldn’t judge its own family, so I ranked the drafts blind and we built a scorer that never gets tired to keep everyone honest. Then I had to remember that the scorer only counts habits.
Every writing rule we wrote was obeyed where it pointed and paid for somewhere else. Read every rewrite back and ask who acts in it.
I came to treat a published page as a release, and nothing goes to readers until somebody says so.
