Skip to content
← All AI assets

Autonomous triage agent · Jira Service Management

Product Support Triage Agent

A Rovo agent that automatically classifies every new ticket the moment it enters the Product Support queue in Jira Service Management (JSM) through a deterministic three-stage decision framework, returning strict JSON that JSM Automation maps into routing and telemetry fields — triaging 100% of tickets with the proper labels to speed up troubleshooting.

My role
Builder & AI architect
Tools
Atlassian Rovo, Jira Service Management, JSM Automation, Confluence, Prompt Architecture, Domo
Who it helps
Product Support Engineers (PSE) and triagers on the PSRD (Product Support Remediation Desk) board, who get consistent, rule-based classifications and proper labels on every incoming ticket instead of ad-hoc manual triage, speeding up troubleshooting.
How it works
Jira Service Management (JSM) is Atlassian's ITSM platform — the system where Product Support tickets are submitted, queued, and worked. When a new ticket enters the PSRD (Product Support Remediation Desk) queue in JSM, a JSM Automation rule immediately passes its summary and description to the agent. It applies a three-stage framework — workType (Incident / Problem / Service Request), a requestType / psCategory drawn from priority-ordered reference tables, then confidence and clarification logic — and returns a single valid JSON object that triages the ticket with the proper labels. Automation writes that output into telemetry custom fields; a human triager confirms the production Request Type and PS Category, which automation never overwrites in this version.
My contribution
Ran the build like a product manager: started with discovery to understand the triage problem and the PSRD taxonomy, wrote a PRD, translated that PRD into a detailed spec (the three-stage classification framework, tiebreaker rules, and labeled few-shot examples), then tested and iterated against real tickets. Owned change management — keeping the Rovo scenario prompt, the automation trigger instructions, and the Confluence documentation in sync — and stood up the feedback loop (manual triager feedback + telemetry routed to Domo) that drives ongoing prompt and logic improvements.
Why it’s valuable
Replaces inconsistent manual first-touch triage with a deterministic, auditable classification that routes tickets the same way every time, flags non-PSRD work for review, and feeds a telemetry loop (Domo dashboard + manual triager feedback) that steadily improves accuracy.

Approach

  1. Solved the core constraint of building an agent that lives inside a JSM Automation, not a chat window — it gets one shot with the ticket summary and description, no ability to ask follow-ups or iterate, so every classification rule had to be baked into the prompt upfront.
  2. Designed a deterministic three-stage decision framework so classifications follow explicit rules and labeled examples rather than probabilistic guesses — Stage 1 sets workType, Stage 2 maps requestType/psCategory via priority-ordered tables, Stage 3 sets confidence and clarification.
  3. Encoded six Incident subcategories (Stakeholder Escalation, Linked to Problem, Partner/Aggregator Outage, Institution Connectivity Failure, Data Quality Incident, Client Outage) evaluated in strict priority order — first match wins.
  4. Encoded Problem subcategories (Aggregator Cleanup/Migration, Performance Trend/Conversion, RCA, Investigate a Problem catch-all) with a fallback mapping table for cases where a specific Request Type ID or PS problem category is unavailable.
  5. Encoded five Service Request subcategories (Connectivity feature/Configuration, Scrape/New Connectivity Method, Data/Reporting support, Alert/Monitoring configuration, General Inquiry) with explicit key-signal triggers.
  6. Authored seven disambiguation tiebreakers with absolute priority over general signal matching — e.g. FI-specific failure defaults to Institution Connectivity Failure until multi-FI scope is explicitly confirmed; stakeholder escalation always overrides technical cause; an active issue is never upgraded from Incident to Problem.
  7. Calibrated the agent with fourteen labeled few-shot examples (A–N) covering canonical incidents, problems, service requests, and negative non-PSRD cases.
  8. Enforced strict-JSON-only output (no code block, no preamble) because the agent runs headless inside JSM Automation — there is no human in the loop to tolerate prose, and any wrapping breaks the `{{agentResponse.asObject.*}}` parse.
  9. Wired the JSM Automation rule: trigger the moment a ticket enters the PSRD queue (ignoring `spectre_alert` and Request Type ID 889), call the agent, then branch on `nonPsrd` to either route to Needs Review or write the PSRD-work fields.
  10. Delivered a telemetry design where agent outputs land in `(Rovo)` reference fields for human validation, plus a manually-entered `agentFeedback (Rovo)` field that feeds a Domo dashboard for prompt and logic iteration.

