For the complete documentation index, see llms.txt. This page is also available as Markdown.

Building and Managing Workflows

Learn how to build custom workflows with triggers, actions, and conditional logic; use template variables; and test and publish workflows.

Path: /workflows

Understanding Workflow Automation

Workflow automation lets you create custom workflows that run automatically based on triggers (manual, scheduled, events, or inbound webhooks) and execute a sequence of steps. Workflows can integrate with Slack, Teams, Okta, HRIS systems, MDM tools, ServiceNow, GitHub, Jira, and Harmony itself.

Understanding the Workflow Builder

The Workflow Builder is a visual editor where you design workflows by adding nodes and connecting them. Open Workflows from the sidebar, then create a new workflow or open an existing one. The builder shows a canvas with a trigger node at the top and action/logic nodes below.

Understanding the Workflow Canvas

The canvas is a drag-and-drop area where workflow nodes are laid out. Nodes connect via edges (lines). Use the zoom controls (bottom-left) to zoom and pan. Right-click on the canvas or on nodes to open context menus. Use Shift+drag to select multiple nodes. The canvas snaps nodes to a grid. The canvas clips cleanly to rounded corners that match the surrounding content card, so the builder looks consistent throughout.

Open Workflows at /workflows to see all custom workflows. Each card shows the workflow name, description, enabled state, and toggle. Click a workflow to edit it. Click Create Workflow to start a new one (when the Workflow Builder feature is enabled).

Creating Your First Workflow

  1. Click Create Workflow on the Workflows page.

  2. You're taken to the builder with a default Manual trigger.

  3. Click the + handle below the trigger (or drag from it) to add a step.

  4. Choose an action (e.g., Slack, Okta, Harmony) and an operation.

  5. Configure the step in the Properties panel.

  6. Add more steps as needed.

  7. Save and enable the workflow.


Building Workflows

Adding Workflow Nodes

  • From the trigger: Click the + handle at the bottom of the trigger node, or drag from it. A step selector appears; pick a category (Slack, Okta, Harmony, etc.) and an operation.

  • From an existing step: Drag from the output handle of a step to create a connection. Drop on the canvas to add a new step, or drop on another step's input handle to connect.

  • Context menu: Right-click the canvas to add a step at that position.

Connecting Workflow Steps

Drag from a step's output handle (bottom) to another step's input handle (top) to connect them. Connections define execution order. You can insert a new step into an existing connection by dropping the new step onto the edge.

Understanding Node Types

Type
Description

Trigger

Starts the workflow. One per workflow. Types: Manual, Scheduled, Event, Webhook.

Action

Performs an operation (Slack message, Okta request, create ticket, etc.).

Logic

Condition (if/else), Sleep (wait), or For Each (iterate over a list). Branches, delays, or loops execution.


Understanding Workflow Triggers

Using Manual Triggers

The default trigger. The workflow runs only when executed manually (from the toolbar Run button). You can define workflow inputs (e.g., employee ID, ticket ID) that users provide when running.

Using Scheduled Triggers

Runs the workflow on a schedule. In the trigger configuration, select Scheduled and set:

  • Cron expression - Standard cron format (e.g., 0 9 * * 1-5 for 9:00 AM weekdays).

  • Timezone - Timezone for the schedule (e.g., America/New_York).

Using Event Triggers

Runs when a specific event occurs. Select Event and choose an event type:

Event
Description

Ticket Created

When a new ticket is created.

Ticket Assigned

When a ticket is assigned to someone.

Ticket Status Changed

When a ticket's status changes.

Ticket Resolved

When a ticket is marked as resolved.

