Documentation for automated readers
A curated documentation index is available at: https://grafana.com/llms.txt
A complete documentation index is available at: https://grafana.com/llms-full.txt
These indexes can help with page discovery before fetching individual documents.
This page is also available in Markdown, which may be easier for automated readers and AI tools to parse than HTML. The Markdown version is available at https://grafana.com/docs/grafana-cloud/platform/workflows/reference/blueprints/enforce-severity-before-resolve.md, or by sending Accept: text/markdown to https://grafana.com/docs/grafana-cloud/platform/workflows/reference/blueprints/enforce-severity-before-resolve/. For broader documentation discovery, the curated index is available at https://grafana.com/llms.txt and the complete index is available at https://grafana.com/llms-full.txt.
Enforce severity before resolve
Note
Grafana Workflows is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
Stop incidents from being resolved while their severity is still Pending. Reopens the incident and tells the team why.
This Grafana Workflows blueprint is in the Incidents category of the Blueprints library.
Before you begin
To use this blueprint, you need:
- Grafana IRM set up on your stack.
- Slack connected to Grafana IRM. For details, refer to Configure Slack for Grafana IRM.
Steps
Steps run in order from first to last. A step inside a switch branch runs only when Workflows chooses that branch.
| Step | ID | Type | Description |
|---|---|---|---|
| Is severity still Pending? | severity-is-pending | filter | Continues only when the incident was resolved with a Pending severity. Change the regex to also block other severities, for example ‘(?i)^(pending|unknown)$’. |
| Revert the status change | reopen | incident.set-field | Sets the incident back to the status it had before it was resolved. No changes needed. |
| Explain on the timeline | explain-on-timeline | incident.add-note | Adds a timeline note that explains why the incident was reopened. Edit the wording to match your policy. |
| Has an incident channel? | has-slack-channel | filter | Stops here when the incident has no linked Slack channel. No changes needed. |
| Tell the incident channel | tell-the-channel | slack.message.post | Explains the reopen in the incident Slack channel. Edit the wording to match your policy. |
For the inputs and outputs of each step type, refer to Step and trigger types reference.
Before you turn on the workflow, customize any steps that need input from you, such as a channel ID or a schedule name. Each step’s description says what to set.
Workflow definition
Save this definition as a YAML file to create the workflow with gcx, the Workflows API, or Terraform, or give it to a coding agent as an example.
Replace FOLDER_UID with the UID of the folder for the workflow.
Blueprints start disabled, so finish customizing the steps before you set enabled to true.
For details, refer to Manage workflows as code.
apiVersion: workflows.ext.grafana.app/v1alpha1
kind: Definition
metadata:
name: enforce-severity-before-resolve
annotations:
grafana.app/folder: <FOLDER_UID>
spec:
name: Enforce severity before resolve
enabled: false
runOnceFor: "enforce-severity:${inputs.data.incidentID}:${has(inputs.data.closedTime) ? inputs.data.closedTime : ''}"
startWhen:
matchingRules:
- eventNameRegex: 'grafana_irm_app\.incident\.updated'
filter: "inputs.data.eventKind == 'incident_updated_status' && inputs.data.newStatus == 'resolved'"
schedules: []
steps:
- id: severity-is-pending
type: filter
name: Is severity still Pending?
description: >-
Continues only when the incident was resolved with a Pending severity. Change the regex
to also block other severities, for example '(?i)^(pending|unknown)$'.
inputs:
condition: "resources.incident.event.severity.matches('(?i)^pending$')"
- id: reopen
type: incident.set-field
name: Revert the status change
description: Sets the incident back to the status it had before it was resolved. No changes needed.
inputs:
incidentID: '${inputs.data.incidentID}'
field: 'status'
value: '${inputs.data.previousStatus}'
- id: explain-on-timeline
type: incident.add-note
name: Explain on the timeline
description: Adds a timeline note that explains why the incident was reopened. Edit the wording to match your policy.
inputs:
incidentID: '${inputs.data.incidentID}'
message: 'This incident was reopened automatically because it was resolved while its severity was still **Pending**. Set a severity, then resolve it again.'
- id: has-slack-channel
type: filter
name: Has an incident channel?
description: Stops here when the incident has no linked Slack channel. No changes needed.
inputs:
condition: "has(resources.incident.event.slackChannelID)"
- id: tell-the-channel
type: slack.message.post
name: Tell the incident channel
description: Explains the reopen in the incident Slack channel. Edit the wording to match your policy.
inputs:
channelID: '${resources.incident.event.slackChannelID}'
messageText: ':warning: This incident was reopened because it was resolved with severity *Pending*. Set a severity on the <${resources.incident.event.overviewURL}|incident page>, then resolve it again.'How it works
This section explains when the workflow runs and how its steps work together.
When it runs
This blueprint starts on the grafana_irm_app.incident.updated event.
Its trigger filter starts a run only when this CEL expression is true:
inputs.data.eventKind == 'incident_updated_status' && inputs.data.newStatus == 'resolved'It runs at most once for each run-once key. This blueprint’s key is enforce-severity:${inputs.data.incidentID}:${has(inputs.data.closedTime) ? inputs.data.closedTime : ''}, so a later event with the same key doesn’t start another run. For details, refer to Deduplicate workflow runs.
How the steps fit together
These notes cover how the steps connect and which Workflows behaviors the blueprint relies on.
- Triggers on incident status changes (
eventKindincident_updated_status) that move an incident to the resolved status category. - The event carries
newStatusandpreviousStatusas status categories (active or resolved), plusclosedTime. - A filter step checks the severity on the auto-loaded incident at
resources.incident.event. - Severity is matched case-insensitively with
matches('(?i)^pending$')because CEL has no lowercase function. - When severity is Pending, the workflow sets the status back to the previous category, adds a timeline note, and posts in the incident Slack channel when one exists.
- Reopening emits another status event, but its
newStatusis active, so the trigger filter ignores it and there is no loop. - IRM can emit two status events for one resolution, so
runOnceForkeys on the incident ID plusclosedTime, which both events share. - A later resolution has a new
closedTime, so it is checked again. runOnceForis rendered for every incident event before the trigger filter runs, sohas()supplies an empty value for events withoutclosedTime.- Customize the note and Slack message text.
Next steps
Was this page helpful?
Related resources from Grafana Labs


