Skip to content

Add the perf-triage agent - #7349

Open
pslawless wants to merge 9 commits into
mozilla:masterfrom
pslawless:perf-triage
Open

pslawless wants to merge 9 commits into
mozilla:masterfrom
pslawless:perf-triage

Conversation

@pslawless

Copy link
Copy Markdown

Adds perf-triage, a Hackbot agent that rates a Firefox performance bug's Performance Impact with the Performance Impact Calculator and writes the result to the bug. A companion bugbot rule (mozilla/bugbot, separate PR) triggers it when cf_performance_impact is set to ? or a bug lands in Core :: Performance: General.

What it writes

Bug state Writes
Unrated (---/?) One comment; cf_performance_impact; the calculator's keywords (add only); a needinfo to the perf reviewer on a high rating
Rated by a person One comment, only if the agent disagrees. Never touches the field

Writes are recorded during the run and applied afterwards by hackbot-api. A run applies unattended only when the calculator, re-scored over every input the bug leaves open and every platform choice, stays in one band. Otherwise it waits for a person. hooks.py refuses any other write as it is recorded.

Deployment prerequisites

  • The hackbot Bugzilla account needs membership in the perf-triage-team Bugzilla group, with edit rights to cf_performance_impact. Without the membership, every update on an unrated bug is rejected. We'll confirm with one real write on a test bug after the first deploy.
  • Deploy the agent before the bugbot rule is enabled. The rule's first run uses --backlog; after that it looks back one day.
  • Open: the agents.json entry in mozilla/webservices-infra. Who adds it: the hackbot team or the agent author?

🤖 Generated with Claude Code

@evgenyrp

evgenyrp commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

@pslawless I'm reviewing the overall agent, but can we add someone else who is familiar with perf-triage to review the relevant pieces?

