Managing app deployment and Admin Approved Apps


Step 1Set up Slack CLI

Use the new Slack CLI to create and deploy Slack apps. With the Slack CLI, developers can create an app and generate some boilerplate code in seconds.

This section walks through setting up your environment for next gen platform development.

  • Install the Slack CLI

    We've built a command line interface to make the process of creating new apps, running them, and deploying them easier. Binaries are available for macOS and Windows.

    Deno is currently a pre-requisite for using the CLI — if you do not have Deno installed, please do so first.

    Additionally, the experience of writing an app will be greatly enhanced if your IDE includes support for Deno. Here's a plugin to add Deno capabilities to VS Code.

    To install the Slack CLI:

    1. Download the latest binary for your platform
    2. Decompress the downloaded file. On macOS, copy the slack binary to a destination in your path (we recommend /usr/local/bin). For Windows, copy the .exe file into any location accessible in your path.
    3. Test the app is properly installed by running slack version and verifying the version matches the one you downloaded.

    Now you can now use the Slack CLI to authenticate and create a new app.

  • Authenticate the Slack CLI

    Before you can create an app, you must authenticate.

    1. Run slack login — this will display some instruction text and a string to copy and paste in any channel in the test workspace.

          /slackauthticket ABC123DEF...XYZ
    2. Copy the entire string, including the leading /, and paste it into any channel in your Slack workspace. (You are essentially calling a special slash command that will authenticate your app with Slack).

    3. Run slack auth info for details on your active workspace authorization.

    Now that you've authenticated, you can create a new app.

  • Create a new app

    Now you can create an app! cd to a directory where you have write access and want your app to live, most likely in your home. Then, run

    $ slack create [optional-project-name]

    This will create a new project called with a random name like priceless-lemur-123.

    If you want to name your project something specific, include an additional parameter

    $ slack create my-new-project

    Once the app has finished running, you'll have a new directory that contains a skeleton app.

    $ cd my-new-project

    The structure of these next-generation apps aims to favor convention over configuration. Directories are named logically and the files within those directories map to specific functionality with an app. For example, the functions directory contains a list of an app's functions, with a single file for each function an app defines.

Step complete!

Step 2Understand how the app works and setup your app for admin approval

This section walks you through how your app is structured and how the different pieces tie together.

We will then make a sample function that takes in a string input and returns a capitalized version.

