---
title: "Use CEL expressions | Grafana Cloud documentation"
description: "Use Common Expression Language (CEL) expressions in Grafana Workflows to access event data, reference step outputs, write conditions, and transform data between steps."
---

# Use CEL expressions

> Note
> 
> Grafana Workflows is currently in [private preview](/docs/release-life-cycle/). Grafana Labs offers support on a best-effort basis, and breaking changes might occur prior to the feature being made generally available.

Grafana Workflows uses the [Common Expression Language (CEL)](https://cel.dev/) for dynamic values, conditions, and data transformation. CEL expressions let you reference event data, access outputs from previous steps, write conditional logic, and build dynamic content throughout your workflow.

## Understand the workflow context

The workflow context is the data environment available to every step. It contains three top-level objects that you can reference in CEL expressions:

- **`inputs`** : The event data that triggered the workflow.
- **`steps`** : The outputs from each previously executed step, keyed by step ID.
- **`resources`** : Resolved resource values, including decrypted secrets, loaded incident data, and loaded alert group data.

Each step can read from the context and writes its outputs back to the context for later steps to use.

## Embed expressions in step inputs

Embed CEL expressions in step input values using `${expression}` syntax:

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

```yaml
inputs:
  messageText: "Incident ${inputs.data.incidentID} has severity ${inputs.data.severity}"
```

You can mix literal text with multiple expressions in a single field. The engine evaluates each expression and substitutes the result into the string.

To include a literal `${` in the output, escape it with `$${`:

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

```yaml
inputs:
  template: "Use $${variable} for shell variables"
```

## Access event data

When an event triggers a workflow, the event payload is available through `inputs`. The fields depend on the event source.

For example, to use the incident ID from a triggering event in an HTTP request:

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

```yaml
inputs:
  url: "https://api.example.com/incidents/${inputs.data.incidentID}"
```

## Access step outputs

Each step stores its outputs under `steps.{step-id}.outputs`. Later steps can reference these values to chain actions together.

The following example fetches data from an API and posts the response to Slack:

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

```yaml
steps:
  - id: fetch-data
    type: http.call
    inputs:
      method: "GET"
      url: "https://api.example.com/data"

  - id: post-results
    type: slack.message.post
    inputs:
      channelID: "C0123456789"
      messageText: "API returned: ${steps.fetch-data.outputs.responseBody}"
```

When a step ID contains hyphens, use bracket notation:

text ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```text
${steps['fetch-data'].outputs.responseBody}
```

For details on the outputs each step type produces, refer to [Step types reference](/docs/grafana-cloud/alerting-and-irm/workflows/reference).

## Access incident and alert group data

Workflows that trigger on incident events automatically load the full incident into the context at `resources.incident.event`. Similarly, workflows triggered by alert group events automatically load the alert group at `resources.alertgroup.event`. You can also declare additional resources in the `resources.incidents` or `resources.alertgroups` sections of the definition.

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

```yaml
inputs:
  message: "Incident ${resources.incident.event.title} is ${resources.incident.event.status}"
  severity: "${resources.incident.event.severity}"
```

For alert groups:

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

```yaml
inputs:
  message: "Alert group ${resources.alertgroup.event.title} is ${resources.alertgroup.event.state}"
  count: "${resources.alertgroup.event.alerts_count}"
```

For workflows with explicitly declared resources, use the reference name you defined:

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

```yaml
inputs:
  relatedTitle: "${resources.incident.related.title}"
  alertGroupState: "${resources.alertgroup.current.state}"
```

For details on declaring resources, refer to [Load incident data](/docs/grafana-cloud/alerting-and-irm/workflows/load-incident-data) and [Load alert group data](/docs/grafana-cloud/alerting-and-irm/workflows/load-alert-group-data).

## Write conditions

CEL supports standard comparison and logical operators for use in `filter` steps and `switch` branch conditions:

text ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```text
inputs.data.severity == "critical"
inputs.data.count > 10
inputs.data.status == "active" && inputs.data.priority == "high"
inputs.data.region == "us" || inputs.data.region == "eu"
```

A `filter` step evaluates a condition and stops the workflow if the result is `false`. A `switch` step evaluates branch conditions in order and runs the first matching branch.

For details on how to use filter and switch steps, refer to [Create workflows](/docs/grafana-cloud/alerting-and-irm/workflows/create-workflows).

## Use built-in functions

Workflows extends CEL with custom functions for working with JSON data:

Expand table

| Function                | Description                                  | Example                                           |
|-------------------------|----------------------------------------------|---------------------------------------------------|
| `json_parse(string)`    | Parse a JSON string into a structured object | `json_parse(steps.api.outputs.responseBody).name` |
| `json_stringify(value)` | Convert a value to a JSON string             | `json_stringify(inputs.data)`                     |

Standard CEL string functions are also available, including `contains`, `startsWith`, `endsWith`, `matches`, and `size`.

## Handle type conversions

JSON numbers deserialize as floating-point values. The CEL environment automatically converts whole-number floats to integers, so expressions like `inputs.data.count > 10` work without explicit type conversion. Cross-type numeric comparisons are enabled.

## Next steps

- [Create workflows](/docs/grafana-cloud/alerting-and-irm/workflows/create-workflows)
- [Configure triggers](/docs/grafana-cloud/alerting-and-irm/workflows/configure-triggers)
- [Load incident data](/docs/grafana-cloud/alerting-and-irm/workflows/load-incident-data)
- [Load alert group data](/docs/grafana-cloud/alerting-and-irm/workflows/load-alert-group-data)
- [Manage secrets](/docs/grafana-cloud/alerting-and-irm/workflows/manage-secrets)
- [Step types reference](/docs/grafana-cloud/alerting-and-irm/workflows/reference)