When you select an event trigger, the condition builder shows a dropdown of valid fields specific to that event type. Typing {{ trigger. in any step input surfaces an autocomplete list of available fields, so you always know exactly which fields are available without guessing.

Available fields by event type:

  • Ticket Created - ticket ID, title, priority, status, reporter, and desk

  • Ticket Status Changed - fields reflecting the previous and new status, plus ticket metadata

Using Webhook Triggers

Runs when an external system sends an HTTP request to a unique webhook URL generated for the workflow. When you save a workflow with a webhook trigger, the URL is created automatically and is ready to use immediately.

The full request body is passed into your workflow as {{ trigger.* }} data, so every field sent by the external system is available in downstream steps.

Authentication options:

Method
Description

API key (header)

Include a pre-shared key in a request header.

HMAC signature

Validate request authenticity using a shared secret.

Bearer token

Standard Authorization header with a bearer token.

You can retrieve the webhook URL at any time using GET /workflows/{id}/webhook-url.

Configuring Trigger Conditions

For event triggers, you can add conditions to filter when the workflow runs (e.g., only for certain desks, statuses, or types). Use the conditions section in the trigger configuration.


Using Workflow Actions

Understanding Action Blocks

Action blocks are steps that call an external system or Harmony. Each block has a schema-driven configuration form with inputs. Many inputs support template variables to pass data from previous steps or the trigger. Integration identifiers are surfaced on blocks so you can precisely target the right connection, and the integration selector dropdown shows the friendly name you assigned to each integration rather than internal system identifiers.

Integration Actions

Category
Examples

Slack

Send message, update message, add/remove reaction, get thread replies.

Microsoft Teams

Send message, update message, get thread replies.

Okta

Get user, list groups, add/remove user from group, reset password, provision access, terminate sessions, deactivate user, unlock user, retrieve recovery email, add/remove users from groups.

HiBob

Get/create/update employee, list departments/jobs/employees.

Workday

Get/create/update employee, list departments/jobs/employees.

BambooHR

Get/create/update employee, list departments/jobs/employees.

ServiceNow

Run Flow, Create Ticket (incident/request), Create Service Request, discover available flows.

GitHub

Search users, retrieve SAML identities, list org teams and repo collaborators, add/remove team members.

Jira / JSM

Look up issues, manage projects and service management requests.

HTTP Actions

Use the HTTP block to make HTTP requests to any API. Configure URL, method, headers, and body. Supports template variables in the request.

MDM Actions

MDM
Examples

Kandji

Get device, list devices, custom request.

Jamf

Get device, list devices, custom request.

Intune

Get device, list devices, custom request.

Identity Provider Actions

IdP
Examples

Okta

Get user, list groups, add/remove users from groups (accepts a list of employee IDs), unlock user, terminate sessions, retrieve recovery email, reset password, deactivate user.

Microsoft Entra

Get user, list groups, add/remove users from groups, reset password, terminate sessions, deactivate user, unlock user, retrieve recovery email.

Google Workspace

Get user, list groups, add/remove users from groups, terminate sessions, unlock user, retrieve recovery email, custom request.

JumpCloud

List groups, add/remove users from groups, reset password, deactivate user, unlock user, terminate sessions, custom request.

Active Directory (on-premises)

Unlock user accounts and additional identity management operations.

Group membership actions accept a list of employee IDs so you can add or remove multiple users in a single step. The action formerly called "Add to Groups" is now named Add Users to Groups.

AI Actions

Use the AI block to analyze content or generate responses. Useful for automated triage, summarization, or classification.

OTP Verification Actions

Use the OTP Verification blocks to add secure one-time password identity checks to your workflows. The flow is handled end-to-end: a code is generated, delivered to the employee by email, and they are prompted to submit it via a Slack or Microsoft Teams form - all within the workflow itself.

Sensitive values such as OTP codes and temporary passwords are encrypted at rest and are never exposed in plain text in workflow history, API responses, or step outputs.

Harmony Actions

Action
Description

Approval

Pause for human approval before continuing.

Create Ticket

Create a Harmony ticket.

Get/Update Ticket

Fetch or update a ticket.

List Tickets

List tickets with filters.

Get Employee

Fetch employee data by ID or email address.

List Employees

List employees, with filters for VIP status, employment status, location, and employment start date range (all applied server-side).

Get Devices

Fetch devices for an employee.

Update Device

Update device attributes.

Update Asset

Update asset attributes, including setting a manual sale price.

List/Get Application

Fetch application data.

Get Employee Applications

List apps for an employee.

Send Email

Send an email.

Resolve Approver

Resolve who should approve.

Resolve Identity Provider

Resolve IdP for an employee.

Generate CSV Report

Generate a CSV report.

Looking Up Employees

The Get Employee block supports two lookup methods - by employee ID or by email address. Both methods return the same employee data and work seamlessly with downstream steps.

Filtering Employee Lists

The List Employees block supports server-side filtering by:

  • VIP status

  • Employment status

  • Location

  • Employment start date range

Setting Asset Sale Prices

In the Update Asset block, add a Manual Sale Price value to save a price directly to the asset's purchase details. Only the price fields are updated - no other purchase details (such as ABM-sourced data) are overwritten.


Using Conditional Logic

Using Conditional Logic (If/Else)

Add a Condition block from the Logic category. Configure a condition; the workflow branches to different paths based on whether the condition is true or false. Connect follow-up steps to the "true" or "false" output handles.

Setting Up Conditions

In the Condition block form, select a field (from trigger or prior steps), an operator (equals, contains, greater than, etc.), and a value. You can add multiple conditions and choose whether all or any must match.

Understanding Field Operators

Common operators: equals, not equals, contains, not contains, starts with, ends with, greater than, less than, is empty, is not empty. The available operators depend on the field type.

Building Complex Conditions

Combine multiple conditions with AND/OR. Use nested Condition blocks for complex branching.


Using Logic Blocks

Pausing Workflows with the Sleep Block

Add a Sleep block from the Logic category to pause workflow execution for a precise amount of time before continuing to the next step. The timer is fully durable - it survives server restarts and continues reliably even across multi-day waits without consuming processing resources.

Duration options:

  • Specify the wait in minutes, hours, or days - or combine all three for an additive total (e.g., 1 day + 2 hours + 30 minutes).

  • Use a template expression for dynamic durations (e.g., {{ config.jit_duration_minutes }}), so wait times can vary based on workflow data.

Iterating Over Lists with the For Each Block

Add a For Each block to iterate over a list and execute a set of steps for each item. This is useful for bulk actions such as notifying a list of employees, processing multiple tickets, or enriching a set of records.

Key configuration options:

Option
Description

items

The list to iterate over, specified as a dynamic expression (e.g., {{ steps.list_employees.employees }}).

max_parallel

How many items are processed at the same time. Default: 5, maximum: 20.

continue_on_item_error

Whether a failure on one item stops the entire loop or allows remaining items to continue.


Working with Variables and Templates

Using Template Variables

Reference data from the trigger or previous steps using {{ ... }} syntax:

  • Workflow inputs: {{ input.employee_id }} (manual trigger inputs)

  • Trigger event data: {{ trigger.ticket_id }} (event triggers)

  • Webhook data: {{ trigger.* }} (any field from the webhook request body)

  • Step outputs: {{ steps.step_id.output_field }} (outputs from prior steps)

Understanding Available Variables

Variables depend on the current node's position. Only inputs and outputs from steps that run before the current node are available. The Template Picker and Token Input show available variables with autocomplete.

Inserting Variables in Actions

In action block fields that support templates, type {{ to open the template picker, or click the variable button. Select a variable to insert it into the field.

Using the Template Picker

The Template Picker modal shows a tree of available variables grouped by source (inputs, trigger, steps). Expand nodes to find the path, then insert it into your field.

Working with Token Inputs

Fields that support templates use a Token Input. It shows inserted variables as tokens. Click a token to edit or remove it. Type to search available variables.

Understanding Token Autocomplete

When typing {{ in a token input, autocomplete suggests variables. Variables are filtered by the current node's context (preceding steps and trigger). When typing {{ trigger. in any step input, autocomplete surfaces the specific fields available for the selected trigger event type.


Managing and Testing Workflows

Editing Existing Workflows

Open a workflow from the Workflows list. The builder loads the workflow. Make changes to nodes, connections, or configuration. Save to persist. Unsaved changes are indicated in the toolbar.

Testing Workflow Steps

Select an action node and click Test this step (or the play icon on the node). The Execute Step modal opens. Provide test values for required inputs and run the step in isolation - without running the full workflow. Inputs are validated against the block's schema before execution, so you get a clear error immediately if something is misconfigured. View the output to verify the step works before running the full workflow.

Re-executing Failed Steps

From a run's detail view, you can re-run a specific failed step using its original inputs or modified ones. This means you can fix a misconfiguration and retry just that step without replaying the entire workflow.

Executing Workflows

Click Run in the toolbar to execute the workflow. For manual triggers, provide any required inputs in the dialog. The workflow runs and the Runs drawer opens with the run result.

Viewing Workflow Run History

Click the Runs (History) button in the toolbar to open the Runs drawer. It lists recent runs with status, duration, and timestamps. Click a run to expand and see step-by-step execution.

Understanding Workflow Run Details

Each run shows: Run ID, status (running, completed, failed), duration, and step list. Expand a step to see its input, output, and any error. Completed steps show green; failed steps show red with the error message. Sensitive values such as OTP codes are never exposed in plain text in run history or step outputs.

Viewing Step Execution Results

In the Runs drawer, expand a run and a step to see Input (JSON sent to the step), Output (JSON returned), and Error (if the step failed).

Understanding Workflow Errors

When a step fails, the error message appears in the step details. Common causes: invalid inputs, integration misconfiguration, API rate limits, or missing permissions. Use the error message and step input/output to troubleshoot.

Troubleshooting Failed Steps

  1. Check the error message in the step details.

  2. Verify inputs (templates resolve correctly, required fields are set).

  3. Confirm the integration is connected and has the right scopes.

  4. Use Test this step to test the step in isolation with sample data.

  5. From the run detail view, re-run the failed step with corrected inputs.

Monitoring Workflow Health

Harmony automatically monitors the health of your workflows and detects when a dependency a workflow relies on becomes unavailable. When a desk, sub-desk, or employee referenced by a workflow is deleted or terminated, that workflow is instantly marked as degraded with a reason and timestamp - so broken workflows surface immediately rather than silently failing when triggered.

You can retrieve a workflow's current health status at any time using GET /workflows/{id}/health. The response includes the status (healthy or degraded) and, when degraded, the reason and the time it was detected.

Getting Notified on Workflow Failures

Each workflow can be configured with its own failure notification target. When a step fails, Harmony sends an alert immediately to your chosen destination. Notifications include:

  • The workflow name and the specific step that failed

  • The error message with full context

  • A direct link to the failed run so you can jump straight into debugging

Supported notification targets: Slack channels, Slack DMs, Microsoft Teams channels, and Teams direct messages. Configure the notification target in the workflow Settings drawer.

Managing Workflow Versions

You can add a human-readable description to each workflow version to track what changed. When saving or updating a version, include a short note - for example, "Fixed approval timeout from 48h to 72h" or "Added JIT support."

  • Descriptions appear alongside the version number, timestamp, and author in the version history list.

  • You can set or update a description at any time after a version is created.

  • Descriptions are optional; versions without one still appear in the history list.

Duplicating Workflows

Duplicate an existing workflow via the API using POST /workflows/{id}/duplicate. The copy is a fully independent workflow - editing the duplicate never affects the original.

The duplicate includes all steps, triggers, configuration schema, error handling, metadata (icon, tags), and branch logic. You can supply an optional name in the request body; if omitted, the copy is named "{original name} (copy)". The duplicate starts at version 1.0.0 and is created in a disabled state.

Bulk Deleting Workflows

Delete multiple workflows in a single API call using POST /workflows/bulk-delete. Pass an array of up to 50 workflow IDs. All in-flight runs are cancelled and related signals, trigger subscriptions, and event waits are removed for each deleted workflow.

If one or more workflow IDs fail to delete, the response includes details of which deletions succeeded and which failed so you can handle partial failures gracefully.

Deleting Workflows

Open the workflow Settings drawer (gear icon) and scroll to the Danger zone. Click Delete Workflow and confirm. The workflow is permanently removed.


Using the Workflow Toolbar and Properties

Using the Workflow Toolbar

The toolbar at the top includes:

  • Back - Return to the Workflows list.

  • Workflow name - Click to edit. Click the emoji to change the workflow icon.

  • Undo/Redo - Revert or reapply edits.

  • Run - Execute the workflow.

  • Runs - Open the run history drawer.

  • Save - Save the workflow.

  • Settings - Open workflow settings (name, description, error notifications, delete).

  • Enabled - Toggle workflow on/off (publish/unpublish).

  • AI - Open the AI workflow builder.

Last updated

Was this helpful?