I Built the Anti-LinkedIn — An AI Platform That Rewards Honesty, Roasts Braggarts, and Turns Your Workplace Chaos Into a Podcast

Community Article
Published June 14, 2026

What happens when you point two agentic systems at the most underrepresented genre of human experience: the truth about work.


Let me describe the problem first.

Every platform for professional communication is architecturally optimized for one thing: the performance of success. LinkedIn rewards achievement announcements. Resumes reward achievement. Performance reviews reward achievement. The entire infrastructure of professional self-expression is a monument to the curated self — the highlight reel, the humble brag, the carefully worded post that makes it sound like you're thriving even when you are, demonstrably, not.

And in the gaps between all of that performance: nothing. No platform. No outlet. No acknowledgment that the meeting lasted three hours when it was scheduled for thirty minutes, that the "quick sync" was neither quick nor a sync, that the company all-hands made you want to change careers and possibly continents.

I built feelin' to fill that gap. It's a real-time workplace confession platform with an AI agent that scores your suffering, a leaderboard of the most painfully relatable posts, and a podcast system that turns the top confessions into narrated audio episodes — complete with sound effects, host personalities, and the kind of editorial voice that LinkedIn will never, ever have.


The Concept

feelin' has three parts.

Confess is where you post. Anonymous, 280 characters, no account required. You write what actually happened today. The AI reads it.

The Leaderboard is where the best posts go. Five categories: 😂 hilarious, 😢 tragic, 😤 unhinged, 😬 awkward, 🤯 chaotic. Each confession gets scored 0–10 across all five simultaneously — not as a distribution, not as a single label — because a post can be both tragic and hilarious at the same time, and it deserves to appear on both leaderboards.

The Podcast is where things get weird. The top-scoring posts in each category get narrated by AI hosts with fully-developed personalities. Dave runs The Weekly Wheeze — 42, raspy, laughs mid-sentence, comedy energy. Elena runs Corporate Tears — 31, soft, melancholic, grieves with you. Marcus runs Officially Unhinged — 55, baritone, barely-contained rage. Priya hosts Please Stop Talking — 27, fast talker, nervous giggle, second-hand cringe. Rex hosts Total System Failure — age unknown, manic, routinely breaks the fourth wall.

Episodes are generated on demand: the LLM writes a full script in character, a TTS engine synthesizes each segment, and pydub mixes it all together with real .wav sound effects — laugh tracks, violin stings, thunder, dial-up modem noise, glass breaking.

The result is a podcast nobody asked for and everybody who's ever had a job needs.


The Architecture

feelin' runs on HuggingFace Spaces as two servers sharing one process:

  • A Gradio UI on port 7860, handling the three-tab interface
  • A FastAPI backend on port 8000, started as a daemon thread when the app boots

The UI layer is intentionally thin — just requests calls to the local API. All logic lives in the backend. The backend has seven endpoints: submit post, leaderboard by category, leaderboard all categories, generate podcast (async), get podcast, stats, and health check. Static podcast files are served via FastAPI's StaticFiles mount.

SQLite is the database, with WAL (Write-Ahead Logging) mode enabled. This matters: when a podcast is being generated in the background — a process that writes TTS segments, mixes audio, and saves the final file — FastAPI still needs to serve leaderboard reads concurrently. WAL mode makes that work without locking.

architecture


The Two Agentic Pipelines

This is the part I want to spend time on, because it's where the project becomes technically interesting.

Pipeline 1: The Post Agent

Every confession triggers a stateful processing pipeline. The state is a FeelState TypedDict that carries everything — post text, post ID, brag flags, emotion scores, rank, response — from node to node:

class FeelState(TypedDict):
    post_text: str
    post_id: str
    is_brag: bool
    brag_roast: str
    scores: dict
    top_category: str
    top_score: float
    reaction: str
    response_message: str
    response_type: str

The pipeline flows through five nodes:

agent1

node_submit_post         → writes to DB, gets UUID
node_detect_bragging     → calls detect_bragging() tool
    │
   [is_brag AND confidence > 0.6?]
    YES → node_flagged   → writes flag, returns roast
    NO  → node_classify  → calls classify_emotion() tool
              ↓
          node_update_leaderboard → writes five scores, computes rank
              ↓
          node_compose_response   → builds markdown verdict

The two LLM tools at the heart of this pipeline are worth examining.

detect_bragging(text) is a zero-shot classifier briefed on the full taxonomy of LinkedIn energy. The system prompt defines specific constructions to flag: achievement announcements, "humbled and honored" energy, "I've been selected…" openings, revenue and metric flexing, award acceptances, prestigious name-dropping. It returns {is_brag, confidence, roast}.

The confidence threshold is 0.6. This is a deliberate design choice: the detector doesn't punish ambiguity. Someone can mention their promotion in the context of explaining why their life has gotten worse — that's not a brag, that's context. The agent only fires the rejection path when it's sure.

When it does fire, it doesn't just reject. It roasts. The roast field is a short, sharp response in the voice of someone who has consumed too much LinkedIn content and has finally had enough:

"LinkedIn called. They want their energy back."
"The humble-to-brag ratio here is clinically concerning."
"Congratulations! You've been selected as today's example of what this platform is not."