Outcomes

  • Triages 100% of Product Support tickets on creation with the proper workType, requestType, and psCategory labels, giving triagers a consistent starting point that speeds up troubleshooting.
  • Non-PSRD tickets are automatically flagged as Needs Review with an explanatory rationale comment, keeping the board clear of out-of-scope work.
  • Built a non-destructive v1 design: automation writes suggestions to telemetry/reference fields only, so production Request Type and PS Category are never overwritten without human confirmation.
  • Established a feedback loop (manual agentFeedback + telemetry routed to Domo) to continuously improve classification accuracy through prompt and logic updates.
  • Documented the full system — field mappings, automation logic, troubleshooting, and a ready-to-paste prompt insert — in Confluence for ops handoff and change control.

What I learned

  • An agent embedded in an automation is fundamentally different from a chat agent — it runs headless, one-shot, with no ability to ask follow-ups, which makes deterministic rules and exhaustive few-shot coverage non-negotiable.
  • Deterministic, rule-ordered classification with labeled examples beats open-ended LLM judgment for routing decisions that must be auditable and consistent.
  • Strict-JSON-only output is what makes an LLM agent safely callable from JSM Automation — any prose wrapping breaks the `{{agentResponse.asObject.*}}` parse.
  • Designing the agent to be non-destructive in v1 (suggestions to telemetry fields, human confirms production fields) built trust with triagers and made rollout low-risk.
  • Tiebreaker rules with explicit priority order are essential for edge cases — without them, plausible-but-conflicting signals produce inconsistent routing.

Overview

Jira Service Management (JSM) is Atlassian’s IT service management platform — the system where Product Support tickets are submitted, queued, and worked. The PSRD (Product Support Remediation Desk) board is the specific JSM project that receives these tickets. Every ticket that enters the PSRD queue needs a consistent first-touch classification: is this an Incident, a Problem, or a Service Request? What request type and PS category does it map to? And does it even belong on this board? Manual triage produced inconsistent answers, especially for edge cases like aggregator-wide outages vs. single-FI failures, or active incidents that also reference a historical pattern.

The Product Support Triage Agent is a Rovo agent that classifies every new ticket the moment it enters the PSRD queue, deterministically, and returns a strict JSON payload that JSM Automation maps into routing and telemetry fields. It does not replace the human triager — it produces suggestions that a PSE confirms — but it removes the cold-start ambiguity from every incoming ticket.

Why this was a complex build: an agent inside an automation

Most Rovo agents are conversational — a person chats with them, refines a request, and iterates. This agent is the opposite: it lives inside a JSM Automation rule, not a chat window. That architecture shaped every design decision:

  • One-shot, no follow-ups: The agent receives only the ticket’s summary and description and gets a single turn to classify it. There is no ability to ask the reporter a clarifying question before deciding — so clarificationNeeded and clarificationQuestion exist as outputs for the human triager, not as a back-and-forth with the reporter.
  • Headless execution: No human reads the raw response. JSM Automation must parse {{agentResponse.asObject.*}} directly into custom fields, which is why the output is strict JSON only — no code blocks, no preamble, no prose. Any wrapping breaks the parse and the whole rule fails silently.
  • All logic lives in the prompt: Because the agent can’t be reconfigured at runtime, every classification rule, tiebreaker, fallback mapping, and few-shot example had to be encoded into the prompt upfront. The three-stage framework, the priority-ordered subcategory tables, and the seven tiebreakers all exist because the agent has to handle every case deterministically in a single pass.
  • Trigger and filter design: The automation had to be wired to fire only on the right tickets — triggering on PSRD queue entry but ignoring spectre_alert tickets and Request Type ID 889 — and then branch on nonPsrd to route non-PSRD work to Needs Review.
  • Non-destructive by necessity: Because the agent runs automatically on every ticket with no human gate before it acts, v1 was designed to write only to telemetry/reference fields — production Request Type and PS Category are never overwritten without a triager’s confirmation. Automation-driven agents that silently mutate production fields are a trust and auditability risk.

In short, building an agent that lives inside an automation is a different engineering problem than building a chat agent: it has to be deterministic, self-contained, parse-safe, and safe-to-autorun on every ticket.

