Step and trigger types reference
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.
This reference lists the step types and trigger types you can use in Grafana Workflows, with their inputs, outputs, and configuration.
Step types
Steps are the individual actions in a workflow.
They execute in order from first to last.
Each step has a type, an ID, and a set of inputs.
Every step produces outputs that later steps can reference through the workflow context using CEL expressions, for example, ${steps['my-step'].outputs.responseBody}.
Step IDs that contain a hyphen need bracket notation, as in this example, because CEL reads a hyphen after a dot as subtraction.
For details on connecting steps with the workflow context, refer to Use CEL expressions.
General
General steps make HTTP calls and run code.
HTTP call (http.call)
Send an HTTP request to a public URL and return the response status code, body, and headers. Supports bearer token and basic authentication using secrets.
The step only calls public addresses. Requests to private or internal network addresses are blocked. Each request times out after 30 seconds and follows up to 5 redirects. The request body can be up to 1 MiB. A response body longer than 1 MiB is truncated to 1 MiB.
A 4xx or 5xx response doesn’t fail the step.
To act on an error response, check responseCode in a later step, for example, in a filter step.
Inputs:
Outputs:
Execute code (code.execute)
Run sandboxed code inside a workflow.
Your code reads the workflow context from the context variable and the named arguments from the args variable.
Code runs in an isolated sandbox with no network access and a temporary filesystem.
Currently supported languages: Python.
Inputs:
Outputs:
Injected variables:
Two variables are automatically available inside the sandbox:
The context variable has the following structure:
{
"inputs": { },
"steps": {
"step-id": {
"outputs": { }
}
},
"resources": {
"incident": { },
"alertgroup": { }
}
}context["inputs"]contains the trigger event data or manual test input.context["steps"]contains outputs from all previously executed steps, keyed by step ID.context["resources"]contains loaded resource data (incidents, alert groups).
Example: process data from a previous step
This example shows a workflow where a code step reads the response from an earlier HTTP call, processes it, and outputs structured JSON for a downstream filter step:
steps:
- id: fetch-status
type: http.call
name: "Get service status"
inputs:
method: "GET"
url: "https://api.example.com/status"
- id: analyze
type: code.execute
name: "Analyze status response"
inputs:
language: python
code: |
import json
response = context["steps"]["fetch-status"]["outputs"]["responseBody"]
data = json.loads(response)
unhealthy = [s for s in data.get("services", []) if s["status"] != "healthy"]
threshold = args.get("threshold", 1)
print(json.dumps({
"unhealthy_count": len(unhealthy),
"unhealthy_services": [s["name"] for s in unhealthy],
"should_alert": len(unhealthy) >= threshold,
}))
args: '{"threshold": 1}'
- id: check-alert
type: filter
name: "Alert if threshold exceeded"
inputs:
condition: "json_parse(steps['analyze'].outputs.stdout).should_alert == true"Example: scheduled check
steps:
- id: run-check
type: code.execute
inputs:
language: python
code: |
has_inputs = len(context.get("inputs", {})) > 0
print(f"Scheduled run, has trigger inputs: {has_inputs}")Later steps reference code output using CEL expressions, for example, ${steps['analyze'].outputs.stdout}.
Flow control
Flow control steps transform data, stop runs, branch, and pause.
Transform (transform)
Evaluate a template string with embedded CEL expressions to generate dynamic content.
Use ${expression} syntax to embed expressions that reference workflow inputs and previous step outputs.
Inputs:
Outputs:
Filter (filter)
Gate workflow execution on a CEL condition.
If the condition evaluates to false, the workflow stops and no further steps execute.
Inputs:
Outputs:
Switch (switch)
Conditionally execute different sets of steps based on CEL expressions.
Each branch has a condition and its own list of steps.
The first branch whose condition evaluates to true runs.
Include a default branch with no condition as a fallback.
Branches:
A switch step uses a branches array instead of inputs.
Each branch has a condition (a CEL expression) and a steps list.
Omit the condition to mark a branch as the default fallback.
- id: route-by-severity
type: switch
branches:
- condition: "resources.incident.event.severity.matches('(?i)^critical$')"
steps:
- id: page-oncall
type: irm.page-team
inputs:
teamIdentifier: "platform"
identifierType: "name"
- steps:
- id: post-update
type: slack.message.post
inputs:
channelID: "C0123456789"
messageText: "Non-critical incident received"Outputs:
Wait (wait)
Pause workflow execution for a specified number of seconds.
Inputs:
Outputs:
Incident
Incident steps operate on incidents in Grafana IRM. You can pass incident IDs directly or reference them from incident resources loaded into the workflow context. For details on loading incident data, refer to Load incident data.
Create incident (incident.create)
Create a new IRM incident with a title, severity, and optional labels.
Inputs:
Outputs:
Add participant to incident (incident.add-participant)
Add a user to an IRM incident with a specific role.
Inputs:
Outputs:
Set incident field (incident.set-field)
Update a field on an IRM incident, including title, status, severity, or role assignments.
Inputs:
Outputs:
Create incident Slack channel (incident.slack-channel.create)
Create a Slack channel for an IRM incident.
Inputs:
Outputs:
Add note to incident (incident.add-note)
Post a note to an IRM incident’s timeline. Use this for routine progress notes. Use incident.add-key-update
for significant milestones.
Inputs:
Outputs:
Add key update to incident (incident.add-key-update)
Post a key update (a significant milestone) to an IRM incident. Key updates appear as headline entries on the incident timeline and stakeholder-facing views.
Inputs:
Outputs:
Slack
Slack steps manage channels and send messages in your connected Slack workspace.
Create Slack channel (slack.channel.create)
Create a new public or private Slack channel.
Inputs:
Outputs:
Post message to Slack channel (slack.message.post)
Post a message to a Slack channel. Supports plain text, Block Kit blocks for rich formatting, attachments, and threaded replies.
Inputs:
Outputs:
Archive Slack channel (slack.channel.archive)
Archive a Slack channel.
Inputs:
Outputs:
Add bookmark to Slack channel (slack.channel.add-bookmark)
Add a bookmark link to a Slack channel.
Inputs:
Outputs:
Add users to Slack channel (slack.channel.add-users)
Invite users to an existing Slack channel.
You can identify each user by their Slack user ID or their email address, and you can mix both in one list.
Workflows looks up each email address in Slack. If an email address doesn’t match a Slack user, the step fails and the error lists the unmatched addresses.
If you set users with an expression and a step output already contains a list, wrap it in json_stringify().
For example, ${json_stringify(steps.oncall.outputs.users.map(u, u.email))} uses the email addresses from a step with the ID oncall, such as Get on-call users from a schedule.
Inputs:
Outputs:
Send Slack direct message (slack.direct-message.send)
Send a direct message to up to 8 Slack users.
If you select more than one user, everyone receives the same message in a single group direct message.
You can identify each user by their Slack user ID or their email address, and you can mix both in one list.
Workflows looks up each email address in Slack. If an email address doesn’t match a Slack user, the step fails and the error lists the unmatched addresses.
If you set users with an expression and a step output already contains a list, wrap it in json_stringify().
For example, ${json_stringify(steps.oncall.outputs.users.map(u, u.email))} uses the email addresses from a step with the ID oncall, such as Get on-call users from a schedule.
Inputs:
Outputs:
IRM
IRM steps page users and teams, invite users to incidents and alert groups, and look up who’s on call.
Page user via IRM (irm.page-user)
Create an IRM escalation to page a user by email address.
Inputs:
Outputs:
Page team via IRM (irm.page-team)
Create an IRM escalation to page an entire team. You can also associate the escalation with an incident, which invites the team to join it, and add a message.
Inputs:
Outputs:
Invite user to incident (irm.invite-user-to-incident)
Create an IRM escalation to invite a user to an incident.
Inputs:
Outputs:
Invite user to alert group (irm.invite-user-to-alert-group)
Create an IRM escalation to invite a user to an alert group.
Inputs:
Outputs:
Get on-call users from a schedule (irm.schedule-current-oncall)
Look up the users currently on call for an IRM schedule. Use the result in later paging or notification steps.
Inputs:
Outputs:
Get on-call users for a team (irm.team-current-oncall)
Look up the users currently on call for a team, using the team’s direct paging integration. Use this step when you want to notify whoever is on-call for a team without specifying a schedule.
Inputs:
Outputs:
Microsoft Teams
Steps that post messages to or create resources in Microsoft Teams.
Prerequisites:
Before using any Microsoft Teams step, install the Microsoft Teams app through Grafana IRM integrations and set up at least one hook for it. This connects your Grafana Cloud stack to your Microsoft Teams tenant. After the connection exists, you can turn off or remove the hook.
The msteams.meeting.create step needs the Calendars.ReadWrite application permission on the app registration
used by your Microsoft Teams integration, with admin consent granted. New installs of the Microsoft Teams app
request this permission and grant consent automatically, so you only need to add it if you installed the app before
Workflows supported msteams.meeting.create. In that case, add the permission in the app registration’s API
permissions page and grant admin consent for it. No additional Teams-specific admin setup is required.
Create Teams meeting (msteams.meeting.create)
Create a Microsoft Teams online meeting on behalf of an organizer. The meeting is added to the organizer’s Outlook
calendar. Requires the Calendars.ReadWrite Microsoft Entra ID application permission. Refer to the Prerequisites above.
The calendar event shows the organizer as free, so it doesn’t block their time or conflict with other meetings.
To compute startDateTime or endDateTime relative to another timestamp, use the CEL timestamp() and
duration() functions, for example, ${timestamp(inputs.time) + duration('1h')}. Refer to
Use CEL expressions.
Inputs:
Outputs:
Post message to Teams channel (msteams.message.post)
Post a text message or Adaptive Card to a Microsoft Teams channel.
At least one of messageText or adaptiveCard is required.
To reply in a thread, pass conversationID and threadActivityID from a previous msteams.message.post step.
Inputs:
Outputs:
Grafana Assistant
Steps that send a prompt to the Grafana Assistant and return structured output.
Ask Assistant (assistant.prompt)
Send a prompt to the assistant and receive structured JSON output conforming to a provided schema.
If the assistant’s response doesn’t parse as JSON or doesn’t validate against outputSchema, the step
sends a follow-up prompt asking the assistant to correct its response.
If the chat request itself fails, the step sends the same prompt again.
Both kinds of retry count toward maxRetries.
When the retries run out, the step fails and the run stops. The run error includes the last error and the beginning of the assistant’s last response.
Prerequisites:
Grafana Assistant must be in use on your stack.
The person whose permissions the run uses needs the grafana-assistant-app.chats:access permission. For details, refer to Manage access.
Inputs:
Outputs:
Trigger types
Triggers define when a workflow starts. You configure triggers in the startWhen section of a workflow definition.
For details on configuring triggers, refer to Configure triggers.
Event trigger
An event trigger starts a workflow when an incoming event matches a regular expression pattern.
Events are named according to the pattern {app}.{resource-type}.{event-type}, for example, grafana_irm_app.incident.updated.
You define event triggers using matching rules. Each rule contains a regular expression that’s tested against the event name. If any rule matches, the workflow starts.
Configuration:
Example:
startWhen:
matchingRules:
- eventNameRegex: "grafana_irm_app\\.incident\\.updated"
- eventNameRegex: "grafana_irm_app\\.alertgroup\\.updated"Available event sources
The following table lists the event sources that can trigger workflows:
Schedule trigger
A schedule trigger starts a workflow at recurring times using a cron expression.
Schedules use the standard five-field Unix cron format.
They run in UTC unless the expression starts with CRON_TZ=<ZONE>.
For details, refer to Run a schedule in a specific timezone.
Configuration:
Example:
startWhen:
schedules:
- "0 9 * * 1-5"
- "0 0 1 * *"A workflow can have multiple schedules. Each schedule triggers the workflow independently.
Cron field reference:
Manual trigger
A manual trigger starts a workflow from the editor on demand. You can trigger any workflow manually, whether or not it has event or schedule triggers.
To trigger a workflow manually in the editor, click Run and provide event data in CloudEvents format in the Trigger Workflow dialog box. For details, refer to Configure triggers.
Manual-only workflows have an empty startWhen section:
startWhen:
matchingRules: []
schedules: []Combine triggers
A workflow can have both event and schedule triggers. The workflow starts when any matching rule matches an incoming event or when any schedule fires.
startWhen:
matchingRules:
- eventNameRegex: "grafana_irm_app\\.incident\\.updated"
schedules:
- "0 9 * * 1-5"

