How to

How to build a bug triage queue

Every bug is urgent to whoever filed it, and the queue is sorted by who shouted loudest. Here is the model behind a triage queue, the prompts to build it, and what it takes to run it.

The short answer

A bug triage queue is four parts: intake detailed enough to reproduce, severity derived from impact rather than chosen by the reporter, reports grouped onto one defect, and targets per severity. The failure is letting the reporter set severity. Everyone rates their own bug highest, so within a month the queue is sorted by confidence rather than by damage, and the genuinely severe issue sits behind six annoyances.

bug-triage.helix-app.ai

Bug triage

7

Untriaged

2

Past triage target

41

Reports on 12 defects

18%

Found internally

Untriaged 7

Export truncates at 10k

14 reports · no workaround

Totals off by rounding

4 reports

Sev 1 1

Export truncates at 10k

overdue 4h

Sev 2 2

Login loop, Safari 18

6 reports · workaround

Totals off by rounding

4 reports

Sev 3 and below 9

Filters reset on refresh

9 reports

Tooltip clipped on mobile

8 reports

A sketch of triage. The tooltip bug has twice the reports of the login loop and sits two columns lower, because severity is derived from impact rather than chosen by whoever filed it.

What matters here

  • A triage queue is four parts: reproducible intake, derived severity, grouping onto one defect, and targets per severity.
  • Never let the reporter set severity. Everyone rates their own bug highest, and the queue stops meaning anything.
  • Derive severity from questions: who is affected, is there a workaround, is data at risk, is it getting worse.
  • Group reports onto one defect. The number of people who hit it is a severity input, not a queue of separate work.
  • Track time to triage separately from time to fix. They fail for different reasons and need different fixes.
  • A bug with no reproduction steps is a conversation, not a ticket, and the form should say so before it is submitted.

Who this is for

You run engineering or support, and the bug list has stopped being a priority order. What you want is a queue sorted by damage rather than volume, and targets the team can actually meet.

How it works in practice

What happens to a bug from the moment somebody hits it to the moment the queue is honest about it.

  1. 1

    It arrives with enough detail to reproduce

    Steps are required, and the form says so before submission rather than an engineer finding out three days later.

  2. 2

    Likely duplicates are suggested immediately

    Matched on symptom and environment, grouped onto one defect with every reporter kept attached.

  3. 3

    Severity is derived from impact questions

    How many people, is there a workaround, is data at risk, is it worsening. Never a dropdown the reporter picks.

  4. 4

    The report count feeds back into severity

    Twenty people hitting one defect is a stronger signal than one, and grouping is what makes that visible.

  5. 5

    Two clocks run separately

    Time to triage and time to fix, because they fail for different reasons and need different responses.

  6. 6

    Known issues become searchable

    With their workarounds, so support answers a large share of new reports without filing anything.

What a triage queue is made of

A triage queue is not a bug list with a priority dropdown. It is four parts, and the second one decides whether the order means anything.

Intake that can be reproduced

What happened, what was expected, the steps, the environment, how often, and when it started. A report without steps is a conversation, and the form should catch that before submission.

Derived severity

From questions about impact: how many people, is there a workaround, is data at risk, is it worsening. Never a dropdown the reporter picks from.

One defect, many reports

Twenty people hitting one bug is one piece of work and a strong severity input. Twenty tickets is a queue that lies about how much there is to do.

Targets per severity

Time to triage and time to fix, set per level and reported against. Targets nobody measures are a wish, and targets nobody can hit get ignored.

These prompts start from a Helix project, which is what handles sign-in, credentials and hosting. Start with Helix

The prompts

