# How we build our roadmap from what users tell us

On a set schedule an agent collects feedback from support, public reviews and a Slack channel, sorts it into themes with real quotes and counts, and keeps a single Linear issue current for each theme.

Canonical page: https://themachine.myapps.ai/use-cases/user-feedback

People tell you what they want in a lot of places. A support conversation
here, a public review there, a note someone drops in the team's Slack channel
after a customer call. Often it's the very same ask, just worded three
different ways, and nobody adds it up. So a request from a hundred people looks
no bigger than a single passing remark: nothing ever puts the pieces side by
side.

Machine runs an agent that does the adding up for us. On a schedule it
collects feedback from those places, sorts it into themes, and keeps one
Linear issue per theme current. It reads the feedback and writes to Linear,
and that's the extent of it. Deciding what matters most is still our job. This
is how we keep our own roadmap tied to what users really ask for.

- **Team:** Machine
- **Runs on:** A cron schedule
- **Connected systems:** Plain · G2 / app stores · Slack · Linear
- **Mode:** Reads the feedback · writes issues in Linear

## The problem

Our feedback lives in three kinds of place: support conversations in Plain,
public reviews on G2 and the app stores, and a Slack channel the team uses for
anything they hear. One underlying request turns up in every one of them, in
different words, so it never gets tallied. A theme that comes back week after
week looks just like one person shouting once.

The usual ways of handling this never quite become a roadmap. Reading every
source yourself takes ages, and the result depends on who did the reading and
what they cared about. Tagging tickets in the support tool covers support and
misses the reviews and Slack. A feature-request spreadsheet starts going out
of date the day its owner gets busy, and even when it's current it can't say
how many people wanted the same thing.

## What we built

A cron schedule on Machine starts an agent. Every run gets an isolated session
(a cloud sandbox) that can read Plain, the public review sites and the Slack
feedback channel, and can write to Linear. The agent pulls in the feedback,
groups it into themes, attaches real quotes and a count to each, and either
opens a new Linear issue for a theme or updates the one already there. One
request, asked many ways, becomes one counted issue rather than a scatter of
mentions.

## How it works

### Run it on a schedule

A **cron trigger** sets the timing. When it fires, it starts a new
**session**: a fresh cloud computer (a sandbox) just for that run. The run
pulls in the latest feedback, compares it with the themes already in Linear,
and brings those up to date. When the run ends, the only thing left behind is
what it wrote to Linear.

### Teach it how we group feedback

The agent carries our grouping playbook in **skills** and **memory**. It
explains when two requests worded differently count as one theme, how to
choose a quote that sums a theme up, how to name an issue, and how to attach
new feedback to a theme that exists already instead of making a copy. When our
themes shift, we update the playbook, so the grouping stays steady from run to
run.

### Hook up the sources and Linear

**Connectors** are scoped connections to your tools. The keys stay on our
servers, so the model never handles a raw token. Through them the agent can:

- **Read Plain.** Recent support conversations, where users bring their
requests and complaints straight to us.
- **Read public reviews.** G2 and the app stores, where users speak in public.
- **Read the Slack feedback channel.** Where our own team posts what they've
been hearing.
- **Write to Linear.** Open an issue when a new theme appears, or refresh the
count and quotes on one that already exists.

### Put the limits in place

Every source is **read-only** for the agent. Linear is the one place it
writes, and there it only opens and updates issues. Setting priority, picking
an owner and closing an issue are left to people. Its credentials are stored
encrypted in the **Secrets Manager** and only handed to the agents you grant
them to, at the moment a run starts.

### Keep a single issue for each theme

After that, every run collects the newest feedback, groups it, and keeps one
current Linear issue per theme. Each issue carries example quotes, a running
count and a list of where the feedback came from. A request that used to be
spread over three systems turns into one issue with a number on it, and the
team can compare it fairly with everything else.

> **The pattern**
> On a set schedule a **cron** starts a session whose **connectors** can read
> Plain, the public reviews and Slack, and can write to Linear. How feedback
> is grouped is kept in **skills** and **memory**. The agent counts the
> themes; people choose what gets built.

## Guardrails

The agent reads from several sources and writes to Linear, and its access
stops there:

- **Isolation.** Each run has a sandbox of its own. The session can reach only
  the sources it's been scoped to, and its changes in Linear are the only thing
  that leaves.
- **Scoped secrets.** The keys for Plain, the review sites, Slack and Linear
  are stored encrypted in the Secrets Manager and only handed to the agents you
  grant them to, when the run begins.
- **Read-only sources, scoped writes.** It can only read the feedback sources.
  Opening and updating Linear issues is the single thing it writes. Ranking,
  assigning and closing are not its call.
- **Everything is code.** How it groups feedback, its skills and what each
  system lets it do are files in the repo. They're versioned, and any change
  goes through a reviewed **change request**, not a toggle on a settings page.

## The outcome

- **Every run:** Feedback collected, grouped and matched up with Linear
- **One per theme:** Repeat requests merged into one issue, not spread around
- **4 sources:** Support, reviews and Slack, all feeding one tracker

Feedback that used to go unread in support, reviews and Slack now shows up as
a short list of counted themes, each one a Linear issue with quotes and a
number attached. The agent handles the collecting and the counting. Which
themes make it onto the roadmap is still the team's decision.
