Bugtriage - Blueprint
AI bug triage workflow with Mastra agents, a TanStack Start UI, Mastra Studio, and PostgreSQL
An agentic process for triaging bug reports, built with Mastra and TanStack Start on Bun, managed as a Turborepo monorepo. One repository, three services, and a database, all wired up on deploy.
Every report is filed, then passes a funnel where each stage costs more than the one before it:
- Duplicates - one embedding, compared against past reports
- Standing rules - decisions your team taught it earlier, recalled from memory
- Analysis - a read-only Rock8Cloud agent reads your repository and the product docs
- Policy - a plain rule decides: not a bug, a simple fix, or needs a person
A simple fix goes to a coding agent that opens a pull request. Anything else suspends the workflow until a person approves, backlogs, or declines it.
Tech stack:
| Layer | Technology |
|---|---|
| Agents | Mastra workflows, Memory, and evals, port 4111 |
| Web | TanStack Start, port 3000 |
| Studio | Mastra Studio, port 3001 |
| Models | Any model behind your own OpenAI-compatible API key and base URL |
| Coding agents | Rock8Cloud agents |
| Database | PostgreSQL with pgvector |
What You Get
- A private clone of the monorepo in your GitHub account, one repo for all three services
- Three Rock8Cloud services: the Mastra server, the web app, and Mastra Studio
- A managed PostgreSQL database, pre-wired via
DATABASE_URL, holding run state, reports, decisions, and the vector indexes - The services wired to each other automatically, including CORS for Studio
After the First Deploy
The model provider is set when you deploy. Enter your own OpenAI-compatible API key and base URL, and both are stored on the server service. Leave them empty to set them later under Env Vars.
The triage process needs two more values before it can run. Set them on the server service, then redeploy it:
| Variable | What it is |
|---|---|
ROCK8CLOUD_API_KEY | A vhk_ Rock8Cloud API key, used to start the coding agents |
ROCK8CLOUD_SERVICE_ID | The repo-backed service the agents read and change |
Your AI provider key and the Rock8Cloud key are separate, with separate budgets. CHAT_MODEL picks the model the app reasons with. ROCK8CLOUD_AGENT_MODEL_ID optionally picks the coding agent model.
Then open the web app, go to Setup, and run the docs index once. It loads the documentation from DOCS_LLMS_URL into pgvector so the analysis can tell intended behaviour from a bug. The same page shows whether each key actually works.
See Environment Variables for how to set these.
The server, the web app, and Studio have no authentication. Anyone with the server URL can start workflows that spend your AI provider budget and task coding agents with your Rock8Cloud key, and Studio shows every run trace. Treat the URLs as private and add auth before you put anything real behind them.
Slack
Optional. Set SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, and SLACK_CHANNEL_ID on the server service. Each report then opens a thread, every stage posts a line as it finishes, and reports waiting on a person get Build it, Backlog it, and Won't do buttons.
Point the Slack app at the server public URL plus /api/agents/review-agent/channels/slack/webhook. The Slack app manifest is in the repository README.
Tuning the Policy
The decision lives in apps/server/src/mastra/classify.ts. Its thresholds are env vars on the server service, with defaults in apps/server/src/config.ts:
| Variable | Default | What it guards |
|---|---|---|
DUPLICATE_THRESHOLD | 0.88 | Above this similarity, already filed |
MAX_AUTOFIX_FILES | 3 | Files a fix may touch without a person |
ANALYSIS_CONFIDENCE_FLOOR | 0.6 | How sure the analysis must be to act on |
DOCS_INTENT_THRESHOLD | 0.52 | How clearly the docs must call the behaviour intended |
Customizing
- Agents live under
apps/server/src/mastra/agents/*, workflows underapps/server/src/mastra/workflows/* - The web app routes live under
apps/web/src/routes/*
Each service builds from its own Dockerfile (apps/server/Dockerfile, apps/web/Dockerfile, and apps/studio/Dockerfile) with the repository root as the build context.