Paste these into Claude Code, Codex or Cursor in order. Each one leaves you with something that runs, so you can stop after any step.

  1. Intake that can actually be worked

    Enough to reproduce, checked before submission.

    In this Helix project, build me a bug triage queue.
    
    A report captures: what happened, what was expected instead, the steps to
    reproduce, the environment (browser, version, platform), how often it
    happens, when it started, the affected account if there is one, and who
    reported it.
    
    Require the steps. A bug with no reproduction steps is a conversation
    rather than a ticket, and the form should say so before it is submitted
    rather than an engineer discovering it three days later.
    
    Let people attach screenshots, recordings and log excerpts.
    
    And let me paste in a support ticket or a Slack message and have you draft
    the fields for me to correct, because most bugs arrive as prose from
    somebody who is annoyed.
    
    I sign in through Helix, so do not build a login page. Read the signed-in
    user from the runtime. And do not put any key or connection string in the
    code: if this needs to reach another system, tell me and I will create the
    connection in my workspace.
  2. Severity that the reporter does not choose

    Derived from impact, which is the whole point of triage.

    Now severity, and do not give the reporter a dropdown. Everyone rates their
    own bug highest, and within a month the queue is sorted by confidence
    rather than by damage.
    
    Instead ask a short set of questions and derive the level: how many people
    are affected, is there a workaround and how painful is it, is data being
    lost or corrupted, is anything exposed that should not be, is it getting
    worse, and does it block a customer commitment.
    
    Put the derivation in a config file so I can tune it, and show the answers
    alongside the resulting severity so anybody can see why a bug sits where
    it does.
    
    Let a triager override the derived level, with a reason. Log the
    overrides, and report on them. If one person overrides constantly, either
    the rules are wrong or the triage is.

    Worth knowing. Deriving severity from impact questions is the single change that makes a bug queue mean something. It also removes the argument, because the answer is visible.

  3. One defect, however many people hit it

    Grouping, which is also a severity input.

    Handle duplicates by grouping rather than closing.
    
    Suggest likely matches on submission using the symptom description and the
    environment. When reports are grouped onto one defect, keep every reporter
    and every affected account attached.
    
    Then feed that count straight back into severity. Twenty people hitting
    one bug is a stronger signal than one person hitting it, and twenty
    separate tickets both hides that and inflates how much work there appears
    to be.
    
    Let me split a group apart when two things turn out to be different bugs,
    and keep the history of the split.
  4. Targets, and the two clocks that fail differently

    What good looks like, and where it actually goes wrong.

    Set targets per severity in the config: time to first triage, and time to
    fix or to a stated workaround. Report against both.
    
    Keep those two clocks separate. Slow triage means nobody is looking at the
    queue. Slow fixing means the work is hard or the team is loaded. They fail
    for different reasons and a single time-to-close number hides which one
    you have.
    
    Show a queue sorted by severity then age, with anything past its triage
    target at the top.
    
    Then reporting: bugs by area and severity over time, reopen rate, the
    proportion arriving from customers versus found internally, and the age of
    the oldest untriaged bug, which is usually more informative than the
    average.
    
    And keep a list of known issues with workarounds that support can search,
    because a large share of new reports are things you already know about.
  5. Connect it to real systems

    The step that turns a working prototype into something with your data in it.

    Now connect it to the systems we actually run, so it works on real data
    rather than the rows you seeded.
    
    Anything in angle brackets is a placeholder. Swap it for whatever we use
    instead, and have the app name the connection it wants rather than assume
    a vendor, so changing my mind later is a config change and not a rewrite.
    
    <Zendesk>. Pull customer-reported bugs with their account attached, so
    severity can weigh who hit it.
    
    <Jira>. Push triaged defects to engineering and read status back, rather
    than keeping two lists.
    
    <Salesforce>. Read the contract value behind the affected accounts, which
    is an input to severity.
    
    <Datadog>. Read the logs and traces around the same request, which is what
    turns a vague report into a reproduction.
    
    <Sentry>. Read the error signature and how often it fires, which usually
    settles reproduction.
    
    <Slack>. Route a severity one to the team that owns the service, not to a
    shared channel.
    
    <Okta>. Attribute every triage decision and severity override to a
    verified person.
    
    Only write where I have said to write. Everything else is read only.
    
    Do not write a key, a token or a connection string anywhere in the code,
    and do not ask me to paste one. Tell me which connections you need and I
    will create each as an authentication in my Helix workspace. Reference
    them by alias.

    Worth knowing. Every name in angle brackets is a placeholder for whatever you run. Helix holds the credential as a workspace authentication, so the app references an alias and never the secret itself.

  6. Ship it

    The last step of every build: a URL, and the right people on it.

    Deploy my app.

    Worth knowing. Your assistant runs helix deploy underneath and the app comes back as a URL. Reports carry customer names and sometimes log excerpts, so set Access Control before sharing and keep the internal analysis internal.

