Skip to main content
New Participant
September 30, 2026

Approval reminders and escalation for Moveworks Access Software requests, built in Jira Service Management Automation

  • September 30, 2026
  • 0 replies
  • 9 views

We kept finding software requests that had been waiting on an approver for weeks, and nobody had noticed. Moveworks doesn’t send approval reminders today, so we built our own on the Jira Service Management side with four Automation rules. Sharing it in case it saves someone the digging. 

The setup

We use Moveworks Access Software (the software catalog) with Native Approvals, set to MANAGER or APP_ADMIN depending on the app, and group-based provisioning. Every request creates a JSM (Jira Service Management) ticket, and the Moveworks integration account comments on it as the request moves along:

  • A public comment: “Approval is needed for <App>. I sent a direct message to <Name>…”
  • An internal comment that includes “Approver: <Name>”
  • On approval, Moveworks provisions access and resolves the ticket
  • On denial, it posts an internal “<Name> denied this request” comment and leaves the ticket open

The problem

The approver gets one DM from the assistant and that’s it. The Moveworks FAQ is explicit: “No approval reminders are sent after the initial reach out.” (source). Pending approvals also drop out of the approver’s queue after 30 days (source). If the DM gets buried, the request just sits there.

It’s hard to catch on the ticket side too. Moveworks runs the approval itself, so the JSM approval fields are empty and nothing in Jira knows who the approver is. Denials had their own problem. The denial comment is internal, so the requester never heard back through the ticket, and the ticket stayed open until someone in IT closed it by hand.

Why Jira Automation

We looked at an Agent Studio scheduled plugin first. The blocker was that there’s no documented API to list pending native approvals, so the plugin would have had nothing to query. The ticket already lives in Jira and already has the approver’s name in a comment, so we built it there.

The rules

Rule 1: assign new tickets (optional). When a ticket is created with the Access Software summary prefix, assign it to the Moveworks integration account (<MOVEWORKS_ACCOUNT_ID>). That keeps them out of the unassigned queue.

Rule 2: capture the approver. Trigger on a comment added by the Moveworks account containing “Approver:”. Pull the name into a variable:

{{comment.body.match("Approver\*?:\s*([^\n]+)").trim()}}

The awkward part is turning a display name into an accountId. Automation has no “lookup user” action, and user fields want an accountId. JQL will accept a display name though, so we use “Lookup work items” with:

project = <SERVICE_DESK_PROJECT> AND reporter = "{{approverName}}"

Then an if/else. If {{lookupIssues.reporter.accountId.distinct.size}} equals 1, add that person as a Request participant with this advanced JSON:

{"update":{"Request participants":[{"add":{"id":"{{lookupIssues.first.reporter.accountId}}"}}]}}

and save the accountId and name to issue entity properties (approverId, approverName) with “Set entity property”. We store them in properties because IT staff and others get added as participants all the time, so reading Request participants later doesn’t tell you who the approver is. If the lookup returns zero or several people, the else branch posts an internal note asking an agent to add the approver by hand.

The obvious caveat: this only works if the approver has filed at least one ticket in the project. People who never filed one, and offboarded users, return nothing and land in the else branch. We’re going to build out a check for that as well and just notify Staff if a manual assignment is needed. An alternative is doing a webhook from Jira automation to search by name and find the ID as well.

Rule 3: weekday reminders and escalation. A scheduled rule on weekday mornings. Cron runs in UTC, so remember to adjust for daylight saving. The JQL:

creator = <MOVEWORKS_ACCOUNT_ID>
AND summary ~ "<REQUEST_PREFIX>"
AND statusCategory != Done
AND created <= -24h
AND (labels is EMPTY OR labels not in (approval-escalated))
AND NOT comment ~ "\"approved this request\""
AND NOT comment ~ "\"denied this request\""

Then, for each ticket, in order:

  1. No approver property: escalate. The check is x{{issue.properties.approverId}} equals x.
  2. Approver marked on leave: escalate. Only do this if your HR sync puts that on the user record.
  3. Three reminders already sent, or the ticket is 25+ days old: escalate.
  4. Otherwise post a public comment mentioning [~accountId:{{issue.properties.approverId}}] and add a reminder-N label.

Escalating means an internal note, assigning the ticket to <ESCALATION_ASSIGNEE>, adding the approval-escalated label, and posting to a Slack channel through an incoming webhook.

The reminder comment has to be public. Request participants only get emailed on public comments, and if you have Atlassian Assist connected to Slack, the @mention shows up in Slack too. The text tells them to find the original approval DM from our Moveworks assistant and click Approve or Deny. We started out telling people they could just type “deny” to the assistant, but that turned out to be unreliable for us, so we point them at the buttons.

Rule 4: close the loop on denials. Trigger on the internal “denied this request” comment from the Moveworks account. Post a public comment to the requester saying who denied it, add a label, and run the Cancel transition with resolution Declined.

Gotchas

  • labels not in (x) on its own excludes tickets with no labels at all. You need the labels is EMPTY OR part.
  • You can’t edit entity properties in the UI. Use a manual-trigger rule or the REST API to set or fix them.
  • JQL can’t search entity properties unless an app indexes them, which is why Rule 3 reads them per ticket instead of filtering on them.
  • On the scheduled trigger, uncheck “only include work items that changed since last run”, or tickets that are just sitting there (the whole point) get skipped.
  • To test, temporarily set the scheduled JQL to key = <TEST_TICKET> and hit “Run rule”.
  • Rules can be exported and imported as JSON if you’re a global admin.
  • Name matching is a real risk. Customer accounts can share a display name with an employee, and that’s why the distinct-size guard is in Rule 2.

Wish list

This works, but it’s a workaround for something that belongs in the product. Moveworks team, native approval reminders with a configurable interval, plus an escalation path when an approval goes stale, would let us delete most of this. An API to list pending native approvals would also open up an Agent Studio version.

Happy to answer questions or share more detail on any of the rules.