classify_emotion(text) scores the post across all five categories simultaneously. The prompt asks the model to treat the categories as independent dimensions, not a distribution. A single post can score 8.7 in hilarious and 7.2 in tragic simultaneously — the meeting-cancelled-five-times story lands differently depending on what you're looking for. The model also generates a one-line coworker reaction: what would someone DM you if they read this post?

The response goes back to the user as a markdown verdict: category, score, score bar, rank in that category, the coworker reaction, a breakdown of all five scores, and — if the score is above 7.0 — a note that the host of the relevant podcast might be reading this soon.

Pipeline 2: The Podcast Agent

The podcast pipeline runs differently. It's triggered via a FastAPI BackgroundTask — the user hits a button, gets a 200 immediately, and the system works in the background. The UI polls for status.

agent2

1. get_top_posts_for_podcast(category, limit=10)
       only posts scoring ≥ 5.0 pass the quality gate

2. build_podcast_script(category, posts)
       LLM writes in character, with ---SECTION--- delimiters
       and inline emotion tags throughout

3. parse_script(script)
       {"INTRO": "...", "POST_1": "...", ..., "OUTRO": "..."}

4. For each section:
       strip_emotion_tags(text)    → clean TTS text
       synthesize_segment(...)     → WAV/MP3 bytes
       cache by MD5(category+text) → skip unchanged sections on re-runs

5. mix_episode(sections, paths, category)
       normalize segments to -20 dBFS
       detect emotion tags in raw text → inject .wav SFX
       750ms silence between sections, 350ms around SFX
       export 128kbps MP3

6. save_podcast() → SQLite

The most interesting design here is the dual-role emotion tag system.

The LLM writes scripts with tags embedded: <laugh/>, <sigh/>, <gasp/>, <cry/>, <pause ms="500"/>, <whisper>text</whisper>, <shout>text</shout>. When a section is prepared for TTS synthesis, strip_emotion_tags() converts these to natural spoken equivalents:

"<laugh/>""ha,"
"<sigh/>""..."
"<gasp/>""oh!"

The TTS engine hears natural speech, not XML. But the raw tagged text is preserved separately. The episode mixer scans it for <laugh/>, <gasp/>, <sigh/> to decide where to inject actual .wav sound effects at -24 dBFS.

One tag. Two jobs. The same instruction that shapes the voice performance also triggers the sound design.

The segment caching matters more than it might seem. An episode for the hilarious category might have 12 sections — intro, 10 post commentaries, outro. If the top 10 hilarious posts haven't changed since the last generation, none of those segments need to be re-synthesized. The mixer just remixes existing cached WAV files. At TTS API rates, that's a meaningful cost and latency saving.


The TTS Stack

feelin' doesn't lock you into one TTS system. There are four backends, selectable by environment variable:

Hybrid local and through HuggingFace InferenceClient calls openbmb/VoxCPM2 ,ResembleAI/chatterbox

VoxCPM2 runs locally and uses voice design mode — you prepend a natural language description to the synthesis text: (A raspy 42-year-old man with warm comedic energy who laughs easily)Dave's opening line.... The model uses the description to shape the voice. Each podcast host has a description mapped to their persona.

Chatterbox Turbo also runs locally and supports reference audio for voice cloning. If you have a .wav file that sounds like your mental image of Marcus — 55, baritone, barely-contained rage — you can clone it.


What Makes This Actually Interesting

feelin' is, on the surface, a confession platform. But it's built around a specific argument about what AI agents are good for.

Most AI applications put the model at the center: you talk to the AI, the AI responds. feelin' puts the human experience at the center and uses the AI as infrastructure. The agent doesn't generate the content — the users do. The agent reads it, classifies it, ranks it, and transforms it into a different format (audio). The model's job is interpretation and amplification, not creation.

The brag detection system is the purest expression of this. It's not trying to generate content — it's trying to enforce a social norm. It has an opinion about what belongs on this platform, and it expresses that opinion with a roast when something violates it. The LLM becomes a gatekeeper with a personality.

The podcast system is the other end of that spectrum: the model as author, writing in character, generating something the user can listen to. But even there, the source material — the raw confessions, the human frustration — is what makes the episode worth hearing. The model is the frame. The humans are the content.

The leaderboard is the piece that makes it social. When you submit a post and see you're ranked #2 in unhinged, you're not just venting — you're participating in a collective taxonomy of professional suffering. The scores make the chaos legible. The categories give people a shared vocabulary: "that's a 9.1 tragic situation" communicates something real.


What's Next

A few things I want to build:

Scheduled podcast generation — a cron job that generates a new episode for each category every 24 hours, so there's always fresh audio without manual triggering.

Voice cloning per host — recording five distinct reference voices and using Chatterbox or VoxCPM2 cloning to make each host actually sound like their character description.

Reaction system — letting people rate confessions with category-specific reactions rather than generic likes. A 😂 and a 😢 on the same post means something.

The LinkedIn mirror — a generated fake LinkedIn version of each confession, showing what it would look like if the person had posted it professionally. "Today I had a challenging alignment conversation with stakeholders about synchronous meeting cadence" vs. the original.


The code is on HuggingFace. The platform is live. If you've ever had a meeting that should have been an email, or a "quick touch base" that became your entire afternoon, or a performance review that made you question the nature of reality — feelin' is for you.

Try feelin' →


Built with Gradio, FastAPI, Qwen3, Kokoro-82M / VoxCPM2 / Chatterbox Turbo, pydub, and a lot of firsthand research into the chaos of professional life.

Community

Sign up or log in to comment