What it connects to

Severity is derived from impact, and impact means knowing who is affected and what it is worth.

  • Zendesk

    Pull customer-reported bugs with their account attached, so severity can weigh who hit it.

  • Jira

    Push triaged defects to engineering and read status back, rather than keeping two lists.

  • Salesforce

    Read the contract value behind the affected accounts, which is an input to severity.

  • Datadog

    Read the logs and traces around the same request, which is what turns a vague report into a reproduction.

  • Sentry

    Read the error signature and how often it fires, which usually settles reproduction.

  • Slack

    Route a severity one to the team that owns the service, not to a shared channel.

  • Okta

    Attribute every triage decision and severity override to a verified person.

Each line says whether the app reads, writes or both. Anything not described as writing should be read only.

Named systems are the ones most teams actually run, not a list of the only ones that work. Swap in whatever you use.

Each connection is an authentication in your Helix workspace, referenced by alias. The app names the connection it wants and never holds the credential, so nothing here ends up in your code and any of it can be rotated or revoked without a redeploy.

Running it for real

The build gets you a working queue. It holds customer-reported detail and drives what engineering works on next, so it needs to be run properly.

AI Deployment

Get it to a URL people can open

One command takes the app from your assistant to a live address, so the people who need it get a link rather than instructions for running it locally.

App Security

Put your identity provider in front of it

Bug reports carry customer names, account context and sometimes log excerpts. SSO means people sign in with their existing account, and access is scoped so reporters see status while engineering sees everything.

App Security

Connect the system of record with managed credentials

Linking bugs to accounts, support tickets and deploys needs real access to those systems. Granting it to the app rather than pasting keys into it means credentials can be rotated or revoked without a redeploy.

App Registry

Put a name on it

Every app carries a named owner and an entry IT can see, so the tool does not become nobody's problem when the person who built it changes role.

Cost Management

Know what it costs to run

Per-app spend visibility, with budgets and caps, so an internal tool cannot quietly become a line item nobody can explain.

Questions people ask

What is a bug triage queue?

A single queue where reports arrive with enough detail to reproduce, severity is derived from impact rather than chosen by the reporter, duplicate reports group onto one defect, and each severity has a target the team is measured against.

Why should reporters not set severity?

Because everyone rates their own bug highest, and they are not being unreasonable, they are just closest to it. Within a month the queue is sorted by confidence rather than damage, and the genuinely severe issue sits behind six annoyances.

How should severity be derived?

From questions about impact: how many people are affected, is there a workaround, is data being lost or exposed, is it getting worse, does it block a commitment. Keep the rules in a config file and show the answers next to the result.

Should duplicate bug reports be closed?

Grouped, not closed. Twenty people hitting one defect is one piece of work and a strong severity signal. Closing duplicates throws away the count, and leaving them open inflates how much work there appears to be.

Which bug metrics actually matter?

Time to triage and time to fix, reported separately. Slow triage means nobody is looking at the queue; slow fixing means the work is hard or the team is loaded. A single time-to-close figure hides which problem you have.

Can I build this without an engineering team?

Yes, and it is a slightly odd thing to build for engineers with an assistant, which is rather the point. The judgement calls are your severity questions and your targets.

Last reviewed September 2026.

Build it, then run it properly

Helix is the governed runtime for AI-built apps. Deploy what you build, put SSO in front of it, connect it to your systems with managed credentials, and give it a named owner.