# Workflow Examples

{% hint style="warning" %}
Workflows are getting an upgrade: meet [Notification Routes](/use-groundcover/monitors/notification-routes.md)
{% endhint %}

This page provides practical examples of workflows for different use cases and integrations.

## Triggers Examples

### Filter by Monitor Name

This example shows how to create a workflow that only triggers for a specific monitor (by its name):

```yaml
workflow: 
  id: specific-monitor-workflow
  description: Workflow triggered only by Workload Pods Crashed Monitor
  triggers:
    - type: alert
      filters:
        - key: alertname
          value: Workload Pods Crashed Monitor
```

### Filter by Environment

Execute only on the Prod environment. The "env" attribute needs to be part of the monitor context attributes (either by using it in the group by section or by explicitly adding it as a context label):

```yaml
workflow: 
  id: prod-only-workflow
  description: Workflow triggered only by production environment alerts
  triggers:
    - type: alert
      filters:
        - key: env
          value: prod
```

### Filter by Multiple Conditions

This example shows how to combine multiple filters. In this case it will match events from the prod environment and also monitors that explicitly routed the workflow with the name "actual-name-of-workflow":

```yaml
workflow: 
  id: multi-filter-workflow
  description: Workflow triggered by critical alerts in production
  triggers:
    - type: alert
      filters:
        - key: env
          value: prod
        - key: annotations.multi-filter-workflow
          value: enabled
```

### Filter by Regex

In this case we will use a regular expression to filter on events coming from the groundcover OR monitoring namespaces. Note that any regular expression can be used:

```yaml
workflow: 
  id: regex-filter-workflow
  description: Workflow triggered by alerts from groundcover or monitoring namespaces
  triggers:
    - type: alert
      filters:
        - key: namespace
          value: r"(groundcover|monitoring)"
        - key: annotations.regex-filter-workflow
          value: enabled          
```

## Consts Examples

The consts section is the best location to create pre-defined attributes and apply different transformations on the monitor's metadata for formatting the notification messaging.

### Map Severities

Severities in your notified destination may not match the groundcover predefined severities. By using a dictionary, you can map any groundcover severity value to another, and extract it by using the actual monitor severity. Use the "keep.dictget" function to extract from a dictionary and apply a default in case the value is missing.

<pre class="language-yaml"><code class="lang-yaml">workflow:
  id: severity-mapping-example
  description: Example of mapping severities using consts
  triggers:
    - type: alert
<strong>      filters:
</strong>        - key: annotations.severity-mapping-example
          value: enabled            
  consts:
    severities: '{"S1": "P1","S2": "P2","S3": "P3","S4": "P4","critical": "P1","error": "P2","warning": "P3","info": "P4"}'
    severity: keep.dictget({{ consts.severities }}, {{ alert.annotations._gc_severity }}, "P3")
</code></pre>

### Best Practice for Accessing Monitor Labels

When accessing a context label via `alert.labels`, if this label is not transferred within the monitor - the workflow might crash. Best practice to pre-define labels is to declare them in the consts section with a default value, using "keep.dictget" so the value is gracefully pulled from the labels object.

```yaml
workflow:
  id: labels-best-practice-example
  description: Example of safely accessing monitor labels
  triggers:
    - type: alert
      filters:
        - key: annotations.labels-best-practice-example
          value: enabled            
  consts:
    region: keep.dictget({{ alert.labels }}, "cloud.region", "")
```

> **Note**: Label names that are dotted, like "cloud.region" in this example, cannot be referenced in the monitor itself and can only be retrieved using this technique of pulling the value with "keep.dictget" from the alert.labels object.

### Additional Useful Functions

* **`keep.dict_pop({{alert.labels}}, "_gc_monitor_id", "_gc_monitor_name", "_gc_severity", "backend_id", "grafana_folder", "_gc_issue_header")`** - "Clean" a key-value dictionary from some irrelevant values (keys). In this case, the groundcover labels dictionary has some internal keys that you might not want to include in your notification content.
* **`keep.join(["a", "b", "c"], ",")`** - Joins a list of elements into a string using a given delimiter. In this case the output is "a,b,c".

## Action Examples

### Conditional Statements

Use "if" condition to apply logic on different actions.

Create a separate block for a firing monitor (a resolved monitor can use different logic to change formatting of the notification):

```yaml
workflow:
  id: conditional-actions-example
  description: Example of conditional actions based on alert status
  triggers:
    - type: alert
      filters:
        - key: annotations.conditional-actions-example
          value: enabled                
  actions:
    - if: '{{ alert.status }} == "firing"'
      name: slack-action-firing
      provider:
        config: '{{ providers.groundcover-alerts-dev }}'
        type: slack
        with:
          attachments:
          - color: '{{ consts.red_color }}'
            footer: '{{ consts.footer_url }}'
            footer_icon: '{{ consts.footer_icon }}'
            text: '{{ consts.slack_message }}'
            title: 'Firing: {{ alert.alertname }}'
            title_link: '{{ consts.title_link }}'
            ts: keep.utcnowtimestamp()
            type: plain_text
          message: ' '
```

"If" statements can include and/or logic for multiple conditions:

```yaml
workflow:
  id: multi-condition-actions-example
  description: Example of multiple conditions in actions
  triggers:
    - type: alert
      filters:
        - key: annotations.multi-condition-actions-example
          value: enabled                    
  actions:
    - if: '{{ alert.status }} == "firing" and {{ alert.labels.namespace }} == "namespace1"'
      name: slack-action-firing
      provider:
        config: '{{ providers.groundcover-alerts-dev }}'
        type: slack
        with:
          attachments:
          - color: '{{ consts.red_color }}'
            footer: '{{ consts.footer_url }}'
            footer_icon: '{{ consts.footer_icon }}'
            text: '{{ consts.slack_message }}'
            title: 'Firing: {{ alert.alertname }}'
            title_link: '{{ consts.title_link }}'
            ts: keep.utcnowtimestamp()
            type: plain_text
          message: ' '
```

### Notification by Specific Hours

Use the function `keep.is_business_hours` combined with an "if" statement to trigger an action within specific hours only.

In this example the action block will execute on Sundays (6) between 20-23 (8pm to 11pm) or on Mondays (0) between 0-1am:

```yaml
workflow:
  id: time-based-notification-example
  description: Example of time-based conditional actions
  triggers:
    - type: alert
      filters:
        - key: annotations.time-based-notification-example
          value: enabled                    
  actions:
    - if: '({{ alert.status }} == "firing" and (keep.is_business_hours(timezone="America/New_York", business_days=[6], start_hour=20, end_hour=23) or keep.is_business_hours(timezone="America/New_York", business_days=[0], start_hour=0, end_hour=1)))'
      name: time-based-notification
      provider:
        type: slack
        config: '{{ providers.slack_webhook }}'
        with:
          message: "Time-sensitive alert: {{ alert.alertname }}"
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.groundcover.com/use-groundcover/workflows/workflow-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
