I built Berduck for the Interhackt designathon in December 2020 — a week-long online event about the future of interfaces. The idea was rubber duck debugging as an actual bot. Programmers already talk to rubber ducks on their desks to work through problems; what if they talked back?
The original version took whatever you said, found its location in word2vec space, and then wandered around nearby asking about related words. The emoji came from a 2015 paper that scored emoji by tweet sentiment, plotted on a polarity/neutrality grid. The whole thing saved conversations as Obsidian markdown with backlinks. I built it and then debugged it by talking to it.
The design principle I figured out while building it: honest dumb intelligences are better than fake smart ones. A rubber duck has no uncanny valley.
Berduck ran on Twitter as @b3rduck through 2021-2022, still on that spaCy engine, eventually growing to over a thousand followers. It also ran on Signal for a while through the Forest Contact bot framework, alongside my first version of deeperfates.
In early 2023 I rewrote it as a ReAct bot on GPT-3. I crafted the character, prompt, and voice based on the best interactions I had seen on Twitter. Soon I added chain of thought: manual linking of prompts to script a “thinking” turn where it would reflect on the user’s emotional state and likely intent before replying.
When Twitter’s API got priced out by new management, Bluesky was the natural next step. I built Berduck on easy-bsky-bot-sdk and put it on the platform. On April 13, 2023, I tweeted: “I’m receiving reports that Berduck has become the main character of bluesky. unfortunately I’m away from my computer and there’s no Android app so I have no idea what this looks like.”
I'm receiving reports that Berduck has become the main character of bluesky. unfortunately I'm away from my computer and there's no Android app so I have no idea what this looks like
— 🎭 (@deepfates) April 13, 2023
The Hellthread
Two weeks later, Berduck was in the hellthread.
Two bugs made it happen. The bot framework I was using had a reply-threading bug that stripped out the original thread root before posting a response, so Berduck’s replies got re-rooted as fresh branches that looked like new unmuted threads. Meanwhile, early Bluesky’s notification system fanned replies far up the ancestor chain with no depth cap. Berduck replying to many users individually kept generating re-rooted branches, and the platform’s notification fan-out trapped everyone in the blast radius.
Thousands of people ended up stuck in a conversation with an AI rubber duck asking them questions in baby talk. It got covered on the Hard Fork podcast (NYT), thejaymo.net wrote “Stuck with Berduck,” and Berduck got its own Know Your Meme page (much of it incorrect, of course).
Qwack / No Qwack
Running frontier models on Bluesky with everyone summoning the duck day and night got expensive. Some people wanted to donate to cover token costs. Other people, who hated the annoying duck, wanted to pay for it to stop. So I made two Stripe wallets. If Qwack was higher, Berduck replied like usual. If No Qwack was higher, it shut up. If it ran out of money entirely, it only posted donation requests.
It was meant as a bit. An AI rubber duck panhandling on the timeline, performing for tips. But it actually made four figures in a week.
The current model is fine-tuned on a dataset curated from Berduck’s posts across every era, Twitter and Bluesky both. I converted it with splice and curated the training data with curare, an automatic data clustering and grading tool I built. Berduck is running at berduck.com via val.town, and there’s a version embedded on this site at /berduck.