Legacy Steps from Apps migration guide

Steps from Apps has been deprecated, but the future of custom steps in Workflow Builder is here! While there is no direct migration to new workflow steps, following this guide will show you how to add a workflow step version of your Steps from Apps step so that Workflow Builder users can more easily recreate their workflows in the new system.

Overview

Although the underlying workflow engine and step APIs have changed, the fundamental concepts remain. When a Slack user configures a workflow using a custom step, they will map data into the input_parameters you define for the step. The output_parameters produced by the step can be used in subsequent steps of the workflow. When the workflow runs, the parameters are dynamically filled and passed to the app in an event.

The following shows how Steps from Apps concepts compare to new workflow steps concepts.

Steps from Apps Workflow steps
Callback ID name (see example below)
Step name Title of step
workflow_step_edit event (edit handler if using Bolt) and workflows.updateStep API method (save handler if using Bolt) The end-user configuration of workflow steps no longer requires the Block Kit-based interaction. Step configuration is managed by the Workflow Builder UI tool itself. Step inputs are displayed based on the step input_parameters you configure, guiding the user to enter input based on your defined type and required status for each input parameter.
workflow_step_execute event (execute handler if using Bolt) function_executed event (function handler if using Bolt)

Manifest examples

Given a step has the name/title of Update Report and the callback_id/name of update_report, how this step is reflected in the app manifest is shown here. Note that Steps from Apps are added to the features property, while workflow steps are reflected in the functions property.

Steps from Apps Example
    "features": {
		...
        "workflow_steps": [
            {
                "name": "Update Report",
                "callback_id": "update_report"
            }
        ]
    },

Workflow steps example
    "functions": {
        "update_report": {
            "title": "Update Report",
            "description": "This step updates a report with the given input.",
            "input_parameters": {
                "report_date": {
                    "type": "slack#/types/date",
                    "title": "Report Date",
                    "description": "",
                    "is_required": true,
                    "name": "report_date"
                },
                "report_update": {
                    "type": "string",
                    "title": "Report Update",
                    "description": "",
                    "is_required": true,
                    "name": "report_update"
                }
            },
            "output_parameters": {}
        }
    }

Upgrade to workflow steps

Add your custom step

As shown above, you will need to add a functions property to your app manifest, then add a step to it, using the Steps from Apps callback_id as the step name. Create the corresponding inputs and outputs as well. For example, if your callback_id is my_step, configure it as such:

...
"functions": {
        "my_step": {
            "title": "My Step",
            "description": "Does custom things",
            "input_parameters": {
                "my_channel": {
                    "type": "slack#/types/channel_id",
                    "title": "My Channel",
                    "description": "It is a channel",
                    "is_required": true,
                    "hint": "Put a channel here",
                    "name": "my_channel"
                },
            "output_parameters": {
                "my_output_channel": {
                    "type": "slack#/types/channel_id",
                    "title": "My Channel Output",
                    "description": "It is a channel",
                    "is_required": true,
                    "name": "my_output_channel"
                }
            }
...

While you could choose to rename, re-type, and remove or add inputs in the new version, we recommend duplicating the step as exactly as possible. This will ensure a smoother transition for Workflow Builder users rebuilding their workflows that use your step.

Update your app code

Update your app code, replacing the WorfklowStep definition with a function handler. You may choose to leave your original code in place for backwards compatibility while migrating workflows.

// Example Steps from Apps with Bolt for Javascript code
const ws = new WorkflowStep('my_step', {
    edit: async ({ ack, step, configure }) => { /* Block Kit step config logic here */ }
    save: async ({ ack, step, view, update }) => { /* save result of step config here */ }
    execute: async ({ step, complete, fail }) => { 
    // get inputs from step object
    const { inputs } = step;
    const myInput = inputs.my_channel.value // property values nested inside `value` key
    
    // custom code here
    
    await complete({ "my_output_channel": "#C1234567" });
  }
});
// register step with app
app.step(ws);

The Steps from Apps code above can be replaced with the following function code:

// Example workflow steps with Bolt for Javascript code
app.function('my_step', async ({ client, inputs, fail, complete }) => {
  // get an input directly from inputs object
  const { my_channel } = inputs; // my_channel has the prop value, not nested inside a `value` key
  // custom code here

  await complete({ "my_output_channel": "#C1234567" });
});

Once your Steps from Apps steps are rebuilt as new workflow steps, builders need to manually rebuild their legacy workflows in the new Workflow Builder using the updated steps.

Next steps

✨ Learn more about workflow steps with a general overview or dive into how to implement workflow steps as custom steps with the Bolt framework.

✨ Let a tutorial guide you in creating a new Bolt app with a custom step or adding a custom step to an existing Bolt app.