If you've already created an app and set up it's functionality skip to section 3.
  • Understand how the app is structured

    Your new project has a directory structure that should resemble the following:

      - apps.json
      - cli.json
      - icon.png
     - myfunction.ts
     - mytable.ts
     - mytrigger.ts
     - myworkflow.ts

    Functions: Modular, reusable, atomic blocks of functionality that can be grouped together as workflows. A function defines inputs, performs some useful bit of work using those inputs, and responds with pre-defined outputs. You'll be able to quickly write custom functions, deploy them via the CLI, and building workflows using these functions. Check out our functions documentation to learn more.

    Workflows: A workflow is a group of functions, including built-in functions provided by Slack. Check out our workflows documentation to learn more.

    Triggers: Define how workflows are called, such as a message action, shortcut, or event, where it is able to be executed, and who can execute it. Check out our triggers documentation to learn more.

    Tables: Define tables and store data to power your application. Check out our tables documentation to learn more.

    Project.ts: Contains all of the metadata about a project, such as the name of project, description, and requested OAuth scopes. It also contains a list of defined triggers and tables.

  • Adding a new function to your app

    A function is defined via the DefineFunction method, which is part of the SDK that gets included with every newly created project. The function is exported so that it can be used elsewhere in your app (such as workflows). DefineFunction accepts a name (as a string) and object that defines the input and output parameters as well as an anonymous, asynchronous function that performs that actual work of the function (i.e. taking the input, doing something like calling an API, and then providing an output via a promise).

    Let's create a function that will take as input a string and an interger and return a string with the value of the remaining budget after expenses:

    1. Create a budget.ts file under the functions/ directory of your project.
    2. Copy and paste the following code into it:
    import { DefineFunction, Schema } from "slack-cloud-sdk/mod.ts";
    export const RemainingBudget = DefineFunction(
        title: "Budget Calculator",
        description: "Calculates your remaining budget",
        input_parameters: {
          required: [],
          properties: {
            budget: {
              type: Schema.types.integer,
              description: "The provided budget",
            expenses: {
              type: Schema.types.string,
              description: "The provided expenses",
        output_parameters: {
          required: [],
          properties: {
            remainder: {
              type: Schema.types.string,
              description: "The remaining budget",
      async ({ inputs, env }) => {
        console.log(`calculating ${inputs.budget}.`);
        const remainder = String(
          inputs.budget -
                (a, b) => a + b,
        return await {
          outputs: { remainder },
  • Adding a new workflow to your app

    Now that we have defined our RemainingBudget, we need to connect it to Workflow.

    Let's create a workflow that leverages our RemainingBudget, take its output and uses a built-in Slack function to post it to a channel:

    1. Create a calc_budget.ts file under the workflows/ directory of your project.
    2. Copy and paste the following code into it:
    import { DefineWorkflow, Schema } from "slack-cloud-sdk/mod.ts";
    import { RemainingBudget } from "../functions/budget.ts";
    export const CalculateBudgetRemainder = DefineWorkflow("calculate_budget", {
      title: "Calculate Remaining Budget",
      description: "Calculates your remaining budget from a provided number.",
      input_parameters: {
        required: [],
        properties: {
          budget: {
            type: Schema.types.integer,
            description: "What's your total budget?",
          expenses: {
            type: Schema.types.string,
            description: "List your expenses, separated by commas",
          channel: {
            type: Schema.slack.types.channel_id,
            description: "Channel to send remaining budget",
    const step1 = CalculateBudgetRemainder.addStep(RemainingBudget, {
      budget: CalculateBudgetRemainder.inputs.budget,
      expenses: CalculateBudgetRemainder.inputs.expenses,
    CalculateBudgetRemainder.addStep(Schema.slack.functions.SendMessage, {
        `You have *$${step1.outputs.remainder}* remaining from your budget of *$${CalculateBudgetRemainder.inputs.budget}*`,
  • Adding a new trigger to your app

    Now that we have defined our CalculateBudgetRemainder workflow, we need to connect it to Trigger. There are many different kinds of triggers, but for our purposes we will use a Shortcut trigger. This Shortcut will be how users in your Slack workspace will interact with this app.

    Let's create a trigger that leverages our CalculateBudgetRemainder workflow, take its output and uses a built-in Slack function to post it to a channel:

    1. Create a budget_shortcut.ts file under the triggers/ directory of your project.
    2. Copy and paste the following code into it:
    import { DefineTrigger, TriggerTypes } from "slack-cloud-sdk/mod.ts";
    import { CalculateBudgetRemainder } from "../workflows/calc_budget.ts";
    export const BudgetShortcut = DefineTrigger("calc_budget_shortcut", {
      type: TriggerTypes.Shortcut,
      name: "calculate",
      description: "Calculates your remaining budget",
      .withInputs((ctx) => ({
    1. Now we need to import and reference the trigger we just created in the project metadata file, located at project.ts in the project root:
      1. Import your new trigger at the top of your project.ts file:

        import { BudgetShortcut } from "./triggers/budget_shortcut.ts";

      2. Make sure BudgetShortcut is referenced in the triggers array of your Project definition, so the relevant section of your project.ts file looks like the following:

        triggers: [BudgetShortcut],

Step complete!

Step 3How admin controls affect app deployment

This section walks you through how to navigate app deployment when Admin Approved Apps is enabled on a workspace.

When this setting is enabled on a workspace, apps will need to be approved by a workspace administrator before it can be deployed.

  • What to expect when Admin Approved Apps is enabled

    If Admin Approved Apps is enabled on your workspace you will be notified upon deployment. Run the slack deploy command to begin the deployment process:

    slack deploy

    You will see a message like this on your command line:

    Admin Approval is required on this workspace.
    ? Would you like to send a request to the workspace admin for approval to install this app? (y/N) 

    Reply with y to send a request to your workspace admin. You will be asked to submit a reason for the request. Admins will receive a Slackbot message:

    Install Request Screenshot

  • If your app is approved

    If your app is approved you will get a message from Slackbot on your Workspace letting you know. You will then be able to re-deploy your app.

    App Install Request Approved

  • If your app is denied

    If the admin clicks on the Restrict for Workspace button it means your app has was denied. You will get a DM from Slackbot letting you know. Any attempt to re-deploy the app will result in the following error:

    Error: failed to add app: failed to create an app manifest: failed to install the app to a workspace: This app is currently denied for installation. You can try requesting again with different scopes and outgoing domains.

    If your app is denied you should reach out to your workspace administrators. They can approve the app manually from the app management page.

  • What if you want to modify your installed app?

    If you add a new OAuth scope or outgoing domain to your app you will need to re-deploy it. This will trigger a new installation request flow. This is expected. Workspace admins will need to approve the new changes in order for the updated version of your app to be installed. This will not affect current app installations but the new scope or domain won't function until the app is re-approved.

    Admin Approval is required on this workspace.
    ? Would you like to send a request to the workspace admin for approval to install this app? (y/N) 

    Admins will be notified about the requested changes. They will also be able to see that the app had previously been approved.

    New App Install Request

Step complete!

Was this page helpful?