Grafana Cloud
Last reviewed: May 21, 2026

Create workflows

Note

Grafana Workflows is currently in private preview. Grafana Labs offers support on a best-effort basis, and breaking changes might occur prior to the feature being made generally available.

You can create and edit workflows using the visual editor in the Grafana UI or by writing definitions in YAML or JSON. This page covers both approaches, including how to add steps, configure fields, and define conditional branches.

Before you begin

To create workflows, you need:

Create a workflow in the editor

The workflow editor provides a visual canvas for building workflows. The editor has three areas: a tree canvas on the left that shows the workflow structure, a configuration panel on the right for editing the selected node, and a header with controls for saving, running, and enabling the workflow.

Choose a trigger

When you create a new workflow, the first step is to choose a trigger. The editor presents three options:

  • Event: React to events matching a regex pattern, for example, grafana_irm_app\.incident\.updated.
  • Schedule: Run on a cron schedule in UTC, for example, 0 9 * * 1-5 for weekdays at 9:00 AM.
  • Manual: Trigger the workflow from the editor.

Select a trigger type and configure its settings in the configuration panel. For details on trigger options, refer to Configure triggers.

Add steps

To add a step to your workflow:

  1. Click + on the last node in the tree.
  2. Browse or search the action palette that appears in the configuration panel.
  3. Click a step type or drag it onto the drop zone.

The new step appears in the tree and the configuration panel displays its configuration form. Fill in the required fields for the step type you selected.

For a full list of available step types and their inputs, refer to Step types reference.

Configure step fields

The configuration panel renders form fields based on the step type. Field types include text inputs, text areas for longer content like message bodies, checkboxes for boolean values, dropdowns for constrained choices like HTTP methods, and JSON editors for structured data.

Fields that accept string values can include CEL expressions using ${expression} syntax to reference the workflow context. For example, you can set a URL field to https://api.example.com/incidents/${inputs.data.incidentID} to dynamically include the incident ID from the triggering event.

For details on expressions and the workflow context, refer to Use CEL expressions.

Add conditional logic

To add conditional branching:

  1. Add a Switch step from the action palette.
  2. The switch node appears in the tree. Click + on it to add condition branches.
  3. Select each condition node and enter a CEL expression in the configuration panel, for example, inputs.data.severity == "critical".
  4. Add steps inside each condition branch by clicking + on the condition node.
  5. A branch with no condition expression acts as the default case.

After all branches have at least one step, a down-arrow appears on the switch node. Click it to add continuation steps that run after the switch completes, regardless of which branch executed.

For the field-by-field schema, refer to Switch step.

Run a workflow on demand

Click Run in the editor header to trigger the workflow with a sample event. The Trigger Workflow dialog opens with a placeholder event in CloudEvents shape. Edit the JSON as needed, then click Trigger Workflow.

The fields under data become available in your steps as inputs.data.*. The other fields (id, type, source, time) describe the event itself. To inspect the run, click the arrow next to Run to open the Latest runs panel.

View the JSON definition

Open the More menu in the editor header and select View JSON to open a read-only drawer showing the workflow definition as JSON. This view is useful for reviewing the full structure or copying the definition for use in version control.

Write a workflow definition

You can edit a workflow as YAML or JSON instead of using the visual editor. This approach is useful for review and copy-paste workflows, and for keeping a record of a definition outside of Grafana.

To edit a workflow’s YAML or JSON in the editor, open the More menu in the editor header and select View JSON. The drawer that opens is read-only today; copy the definition out, edit it, and paste it back into a new workflow to apply changes through the editor.

Note

A programmatic API for managing workflow definitions outside the Workflows app is not supported during private preview.

Understand the definition structure

The following example shows the top-level structure of a workflow definition:

YAML
apiVersion: workflows.ext.grafana.com/v1alpha1
kind: Definition
metadata:
  name: my-workflow
  namespace: my-namespace