The three-stage decision framework

The agent follows an explicit, ordered framework rather than open-ended judgment:

Stage 1 — workType

Classify the ticket as Incident, Problem, or Service Request.

Stage 2 — requestType & psCategory

Once workType is set, evaluate a priority-ordered subcategory table and take the first match.

  • Stage 2a (Incident): Six subcategories evaluated in priority order — Stakeholder Escalation → Linked to Problem → Partner/Aggregator Outage → Institution Connectivity Failure → Data Quality Incident → Client Outage/Degradation.
  • Stage 2b (Problem): Aggregator Cleanup/Migration, Performance Trend/Conversion, RCA, or a catch-all Investigate a Problem — with a fallback mapping table for cases where a specific Request Type ID or PS problem category is unavailable.
  • Stage 2c (Service Request): Connectivity feature/Configuration, Scrape/New Connectivity Method, Data/Reporting support, Alert/Monitoring configuration, or General Inquiry.

Stage 3 — Confidence & clarification

Assign High / Medium / Low confidence and a clarification flag based on decision-tree match quality, lexical signal strength, whether tiebreakers were needed, and similarity to the labeled examples. Low confidence always sets clarificationNeeded: "True" and a single targeted question targeting the one unknown that would most change routing.

Tiebreakers: the edge-case rules

Edge cases are where deterministic triage earns its keep. Seven tiebreaker rules have absolute priority over general signal matching, applied in order:

  1. FI-specific vs. aggregator-wide: Default to Institution Connectivity Failure; only upgrade to Partner/Aggregator Outage when multi-FI impact is explicitly confirmed.
  2. Stakeholder escalation overrides technical cause: CSM/AM/executive origin or escalation language always classifies as Stakeholder Escalation.
  3. Active issue is an Incident: A ticket opened as an active problem right now is an Incident even if a pattern is mentioned — create a separate Problem for the pattern.
  4. Broken config with active impact is an Incident: If clients are impacted now, it’s an Incident; if the config is just wrong but not yet causing impact, it’s a Service Request.
  5. Specific Problem subtype over catch-all: Use Investigate a Problem only when the subtype is genuinely unclear at intake.
  6. Single-client data defect vs. systemic: One client/FI affected now = Incident; multiple clients/FIs from the same underlying defect = Problem.
  7. Non-PSRD detection: Internal Eng/TOPS tasks and documentation requests are not PSRD work — flag nonPsrd and route to Needs Review.

The output schema

The agent returns one JSON object — no code block, no preamble, no "fields" wrapper — that JSM Automation parses directly:

{
  "workType": "Incident" | "Problem" | "Service Request",
  "requestType": "<value from Stage 2 tables>",
  "psCategory": "<value from approved list>",
  "confidence": "High" | "Medium" | "Low",
  "clarificationNeeded": "True" | "False",
  "clarificationQuestion": "<single concise question, or omit if false>",
  "rationale": "<1-2 sentence plain-English reasoning>",
  "nonPsrd": "True" | "False",
  "routeTo": "PSRD board" | "Internal/TOPS" | "TechOps Docs" | "Needs Review"
}

How automation consumes it

A JSM Automation rule triggers the moment a ticket enters the PSRD queue (ignoring spectre_alert tickets and Request Type ID 889), passes {{issue.summary}} and {{issue.description}} to the agent, and branches on the response:

  • If nonPsrd = "True": sets Needs Review, writes confidence/clarification/rationale, and adds an explanatory comment.
  • Else (PSRD work): writes workType, confidence, clarificationNeeded, rationale, nonPsrd, and routeTo into the corresponding (Rovo) telemetry custom fields.

Critically, this version is non-destructive: requestType and psCategory suggestions land in telemetry/reference fields, and the production Request Type and PS Category fields are never overwritten by automation. A human triager reviews and confirms those.

The telemetry & improvement loop

Every agent output is captured in (Rovo) custom fields and routed to a Domo dashboard for audit and routing analysis. A separately maintained agentFeedback (Rovo) field lets triagers note when the agent miscategorized a ticket — feedback that’s reviewed alongside the telemetry and fed back into prompt and logic updates to steadily increase triage accuracy.

Email copied: mitchellgdyer@gmail.com