and the refused action never lands. Pattern from frontend-triage's hooks.py.
"""

from __future__ import annotations

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already require python 3.14, so no need for __future__.

Comment on lines +93 to +97
recorder.record(
"bugzilla.add_comment",
{"bug_id": bug_id, "text": text, "is_private": False},
reasoning=f"Performance triage: {result.impact} ({result.score})",
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use add_comment() here instead of using recorder.record(), so that we do not need to add the footer manually and things stay constant.

Comment on lines +104 to +108
recorder.record(
"bugzilla.update_bug",
{"bug_id": bug_id, "changes": changes},
reasoning="Set from the triage calculator's rating and keywords",
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use update_bug() here instead of using recorder.record().

Comment on lines +33 to +36
REACTION_LINE = (
"If you'd like to provide feedback on this comment, please use the 👍 or 👎 "
"reaction."
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid adding this manually.

Comment on lines +37 to +41
FEEDBACK_TAGS = (
"If you want to categorize your feedback you can add one of the following "
"tags: perf-triage-{wrong-impact, wrong-component, wrong-cause, "
"wrong-severity, hallucination, not-perf}."
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be added using a hook, example:

def feedback_tags_hook(action: dict) -> None:
"""Offer the feedback tags and the patch request below the runtime's footer.
The patch request takes a blank line: the comment is Markdown, where a lone
newline would fold it onto the end of the tag list.
"""
params = action.get("params")
if not isinstance(params, dict):
return
text = params.get("text")
if isinstance(text, str):
params["text"] = f"{text.rstrip()}\n{_FEEDBACK_TAGS}\n\n{_PATCH_REQUEST}"

Comment thread libs/performance-tools/pyproject.toml Outdated
@@ -0,0 +1,30 @@
[project]
name = "performance-tools"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code in libs/performance-tools would be a natural fit as part of the agent itself rather than as a standalone library. I understand the goal is to make it reusable for future performance-related agents. Since this is a single uv workspace, agents can easily import modules from one another, and any common tools can be extracted into a shared library later, once the need is clear.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Folded into the agent package in e5be53a. If a second perf agent needs it, we'll extract a shared library then.

Comment thread .gitignore Outdated
Comment on lines +56 to +57
# Local agent run output
artifacts/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should be in ~/hackbot/artifacts, so this should not be needed any way.

@evgenyrp
evgenyrp removed their request for review November 5, 2026 19:58
@evgenyrp

evgenyrp commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

@pslawless I'm reviewing the overall agent, but can we add someone else who is familiar with perf-triage to review the relevant pieces?

I'm passing it to @suhaibmujahid as he already started reviewing

@pslawless

Copy link
Copy Markdown
Author

@suhaibmujahid - I've addressed your comments so far. And I asked @Bas-moz to review the triage parts (I didn't see a way to add him as a reviewer on the PR though).

@suhaibmujahid
suhaibmujahid requested a review from Bas-moz November 6, 2026 22:29
@suhaibmujahid

Copy link
Copy Markdown
Member

I didn't see a way to add him as a reviewer on the PR though

@pslawless I created a new team, @mozilla/hackbot-performance, with write permission to the repo. I added @Bas-moz to it, so he can now be requested as a reviewer on PRs. You can manage the team, so please remove me from it once you’ve accepted the invite.

Related: please add @mozilla/hackbot-performance as the agent code owner in .github/CODEOWNERS, so you can land PRs independently going forward.

"duckduckgo.com",
"amazon.de"
],
"common": [

@Bas-moz Bas-moz Nov 11, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still used? It seems to me like the code just looks at the rank now.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code only reads rank. tier_examples is a human-readable sample that the upstream generator (build_top_sites.py in performance-triage-calculator) writes, and the file is vendored verbatim. I'll drop it upstream rather than edit the vendored copy.

@@ -0,0 +1,62 @@
You are a Firefox page-load performance reproduction agent. You investigate

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we intend to limit the scope of the agent to pageload? It feels like the rest of this patch permits a broader scope.

pslawless and others added 9 commits November 12, 2026 12:20
Runs the triage-perf-bug skill from mozilla/performance-triage-calculator in
agent mode and returns its Performance Impact rating, severity, the inputs
the bug did not establish, the related bugs it took inputs from, and an
optional profile finding.

The stability check re-scores the vendored calculator over every value of
the unestablished inputs, plus platforms; a rating is confident only when the
band never changes. Reproducibility is out of scope for this phase and is
never varied.

blind.py lets the broker hide a bug's engineer triage (BLIND_BUG_ID), for
evaluating the agent against ratings people already made.

The skill, the profiler-analysis skill and perf_triage.py are vendored
verbatim (see skills/PINNED.md) and excluded from pre-commit so they stay
byte-identical to their pinned revisions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Triages a performance bug with libs/performance-tools and records a comment
plus cf_performance_impact and keywords. Writes auto-apply only when the
rating is stable; otherwise they are held for review. On a bug a person
already rated it comments only when it disagrees and never changes the
field. A high rating needinfos the performance triage reviewer, and every
comment names them as the contact for disagreements. Fails closed when the
bug lookup fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cleaned up README
- Fold libs/performance-tools into the agent package; extract a shared
  library later if a second agent needs it.
- Record the comment and bug change through hackbot_runtime's add_comment
  and update_bug, so the runtime supplies the reaction footer.
- Append the feedback tags with an add_comment hook, as frontend-triage does.
- Drop from __future__ imports (Python 3.14 is required).
- Drop the artifacts/ ignore; runs write to ~/hackbot/artifacts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shared system prompt was perf-repro's: it told every triage run it was a
page-load reproduction agent, to measure and not diagnose, and to triage out
jank, memory and startup bugs. Keep only the generic rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Picks up the per-bug profiler-cli session (39acdfa), a symlink note in
Step 0 (ec4f454), and drops the unused tier_examples block from
top_sites.json (0674246, raised in review). perf_triage.py, criteria.md and
the two scripts are byte-identical to c78430d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Matches mozilla#7466: the release flow bumps agents/<name>/VERSION, and it fails on
an agent without one. Also require Python 3.14, as the other agents do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pslawless

Copy link
Copy Markdown
Author

Hi @suhaibmujahid, just wanted to check in on this PR. Looks like Bas has accepted the triage related parts. Is there anything else you need from me? (I'm excited to get this agent running :)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants