# How the triage-issue Skill Uses JQL for Duplicate Bug Detection in Jira

> Learn how the triage-issue skill uses JQL in Jira to dynamically search for duplicate bugs by error signatures components and symptoms improving bug detection accuracy.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-11

---

**The triage-issue skill dynamically constructs three targeted JQL queries—focusing on error signatures, components, and symptoms—to search for potential duplicates, then scores and merges results from the `searchJiraIssuesUsingJql` helper to identify existing bugs with high confidence.**

The **triage-issue** skill, part of the **atlassian-rovo** plugin in the `openai/plugins` repository, automates duplicate bug detection by leveraging Jira Query Language (JQL) to search across existing issues. Instead of relying on a single static query, the skill extracts keywords from incoming bug reports and injects them into three distinct JQL templates, maximizing recall while maintaining precision through intelligent scoring.

## Dynamic JQL Construction Workflow

The skill implements a multi-stage pipeline defined in [`plugins/atlassian-rovo/skills/triage-issue/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/skills/triage-issue/SKILL.md). It never hard-codes complete JQL strings, instead using runtime interpolation to adapt queries based on the specific bug report content.

### Keyword Extraction from Bug Reports

First, the skill parses the incoming bug report to extract three critical elements:

- **Error signature**: The specific error text or stack trace identifiers
- **Component keywords**: Subsystem or module references (e.g., "authentication", "database")
- **Symptom description**: User-visible problem statements (e.g., "login fails")

According to the skill definition in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) (lines 29-38), this extraction happens via natural-language parsing before any JQL construction begins.

### Three-Angle JQL Templates

The skill prepares three distinct query templates to search from complementary angles, as documented in lines 69-95 of [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md):

- **Error-focused**: Targets exact error text even when component phrasing differs
- **Component-focused**: Finds issues referencing the same subsystem regardless of error phrasing  
- **Symptom-focused**: Surfaces tickets describing the same user-visible problem even without matching error codes

Each template uses placeholder tokens like `"error signature"` or `"component keywords"` that get replaced at runtime with the extracted keywords.

### Executing Searches with searchJiraIssuesUsingJql

For each constructed JQL string, the skill invokes the generic helper function:

```python
searchJiraIssuesUsingJql(
    cloudId=cloud_id,
    jql=interpolated_query,
    fields=["summary", "description", "status", "resolution", 
            "created", "updated", "assignee"],
    maxResults=20
)

```

This API signature appears throughout the skill definition (lines 69-94), consistently requesting a concise field set to minimize payload size while capturing essential duplicate-detection context.

## The Three-Query Strategy Explained

Using multiple queries ensures high recall across different bug description styles:

- **Error-focused queries** prioritize `created DESC` to surface recent instances of the same crash signature
- **Component-focused queries** use `updated DESC` to find actively worked issues in the same subsystem
- **Symptom-focused queries** order by `priority DESC, updated DESC` to highlight severe, recently touched tickets that match the user-reported symptoms

Each query targets `type = Bug` and restricts results to the specified project, ensuring relevant scope.

## Code Implementation: Building and Executing JQL Queries

Below is a Python representation mirroring the skill's runtime logic, showing how extracted keywords populate the JQL templates before calling the Jira search API:

```python
def build_triaging_queries(project_key, error_kw, component_kw, symptom_kw):
    """Construct the three JQL queries used for duplicate detection."""
    
    # Error-focused: Catch exact error text regardless of component wording

    error_jql = (
        f'project = "{project_key}" AND '
        f'(text ~ "{error_kw}" OR summary ~ "{error_kw}") '
        f'AND type = Bug ORDER BY created DESC'
    )
    
    # Component-focused: Find same subsystem, different error phrasing

    component_jql = (
        f'project = "{project_key}" AND '
        f'text ~ "{component_kw}" AND type = Bug '
        f'ORDER BY updated DESC'
    )
    
    # Symptom-focused: Match user-visible problems, flexible on error codes

    symptom_jql = (
        f'project = "{project_key}" AND '
        f'summary ~ "{symptom_kw}" AND type = Bug '
        f'ORDER BY priority DESC, updated DESC'
    )
    
    return error_jql, component_jql, symptom_jql


def detect_duplicates(cloud_id, project_key, extracted_keywords):
    """Execute searches and aggregate results for duplicate detection."""
    queries = build_triaging_queries(
        project_key,
        extracted_keywords["error"],
        extracted_keywords["component"],
        extracted_keywords["symptom"]
    )
    
    all_results = []
    for jql in queries:
        results = searchJiraIssuesUsingJql(
            cloudId=cloud_id,
            jql=jql,
            fields=["summary", "description", "status", "resolution",
                    "created", "updated", "assignee"],
            maxResults=20
        )
        all_results.extend(results)
    
    return all_results

```

The actual skill executes this logic within the OpenAI function-call flow defined in [`plugins/atlassian-rovo/skills/triage-issue/agents/openai.yaml`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/skills/triage-issue/agents/openai.yaml).

## Result Scoring and Aggregation

After retrieving results from all three queries, the skill merges the datasets and calculates confidence scores based on criteria defined in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) (lines 20-36):

- **Exact error match**: Higher weight when error signatures align
- **Component overlap**: Verification that the subsystem matches
- **Recency**: Preference for recently created or updated issues
- **Status**: Consideration of resolution state (open vs. closed duplicates)

The system categorizes findings as **high-confidence duplicates**, **likely duplicates**, **related issues**, or **new problems**, then formats the top matches using presentation templates starting at line 64 of [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md).

## Key Source Files

The triage-issue skill implementation spans these files in the `openai/plugins` repository:

- **[`plugins/atlassian-rovo/skills/triage-issue/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/skills/triage-issue/SKILL.md)** — Contains JQL templates, scoring rules, and workflow definitions (lines 20-95)
- **[`plugins/atlassian-rovo/skills/triage-issue/agents/openai.yaml`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/skills/triage-issue/agents/openai.yaml)** — Maps `searchJiraIssuesUsingJql`, `addCommentToJiraIssue`, and `createJiraIssue` to the function-call interface
- **[`plugins/atlassian-rovo/.app.json`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/.app.json)** — Plugin manifest registering the triage-issue skill
- **[`plugins/atlassian-rovo/.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/.codex-plugin/plugin.json)** — High-level metadata including required Jira scopes

## Summary

- The **triage-issue** skill uses **three distinct JQL queries** (error, component, and symptom-focused) to maximize duplicate detection recall
- Keywords are **dynamically interpolated** into templates at runtime rather than using static queries
- The **`searchJiraIssuesUsingJql`** helper retrieves essential fields (`summary`, `description`, `status`, `assignee`, timestamps) for comparison
- Results are **merged and scored** based on exact matches, component overlap, recency, and status to determine confidence levels
- All JQL logic and scoring rules are defined in **[`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md)** within the `openai/plugins` repository

## Frequently Asked Questions

### What specific JQL fields does the triage-issue skill retrieve?

The skill requests seven specific fields via the `fields` parameter in `searchJiraIssuesUsingJql`: `summary`, `description`, `status`, `resolution`, `created`, `updated`, and `assignee`. This minimalist field set, defined in lines 69-94 of [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md), provides sufficient context for duplicate comparison while keeping API payloads efficient.

### How does the skill differentiate between duplicates and merely related issues?

The scoring system weighs four factors: exact error signature matches carry the highest weight, followed by component overlap, ticket recency (preferring newer issues), and current status. According to lines 20-36 of [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md), results crossing specific confidence thresholds classify as "high-confidence duplicates" or "likely duplicates," while partial matches are flagged as "related issues."

### Can developers customize the JQL templates for specific project requirements?

While the templates are embedded in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) (lines 69-95), the skill architecture supports modification because the JQL strings use placeholder-based interpolation. Developers can adjust the base templates—changing operators like `~` (contains) to `=` (equals) or modifying `ORDER BY` clauses—within the skill definition, though the [`openai.yaml`](https://github.com/openai/plugins/blob/main/openai.yaml) agent configuration must remain synchronized with any new parameters.

### Where is the searchJiraIssuesUsingJql function implemented?

The function appears as a callable action in [`plugins/atlassian-rovo/skills/triage-issue/agents/openai.yaml`](https://github.com/openai/plugins/blob/main/plugins/atlassian-rovo/skills/triage-issue/agents/openai.yaml), where it is mapped to the OpenAI function-call interface. The actual Jira API wrapper implementation resides in the broader atlassian-rovo plugin infrastructure, while the skill itself focuses on JQL construction and result interpretation in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md).