Triage and route bug reports
An incoming report is read, matched against open issues to catch duplicates, and filed to the right team's board with severity attached.
- TriggerTriggeredLinear
Webhook on new bug report
- CompletedClaudeChatGPT
Read it and name the gaps
- Completed
Separate symptom from diagnosis
- CompletedLinear
Check whether it is known
- Completed
Assign a defensible severity
- CompletedLinearSlack
Route it to the owning team
Triage is a job that is easy to do badly and invisible when done well. A report arrives, somebody skims it, files it wherever seems reasonable, and assigns a severity based mostly on how the reporter sounded. Two weeks later the same bug has three open issues on two boards, one of which is a regression nobody spotted because it matched a closed ticket that nobody searched.
Almost none of that requires product judgement. Extracting a symptom, searching for an existing match, deciding a band from stated impact, and mapping a surface to its owning team are all mechanical, and doing them consistently at 200 reports a week is precisely where humans stop being consistent.
What you get
Every report lands on the owning team's board within minutes, deduplicated against what is already open, with a severity that reflects what the reporter actually described.
The part worth getting right
Search closed issues as well as open ones. A report matching something closed last week is a regression: the fix did not hold, or it held and something else broke it. Triaged as a new bug it starts at the back of the queue with no history, and the person who fixed it the first time never finds out. One extra query changes the outcome entirely.
The symptom goes in the title, never the reporter's diagnosis. People supply causes with their reports and the causes are often wrong, but a title stating one sends the issue straight to whichever team owns the thing they guessed at, where it is correctly closed as not-a-bug. The guess goes in the body with a name attached, and the issue lands wherever the symptom points.
Posting only the top band to a channel is a discipline that protects the channel. Routing every routine report into chat teaches the team that the channel is background noise, and the alert that genuinely needed a response in ten minutes gets the same treatment as the misaligned button from Tuesday.
The prompt
The real prompt behind the steps above — detailed enough that an agent with a people-search tool, email/phone enrichment, and CRM access can run it as written.
# Triage and route bug reports
You have access to an issue tracker and a messaging tool. Run this on
**[each incoming bug report]**.
## 0. Set up (skip if you're already connected)
If you don't already have live tool access for this, connect it
first. This prompt is only as real as the tools behind it:
1. Create a free account at app.tulina.ai.
2. Add Tulina's MCP server to your assistant: https://mcp.tulina.ai/mcp
3. In Tulina, connect your own API keys for the tools this
prompt uses: your issue tracker and your team's messaging tool.
Once connected, your assistant has real tool access and the rest of
this prompt runs as written.
## 0b. Already on Tulina? Three things around the run
An account and the MCP server are not the whole setup. Two of these come
before the run below and one after it, and together they turn this from a
one-off answer into a process your workspace keeps:
1. **Activate this process's connectors first.** Call
`oto_connector(op="list")`, match it against the tools named in step 3
above, and `oto_connector(op="select", name="...")` every one that
isn't active yet. Selecting a connector does not mount its tools in the
conversation you're already in — reach them through `oto_call` for this
run, or open a fresh conversation once they're all on.
2. **Attach the work to an existing project.** `oto_project(op="list")`
shows your active org's projects: pick the one this work belongs to
rather than opening another, and keep its id. The project is where this
process, the tables it writes to and the connectors it uses hang
together.
3. **When the run is done, save it as a process — with its graph.** Write
the body with `oto_procedure(op="set", ...)`, then attach it with
`oto_project(op="link", project_id=..., target_type="procedure",
target_ref="<your slug>")`. The body has to carry a drawing: read
`oto_guide(op="read", slug="procedure-flowchart")` and follow it
exactly — ONE untagged fenced block in that grammar, opening with the
trigger and a quoted example of what you'd type to start a run. Tulina
parses that drawing back into the graph it renders as the process's
default view, which is what makes it come out in the same style as
every other process in the app; a drawing the grammar can't read falls
back to raw characters instead. Saving a process needs org-admin
rights — without them, hand the finished body to someone who has them.
## 1. Read the report and name what is missing
Extract, in the reporter's own words where possible:
- The symptom. What happened, not what they think caused it.
- Reproduction steps, if given.
- Environment: browser, device, version, account.
- Frequency: once, intermittent, or every time.
- Impact: blocked entirely, or working around it.
Where reproduction steps or environment are missing, say so
explicitly. A report with no repro is still worth filing, but it must
be visibly labelled, because the difference between "cannot reproduce"
and "was never told how" is the difference between closing an issue
correctly and closing it wrongly.
## 2. Separate the symptom from the diagnosis
Reporters routinely supply a cause along with the effect, and the
cause is frequently wrong. "The cache is broken so my dashboard is
empty" is one observation and one guess.
File the observation. Keep the guess in the body, attributed to the
reporter. A title describing a diagnosis sends the issue to the wrong
team and gets closed as not-a-bug while the actual problem stays open.
## 3. Check whether it is already known
Search the tracker on the symptom, matching by substance rather than
by wording. Search open issues first, then recently closed ones: a
report about something closed last week is a regression, which is more
urgent than a new bug, not less.
When it already exists, comment on it with the new report's specifics
and reporter rather than filing a duplicate, and say in the response
that it was linked to an existing issue.
## 4. Assign a severity you can defend
Severity comes from what was described, never from the reporter's
tone. An angry report about a cosmetic misalignment is not urgent, and
a politely worded note about corrupted exports is.
- Blocked with no workaround, or data being lost or shown wrongly, is
the top band.
- A workaround exists but is performed repeatedly is the next.
- Cosmetic, or affecting one unusual configuration, is the lowest.
Two multipliers: how many accounts have reported it, and whether it is
a regression. Both should raise the band, and both are facts rather
than judgements.
## 5. Route it to the team that owns the area
Map the affected surface to the board that owns it. Where ownership is
ambiguous, file it on the most likely board and flag the ambiguity in
the issue rather than leaving it in a triage queue. An issue sitting
unassigned pending a routing decision is the most common way a real
bug goes stale.
Post to the channel only for the top severity band. Routine reports
going into a channel train everyone to ignore that channel, which
means the one that mattered is ignored too.
## Output
Report: reports triaged, matched to existing issues, regressions
identified, new issues created by board and severity, reports missing
repro steps, and the ones where ownership was ambiguous.
Questions about this process
Related processes
- Call feedback becomes tickets and docs
Every call recorded during the day is distilled overnight, with bugs and feature requests routed to the right team as tickets and docs, plus a Friday digest.
- Merged PRs move tickets and post a digest
Every pull request that lands gets matched to its ticket, moved forward on the board, and rolled into one summary for the team.
- Prepare for a customer call
Before the call, the last conversations, the account's state, how the product is actually being used, and where their requested features stand, in one brief.