Case study · 04 / 05 · 20263 min read
  • Python
  • LLM pipeline
  • Slack
  • Shipped

Customer Feedback Monitor

What if the product team never had to go looking for what customers were saying?

Where
Built on my own, in my own repo. Now transferred to a product team and running in production on a weekday schedule.
Role
Built it. Python, LLM pipeline, GitHub Actions
SEN-MO, the bot's avatar: an astromech droid with a sentiment readout on its dome, on a starfield
Read every weekdayOne team, one product

01What it is

An automated pipeline that watches customer feedback across the App Store, Google Play, Reddit, X, Facebook, Trustpilot and Google News, analyses and clusters it, and posts a digest to Slack every weekday morning. During a launch window it also runs hourly to catch app-breaking issues in real time.

02Why it belongs here

  1. 01Multi-source ingestion with fallback chains per source, so one dead API does not take the digest down
  2. 02LLM enrichment and clustering, so the output is themes rather than a wall of reviews
  3. 03A feedback loop: the team replies with commands in the Slack thread and the bot reconfigures itself
  4. 04Orchestrated on GitHub Actions with an external scheduler, so there is no server to babysit

A designer noticing that nobody reads the reviews, then building the thing that reads them, is the whole argument of this site in one project.

03How it runs

The pipeline: seven sources feed fetch, dedupe, LLM enrichment and clustering, which post a digest to Slack in three layers, pulse, detail and thread; a reply in the thread loops back into the config for the next run; the digest archive feeds a planning board downstream
Structure only. Every source has a fallback chain, dropped items stay in the day's source file so the exclusions can be audited, and a reply in the Slack thread changes the next run.

Nothing it read is shown here. The feedback belonged to the company and the bot now runs inside their team. The diagram above is the shape of it, and the digest below is that shape with invented numbers for an invented app.

04The digest

A sample morning digest as it renders in Slack: the bot's post with a one-sentence headline, today at a glance with counts against a usual day, sentiment breakdown bars, volume by platform, a seven-day net sentiment trend, then a negative, a positive and an app-breaking section, and three example thread commands
Sample data. The app, the numbers and the reviews are invented; the layout is the one that posted every weekday morning.

It does two jobs in one post. The top is a summary so the team can track how we are doing without reading anything: one headline, the day's counts against a usual day, sentiment, volume by platform, a seven-day trend. Under it is the detail, every item the summary was built from, urgent ones first, then by source, each with its link, its store and its version. The summary tells you whether today is normal. The detail is what you act on.

The team steers it from the thread. Reply with a command and the next run picks it up: which sources to mute, which area to focus on, whether to go hourly. Nobody has to open a config file to change what the bot does.

05From digest to board

The digest archive, one file per day, fed a kanban I built next. Every item is deduped across days, categorised as bug, enhancement, new feature, praise, venting or off-topic, given an area and a severity, then grouped by the squad that owns the area and sorted by a severity score so a PM reviews the most important first. Each theme card carries its raw evidence rows and their links, so the decision is made from the quotes rather than from my summary.

Statuses follow the review rather than the roadmap: unreviewed, discuss, ticketed, dismissed, and parked for feature asks that are out of scope for a bug pass. Praise and venting never become cards; they roll up per area on an overview tab, because a PM needs to know the mood without triaging it.