---
title: "Learn: expressions and branching | Grafana Cloud documentation"
description: "A runnable tour of CEL expressions, step outputs, switch branches, and filters. No setup or integrations needed. Click Run and try different payloads."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Learn: expressions and branching

> Note
> 
> Grafana Workflows is currently in [public preview](https://grafana.com/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.

A runnable tour of CEL expressions, step outputs, switch branches, and filters. No setup or integrations needed. Click Run and try different payloads.

This Grafana Workflows blueprint is in the **Basics** category of the Blueprints library.

## Before you begin

This blueprint needs no integrations or secrets.

## Steps

Steps run in order from first to last. A step inside a switch branch runs only when Workflows chooses that branch.

Expand table

| Step                                        | ID               | Type        | Description                                                                                                                                       |
|---------------------------------------------|------------------|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| Build a greeting                            | `greeting`       | `transform` | Shows `${...}` interpolation, `has()` for optional fields, the ternary operator, and `now()`. Run it with and without a name in the payload data. |
| Branch on priority                          | `classify`       | `switch`    | Runs the first branch whose condition is true, or the default branch when none match. Try priority high, low, or leave it out.                    |
| High priority path (branch 1 of `classify`) | `high-priority`  | `transform` | Runs only when priority is high. It can read greeting because greeting ran before the switch.                                                     |
| Low priority path (branch 2 of `classify`)  | `low-priority`   | `transform` | Runs only when priority is low.                                                                                                                   |
| Default path (default branch of `classify`) | `no-priority`    | `transform` | The default branch, with no condition. Runs when no other branch matches.                                                                         |
| Continue only if notify is true             | `only-if-notify` | `filter`    | Ends the run here, successfully, unless the payload sets notify to true. Set `failOnExit` to true to make it fail instead.                        |
| Summarize the run                           | `summary`        | `transform` | Reads the output of an earlier top-level step and the switch output that says which branch ran.                                                   |

For the inputs and outputs of each step type, refer to [Step and trigger types reference](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/step-trigger-types).

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](https://grafana.com/docs/grafana-cloud/platform/workflows/as-code).

YAML ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```yaml
apiVersion: workflows.ext.grafana.app/v1alpha1
kind: Definition
metadata:
  name: learn-expressions-and-branching
  annotations:
    grafana.app/folder: <FOLDER_UID>
spec:
  name: 'Learn: expressions and branching'
  enabled: false
  startWhen:
    matchingRules: []
    schedules: []
  steps:
    - id: greeting
      type: transform
      name: Build a greeting
      description: >-
        Shows ${...} interpolation, has() for optional fields, the ternary operator, and now().
        Run it with and without a name in the payload data.
      inputs:
        template: "Hello ${has(inputs.data.name) ? inputs.data.name : 'there'}! This run started at ${now()}."
    - id: classify
      type: switch
      name: Branch on priority
      description: Runs the first branch whose condition is true, or the default branch when none match. Try priority high, low, or leave it out.
      branches:
        - condition: "has(inputs.data.priority) && inputs.data.priority == 'high'"
          steps:
            - id: high-priority
              type: transform
              name: High priority path
              description: Runs only when priority is high. It can read greeting because greeting ran before the switch.
              inputs:
                template: 'High priority. ${steps.greeting.outputs.result}'
        - condition: "has(inputs.data.priority) && inputs.data.priority == 'low'"
          steps:
            - id: low-priority
              type: transform
              name: Low priority path
              description: Runs only when priority is low.
              inputs:
                template: 'Low priority, nothing urgent.'
        - steps:
            - id: no-priority
              type: transform
              name: Default path
              description: The default branch, with no condition. Runs when no other branch matches.
              inputs:
                template: 'No priority set, using the default path.'
    - id: only-if-notify
      type: filter
      name: Continue only if notify is true
      description: Ends the run here, successfully, unless the payload sets notify to true. Set failOnExit to true to make it fail instead.
      inputs:
        condition: 'has(inputs.data.notify) && inputs.data.notify == true'
    - id: summary
      type: transform
      name: Summarize the run
      description: Reads the output of an earlier top-level step and the switch output that says which branch ran.
      inputs:
        template: "${steps.greeting.outputs.result} Branch index: ${string(steps.classify.outputs.matchedBranchIndex)}."
```

## How it works

This section explains when the workflow runs and how its steps work together.

### When it runs

This blueprint has no event or schedule trigger, so it runs only when you start it manually.

### How the steps fit together

These notes cover how the steps connect and which Workflows behaviors the blueprint relies on.

- Manual-only workflow (no matching rules, no schedules) that needs no integrations, so it can be run from the editor right away.
- Suggested test payload data: {“name”: “Ada”, “priority”: “high”, “notify”: true}.
- It shows: `${...}` interpolation in a transform; `has()` with the ternary operator for optional fields; `now()` for the run time; reading a prior step’s output with `steps.<id>.outputs.<field>`, and bracket notation for hyphenated IDs; a switch whose first matching branch runs, with a default branch; and a filter that ends the run early when its condition is false.
- Steps after the switch cannot read outputs from steps inside its branches, so the final step reads only top-level steps.
- Use it as a reference for expression syntax.

## Next steps

- [Blueprints](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/blueprints)
- [Start from a blueprint](https://grafana.com/docs/grafana-cloud/platform/workflows/build/use-blueprints)
- [Manage workflows as code](https://grafana.com/docs/grafana-cloud/platform/workflows/as-code)
- [Step and trigger types reference](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/step-trigger-types)