spec:
  name: 'My Workflow'
  enabled: true
  startWhen:
    matchingRules: []
    schedules: []
  steps: []
  resources:
    secrets: {}
    incidents: {}
    alertgroups: {}
  runOnceFor: ''
  • name: A human-readable name for the workflow.
  • enabled: When true, the workflow runs automatically when its trigger conditions are met. When false, the workflow can only run through manual triggers or test execution.
  • startWhen: Defines the trigger conditions. Contains matchingRules for event triggers and schedules for cron triggers. For details, refer to Configure triggers.
  • steps: An ordered list of steps that execute sequentially.
  • resources.secrets: An optional map of reference names to secret URIs for authentication. For details, refer to Manage secrets.
  • resources.incidents: An optional map of reference names to incident identifiers. Values can be literal IDs or CEL expressions. For details, refer to Load incident data.
  • resources.alertgroups: An optional map of reference names to alert group identifiers. Values can be literal IDs or CEL expressions. For details, refer to Load alert group data.
  • runOnceFor: An optional template string for deduplication. Use ${...} segments for CEL expressions. For details, refer to Configure triggers.

Note

The editor’s Settings drawer currently exposes UI inputs for resources.secrets and resources.incidents only. To declare resources.alertgroups for a workflow today, edit the YAML directly through the More > View JSON drawer or by importing a YAML definition.

Define steps

Each step requires a type, an id, and typically a set of inputs:

YAML
steps:
  - id: call-api
    type: http.call
    name: 'Fetch incident details'
    inputs:
      method: 'GET'
      url: 'https://api.example.com/incidents/${inputs.data.incidentID}'

Step IDs must start with a lowercase letter and can contain lowercase letters, numbers, hyphens, and underscores.

Run custom code

Use the code.execute step to run sandboxed Python code. The sandbox automatically injects a context variable containing the workflow execution context (trigger inputs, previous step outputs, and resolved resources) and an args variable containing any named arguments you define.

YAML
steps:
  - id: fetch-data
    type: http.call
    name: 'Fetch incident data'
    inputs:
      method: 'GET'
      url: 'https://api.example.com/incidents/${inputs.data.incidentID}'

  - id: process-incident
    type: code.execute
    name: 'Summarize incident'
    inputs:
      language: python
      code: |
        import json

        response = json.loads(context["steps"]["fetch-data"]["outputs"]["responseBody"])
        labels = response.get("labels", [])
        severity = args.get("default_severity", "unknown")

        for label in labels:
            if label.startswith("severity/"):
                severity = label.split("/")[1]

        print(json.dumps({
            "title": response["title"],
            "severity": severity,
            "label_count": len(labels),
        }))
      args:
        default_severity: "${inputs.data.severity}"

  - id: post-summary
    type: slack.message.post
    inputs:
      channelID: 'C0123456789'
      messageText: "Incident summary: ${steps['process-incident'].outputs.stdout}"

The code step captures stdout as its primary output. Write structured data as JSON to stdout so downstream steps can reference it. stderr is available separately for diagnostics. For the full list of inputs, outputs, and the context variable structure, refer to Execute code in the step types reference.

Define branches

Use the switch step type with branches to add conditional logic:

YAML
steps:
  - id: route-by-severity
    type: switch
    branches:
      - condition: "inputs.data.severity == 'critical'"
        steps:
          - id: page-oncall
            type: irm.page-user
            inputs:
              userID: "oncall@example.com"
              important: true
              message: "Critical incident: ${inputs.data.title}"
      - condition: "inputs.data.severity == 'warning'"
        steps:
          - id: notify-channel
            type: slack.message.post
            inputs:
              channelID: 'C0123456789'
              messageText: 'Warning: ${inputs.data.title}'
      - steps:
          - id: log-event
            type: transform
            inputs:
              template: 'Non-actionable severity: ${inputs.data.severity}'

Branches evaluate in order. The first branch whose condition evaluates to true runs. A branch with no condition field acts as the default case. Branches can be nested for complex routing logic.

For the field-by-field schema, refer to Switch step.

Next steps