---
title: Create your own workflow
source: https://docs.newrelic.com/docs/workflow-automation/create-a-workflow-automation/create-your-own
---

Build custom workflows from scratch when templates don't meet your needs. Use the [create your own](https://onenr.io/0OQM47KgxjG) builder to drag and drop actions from the [actions catalog](https://docs.newrelic.com/docs/workflow-automation/setup-and-configure/actions-catalog/actions-catalog) into automation that matches your process.

## How to use this guide

This guide shows you how to build workflows using concepts and a complete example. Choose your learning path:

-   **Learn core concepts first**: Read [Core concepts](#core-concepts) and [workflow patterns](#workflow-patterns) to understand the fundamentals, then apply them
-   **Follow the example**: Jump to [Example walkthrough](#example-walkthrough) to build an EC2 auto-resize workflow step-by-step
-   **Reference patterns**: Use the [workflow patterns](#workflow-patterns) section as a quick reference when building your own workflows

## Why build custom workflows?

Build your own workflow to:

-   **Implement unique business logic** that templates don't support
-   **Integrate multiple systems** beyond standard templates
-   **Handle complex decisions** with conditional branching
-   **Match your team's process** for approvals and notifications

## Core concepts [#core-concepts]

Understand these fundamentals before you build:

| **Concept**                                                                                                               | **Purpose**                                                                          |
| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| [Inputs and secrets](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/basic-patterns/workflow-inputs) | Parameters for credentials and configuration                                         |
| [Actions](https://docs.newrelic.com/docs/workflow-automation/setup-and-configure/actions-catalog/actions-catalog)         | Pre-built integrations (AWS, Slack, databases, APIs)                                 |
| [Data flow](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/basic-patterns/data-passing)             | Pass outputs between steps                                                           |
| [Assign](https://docs.newrelic.com/docs/workflow-automation/workflow-automation-apis/definition-schema#assign)            | Initialize and assign values to variables for use in subsequent steps                |
| [Switches](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/basic-patterns/conditional-logic)         | Create different paths based on conditions                                           |
| [Loops](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/basic-patterns/loops)                        | Process lists or poll for completion                                                 |
| Range                                                                                                                     | Required parameter for loop functions to define iteration count                      |
| [Wait](https://docs.newrelic.com/docs/workflow-automation/workflow-automation-apis/definition-schema#wait)                | Pauses workflow execution for a specified duration or until a condition is satisfied |
| Stop                                                                                                                      | Terminate workflow execution                                                         |
| [Error](https://docs.newrelic.com/docs/workflow-automation/workflow-automation-apis/definition-schema#error)              | Fail the workflow with a custom message, optionally gated by a condition             |

> #### 💡 TIP
>
> **Learn by doing:** Each concept is demonstrated in the [example walkthrough](#example-walkthrough). You'll see inputs, switches, loops, and approval gates working together in a real workflow.

### Syntax examples

Use these patterns when building workflows:

| **Pattern**                | **Syntax**                                                   | **When to use**                                                         |
| -------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------- |
| Retrieve secret            | `${{ :secrets:awsKeyId }}`                                   | Access credentials from secrets manager                                 |
| Reference workflow input   | `${{ .inputs.region }}`                                      | Use configuration provided when workflow starts                         |
| Use previous step output   | `${{ .steps.getAlert.outputs.entityGuid }}`                  | Pass data between workflow steps                                        |
| Drag action from catalog   | Drag `aws.ec2.stopInstances` into workflow canvas            | Add pre-built integrations to workflow                                  |
| Create variable            | `type: assign` with `inputs:`                                | Store calculated or intermediate values                                 |
| Check condition            | `condition: "${{ ... }}"` within switch                      | Route by `CPU > 90%` vs. `70-90%` vs. `< 70%`                           |
| Loop over items            | `type: loop` with `for` and `in` to iterate over collections | Process lists or poll for completion                                    |
| Define iteration count     | `range(1, 6)` to loop 5 times                                | Required parameter for loop functions                                   |
| Pause execution            | `type: wait` with `seconds: 60` to delay 60 seconds          | Pauses workflow for specified duration                                  |
| End workflow               | Terminate workflow execution                                 | Ends workflow after validation failures or cancellations                |
| Fail workflow with message | `type: error` with `message:` and optional `condition:`      | Stop the workflow with a custom failure message when a condition is met |

For detailed error handling patterns, see [Best practices](https://docs.newrelic.com/docs/workflow-automation/limitations-and-faq/workflow-best-practices#handle-errors).

> #### ⚠️ IMPORTANT
>
> For security and privacy best practices and limitations, including data deletion, see [security best practices](https://docs.newrelic.com/docs/workflow-automation/limitations-and-faq/workflow-best-practices#security).

## Quick start [#quick-start]

Build your first workflow in five steps:

1.  Navigate to **[one.newrelic.com](https://one.newrelic.com) > All Capabilities > Workflow Automation** and select **[Create Your Own](https://onenr.io/0OQM47KgxjG)**
2.  Define parameters for credentials (from [secrets manager](https://docs.newrelic.com/docs/workflow-automation/limitations-and-faq/workflow-best-practices#secure-credentials): `${{ :secrets:keyName }}`), configuration (regions, instance types), and runtime data (account IDs, alert IDs)
3.  Drag actions from the [catalog](https://docs.newrelic.com/docs/workflow-automation/setup-and-configure/actions-catalog/actions-catalog), connect them with `${{ .steps.stepName.outputs.field }}` syntax to pass data
4.  Insert [switches](#conditional-branching-with-switches) for conditional branching, [loops](#loops-for-processing-lists) for processing lists or polling, [approval gates](#approval-gates-and-waiting) for human decisions
5.  Run after each section to catch errors early, then [start or schedule](https://docs.newrelic.com/docs/workflow-automation/manage-workflows/workflow-entity-overview) your workflow

## Key workflow patterns [#workflow-patterns]

Four essential patterns handle most automation scenarios. Each pattern is demonstrated in the [example walkthrough](#example-walkthrough) below.

### Conditional branching with switches

**Use switches when:** Outcomes vary based on data (threshold checks, API responses, user decisions)

**Key syntax:**

```yaml
  - name: hasCompleted
    type: switch
    switch:
      - condition: "${{ .steps.waitForCompletion.outputs.automationExecutionStatus == 'Failed' }}"
        next: displayError
      - condition: "${{ .steps.waitForCompletion.outputs.automationExecutionStatus == 'Success' }}"
        next: displaySuccess
    next: displayUnexpected  # Default path when no condition matches
```

**Example:** [Handle team response](#handle-team-response), [Verify and clean up](#verify-and-clean-up)

### Loops for processing lists

**Use loops when:** Processing multiple items or repeating actions

For detailed information about loop structure, parameters, and advanced usage (including break/continue), see [Loop structure](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/basic-patterns/loops).

**Key syntax:**

```yaml
  # Send progress updates using range loop
  - name: progressLoop
    type: loop
    for:
      in: "${{ [range(1; 5)] }}"  # Loop 5 times
      steps:
        - name: wait
          type: wait
          seconds: 10
        - name: progressMessage
          type: action
          action: slack.chat.postMessage
          version: 1
          inputs:
            channel: "${{ .workflowInputs.channel }}"
            text: "Resizing in progress..."
```

**Example:** [Execute the resize](#execute-the-resize)

### Approval gates and waiting

**Use approval gates when:** Human judgment is needed before destructive operations or compliance sign-off is required

**Key syntax:**

```yaml
  - name: requestApproval
    type: action
    action: slack.chat.postMessage
    version: 1
    inputs:
      channel: "#approvals"
      text: "Approve? React with :thumbsup: or :thumbsdown:"

  - name: getReactions
    type: action
    action: slack.chat.getReactions
    version: 1
    inputs:
      token: "${{ .workflowInputs.slackToken }}"
      channelID: "${{ .steps.requestApproval.outputs.channelID }}"
      threadTs: "${{ .steps.requestApproval.outputs.threadTs }}"
      timeout: 300  # Wait 5 minutes for reaction

  - name: checkApproval
    type: switch
    switch:
      - condition: '${{ .steps.getReactions.outputs.reactions | any(.name == "+1") }}'
        next: handleApproval
      - condition: '${{ .steps.getReactions.outputs.reactions | any(.name == "-1") }}'
        next: handleRejection
```

**For simple delays:**

```yaml
  - name: waitBeforeRetry
    type: wait
    seconds: 60  # Wait 60 seconds before continuing
```

**Example:** [Request team approval](#request-team-approval)

### Passing data between steps

**Use data passing when:** One step's output becomes another's input (the foundation of all workflows)

**Key syntax:**

```yaml
  # Reference previous step outputs
  awsRegion: "${{ .inputs.region }}"
  instanceId: "${{ .steps.getAlert.outputs.data.entity.instanceId }}"
```

**Example:** All workflow steps

### Variable assignment with assign

The assign step type allows you to initialize and assign values to variables that can be used in subsequent workflow steps. This step supports multiple data types including strings, integers, booleans, maps (objects), and lists (arrays).

**Basic structure:**

```yaml
  - name: <step_name>
    type: assign
    inputs:
      <variable_name>: <value_or_expression>
```

**Example:**

```yaml
  - name: variableInitialization
    type: assign
    inputs:
      stringVar: "${{ .workflowInputs.initialValue }}"
      intVar: "${{ .workflowInputs.anotherValue }}"
      concatenationVar: "${{ .workflowInputs.initialValue }} - concatenated"
      booleanVar: true
      mapVar:
        key1: "value1"
        key2: "${{ .workflowInputs.initialValue }}"
      listVar:
        - "listItem1"
        - "${{ .workflowInputs.initialValue }}"
        - "${{ .workflowInputs.anotherValue }}"
      statusCode: ${{ .steps.runAction.outputs.statusCode }}
```

> #### 💡 TIP
>
> **Want complete pattern examples?** See [Workflow examples](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/workflow-examples) for additional patterns including error handling, retries, and complex integrations.

## Example walkthrough: Auto-resize EC2 with approval [#example-walkthrough]

This example builds a workflow that resizes EC2 instances when CPU spikes—after getting team approval via Slack. It demonstrates data gathering, conditional logic, external integrations, and error handling.

> #### 💡 TIP
>
> **New to workflows?** This example uses AWS, Slack, and approval logic. Try [Send report to Slack](https://docs.newrelic.com/docs/workflow-automation/create-a-workflow-automation/use-a-template#send-report-to-slack) first if you're just starting.

### Workflow overview [#workflow-overview]

**High-level flow:**

1.  **Gather data**: Fetch alert and instance details from New Relic
2.  **Request approval**: Send Slack message, wait for team response
3.  **Execute resize**: Use AWS Systems Manager to resize EC2 instance
4.  **Verify and clean up**: Check results, notify team, remove temporary resources

### Prerequisites [#prerequisites]

Before building this workflow, ensure you have:

-   **AWS**: Credentials with EC2 and Systems Manager permissions
-   **Slack**: Bot token and channel for notifications
-   **New Relic**: Alert condition monitoring EC2 CPU
-   **Secrets manager**: Configured, see [secrets manager](https://docs.newrelic.com/docs/workflow-automation/limitations-and-faq/workflow-best-practices#secure-credentials)

### Build the workflow step-by-step [#step-by-step-workflow]

Build each part of the workflow. Each step includes specific actions and demonstrates workflow patterns.

### Gather alert context [#gather-alert-context]

Query APIs and databases to gather complete context before taking action.

Three actions collect alert and EC2 instance information:

-   **`getAlertDetails`**: Calls NerdGraph API to fetch alert metadata—activation time, condition name, and affected entities.
-   **`activatedDateTime`**: Converts timestamp to readable format (e.g., **01-24-2025 14:30**) for Slack messages.
-   **`impactedEC2Instance`**: Queries NRDB to find EC2 instance ID and current type.

    ![Workflow diagram showing three steps: getAlertDetails queries NerdGraph API, activatedDateTime converts timestamp, and impactedEC2Instance retrieves instance details from NRDB](https://docs.newrelic.com/images/initial-data-gathering.webp "Initial data gathering steps")

    **Why this matters:** Without these details, you can't construct meaningful Slack messages or target the right EC2 instance.

### Request team approval [#request-team-approval]

Connect to collaboration tools for human decision points.

Send details to Slack and wait for response:

-   **`IssueDetected`**: Posts alert details, current instance type, and proposed resize. Asks team to react with `:+1:` (approve) or `:-1:` (cancel).
-   **`GetUserReaction`**: Pauses for 5 minutes waiting for a reaction.
-   **`checkQuery` (Switch)**: Routes based on reaction:

    -   **`:+1:`** → Start resizing
    -   **`:-1:`** → Stop workflow
    -   **Other** → Prompt for valid reaction, loop back

        ![Workflow diagram showing user approval process: IssueDetected posts Slack message, GetUserReaction waits for response, checkQuery evaluates reactions with three conditions for approval, cancellation, or unexpected responses](https://docs.newrelic.com/images/user-approval-process.webp "User approval process steps")

### Handle team response [#handle-team-response]

Create different paths based on data values or user input.

Branch based on the reaction:

-   **`unexpectedReaction`**: Explains valid reactions and loops back to wait again.
-   **`gotCancelReaction`**: Confirms cancellation, skips to completion. No infrastructure changes.
-   **`gotYesReaction`**: Confirms approval, proceeds to resize.

    > #### 💡 TIP
    >
    > **Approval gates pattern:** Use switches like this when you need human judgment before risky changes. The pattern works with Slack reactions, PagerDuty acknowledgments, email responses, or custom webhooks.

### Execute the resize [#execute-the-resize]

Prevent duplicate operations with unique tokens. Check long-running operations with loops.

Resize the instance through AWS Systems Manager (SSM):

-   **`createSsmDocument`**: Creates SSM Automation document that stops the instance, modifies type, and restarts it.
-   **`generateIdempotencyToken`**: Creates unique UUID to prevent duplicate resizes.
-   **`startResizing`**: Executes SSM document with instance ID and new type.
-   **`progressLoop` (Loop)**: Posts Slack updates every 10 seconds (5 times).
-   **`waitForCompletion`**: Polls SSM status with 2-minute timeout.

    > #### ⚠️ IMPORTANT
    >
    > **Why SSM?** Systems Manager provides error handling, state verification, and CloudTrail audit logs. Better than direct EC2 API calls.

### Verify and clean up [#verify-and-clean-up]

Clean up temporary resources regardless of outcome.

Check results and remove temporary resources:

-   **`hasCompleted` (Switch)**: Branches on SSM status (success/failed/timeout).
-   **`displaySuccess`**: Logs success to New Relic.
-   **`sendSuccessMessage`**: Confirms completion in Slack.
-   **`displayError`**: Logs error details for troubleshooting.
-   **`displayUnexpected`**: Logs unusual states (manual cancellation, etc.).
-   **`cleanupSsmDocument`**: Deletes temporary SSM document.
-   **`sendSSMCleanMessage`**: Confirms cleanup in Slack.
-   **`workflowCompleted`**: Final completion message (runs for success or cancel).

## Complete parameter reference [#parameter-reference]

This workflow requires credentials, configuration, and runtime context as inputs. Sensitive values come from [secrets manager](https://docs.newrelic.com/docs/workflow-automation/limitations-and-faq/workflow-best-practices#secure-credentials) using `${{ :secrets:keyName }}` syntax.

**Input categories:**

-   **Authentication**: AWS and Slack credentials
-   **Alert context**: Account ID and issue ID from New Relic
-   **Configuration**: Region, instance type, timezone, Slack channel

| **Parameter name**   | **Type** | **Default value**                    | **Description**                                                                                                                   |
| -------------------- | -------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `awsAccessKeyId`     | String   | `${{ :secrets:awsAccessKeyId }}`     | AWS Access Key ID for authenticating with AWS services.                                                                           |
| `awsSecretAccessKey` | String   | `${{ :secrets:awsSecretAccessKey }}` | AWS Secret Access Key. Pairs with the access key ID.                                                                              |
| `awsSessionToken`    | String   | `${{ :secrets:awsSessionToken }}`    | Session token for temporary AWS credentials (optional, used with IAM roles).                                                      |
| `slackToken`         | String   | `${{ :secrets:slackToken }}`         | Bot token for posting messages and reading reactions in Slack.                                                                    |
| `accountId`          | Int      | Required                             | Your New Relic account ID. Used for querying alert details and entity data.                                                       |
| `issueId`            | String   | Required                             | The issue ID from the New Relic alert that triggered this workflow. Provided automatically when the workflow runs from an alert.  |
| `awsRegion`          | String   | `us-east-2`                          | AWS region where your EC2 instance runs (for example, `us-east-1`, `us-west-2`, `eu-west-1`).                                     |
| `InstanceType`       | String   | `t4g.nano`                           | Target EC2 instance type for resizing. Choose based on your performance needs and budget.                                         |
| `timestampUnit`      | String   | `MILLISECONDS`                       | Time unit for the alert timestamp. Typically `MILLISECONDS` or `SECONDS`.                                                         |
| `timezoneId`         | String   | `America/Los_Angeles`                | Timezone for displaying alert activation time in Slack messages (for example, `America/New_York`, `Europe/London`, `Asia/Tokyo`). |
| `pattern`            | String   | `MM-dd-yyyy HH:mm`                   | Date/time format pattern for displaying timestamps. Uses Java SimpleDateFormat patterns.                                          |
| `channel`            | String   | Required                             | Slack channel ID (not name) where notifications are posted. Find this in Slack's channel details.                                 |

## Next steps [#next-steps]

After completing this example, explore these resources:

[Set up AWS credentials](https://docs.newrelic.com/docs/workflow-automation/setup-and-configure/set-up-aws-credentials)

Configure IAM roles for EC2 and other AWS actions

[Actions catalog](https://docs.newrelic.com/docs/workflow-automation/setup-and-configure/actions-catalog/actions-catalog)

Explore all available actions for workflows

[Workflow examples](https://docs.newrelic.com/docs/workflow-automation/workflow-examples/workflow-examples)

See examples for HTTP APIs, Slack integrations, and more

[Best practices](https://docs.newrelic.com/docs/workflow-automation/limitations-and-faq/workflow-best-practices)

Learn error handling, retry logic, and security patterns

[Workflow entity overview](https://docs.newrelic.com/docs/workflow-automation/manage-workflows/workflow-entity-overview)

Trigger your workflow manually, from alerts, or on a schedule

[Manage workflows](https://docs.newrelic.com/docs/workflow-automation/manage-workflows/managing-workflow)

Edit, duplicate, and monitor workflow execution

[Troubleshooting](https://docs.newrelic.com/docs/workflow-automation/troubleshooting)

Common issues and solutions for custom workflows
