Slack

Here's what happens when you use Slack as a channel for your digital assistant (or standalone skill):

  • Slack hosts your digital assistant through the intermediary of a Slack app.
  • Users chat with your digital assistant through the Slack app in the Slack user interface.

See Building Slack apps for Slack's developer documentation for Slack apps.

Below are the steps for creating a Slack channel for Digital Assistant.

Note

Skills and digital assistants that you expose through Slack channels can also be included in group chats. See Group Chats.

Step 1: Get a Slack Workspace

To make your digital assistant (or standalone bot) available in Slack, you need to have a Slack workspace available to you where you have the permissions necessary to create a Slack app.

If you don't have such a workspace available to you, you can create your own. See Slack's Create a new workspace page.

Step 2: Create a Slack App

  1. Go to Slack's Your Apps page.

  2. Click Create a Slack App.

  3. In the Create a Slack App dialog, fill in the App Name and Development Slack Workspace fields and click Create App.

    Once the app is created, its Basic Information page appears.

  4. Scroll down to the App Credentials section of the page and note the values of the Client ID, Client Secret, and Signing Secret.

    You'll need these credentials when you set up the channel in Digital Assistant.

Step 3: Add OAuth Scopes for the Slack App

You add OAuth scopes for permissions that you want to give to the bot and to the user.

  1. In the left navigation of the web console for your Slack app, within the Features section, select OAuth and Permissions.

  2. Scroll to the Scopes section of the page.

  3. The scopes fall into these categories:
    • Bot Token Scopes
    • User Token Scopes
  4. In the Bot Token Scopes section, add the scopes that correspond to the bot-level permissions that you want to allow. At minimum, the following bot token scopes are required:

    • chat:write
    • im:history
    • users:read

    Depending on the skill's features, other scopes might be required. For example, the following scopes are required for working with attachments:

    • files:read
    • files:write
  5. In the User Token Scopes section, add the scopes that correspond to the user-level permissions that you want to allow. The following user token scopes are required:

    • files:read
    • files:write

Depending on the requirements of your bot, you may need to add other scopes.

Step 4: Add the App to the Workspace

  1. Scroll back to the top of the OAuth & Permissions page.

  2. Within the OAuth Tokens & Redirect URLs section, click Install to Workspace.

    A page will appear showing what the app will be able to do.

  3. At the bottom of the page, click Allow.

Once you have completed this step, you should be able to see the app in your Slack workspace by selecting Apps in the left navigation.

Step 5: Create a Channel in Digital Assistant

  1. In Digital Assistant, click Channels in the left menu and then choose Users.

  2. Click + Channel to open the Create Channel dialog.

  3. Give your channel a name.

  4. Choose Slack as the channel type.

  5. Fill in the the values for Client ID, Client Secret, and Signing Secret that you obtained when you created your Slack app.

    You can retrieve these values from the Settings page of your Slack app.

  6. If you are setting up the channel for group chats and you want messages to go to the group without mentioning the Slack app name, select Allow Messages Without App Mention in Group Chat.
  7. Click Create.

  8. In the Channels page, copy the WebHook URL and paste it somewhere convenient on your system. You’ll need this to finish setting up the Slack app.

  9. Click icon for the Route To ... dropdown and select the digital assistant or skill that you want to associate with the channel.

  10. In the Route To dropdown, select the digital assistant or skill that you want to associate with the channel.

  11. Switch on the Channel Enabled control.

Step 6: Configure the Webhook URL in the Slack App

  1. In the left navigation of the web console for your Slack app, select Interactivity & Shortcuts.

  2. Turn the Interactivity switch ON.

  3. In both the Request URL and Options Load URL fields, paste the webhook URL that was generated when you created the channel in Digital Assistant .

  4. Click Save Changes.

  5. In the left navigation, select OAuth & Permissions.

  6. In the Redirect URLs field, click Add New Redirect URL.

  7. Paste the webhook URL, append /authorizeV2, and click Add.

  8. Click Save URLs.

  9. In the left navigation, select App Home.

  10. In the Your App’s Presence in Slack section, turn on the Always Show My Bot as Online switch.

  11. Scroll down the page to the Show Tabs section, and turn the Messages Tab switch on.

  12. Select the Allow users to send Slash commands and messages from the messages tab checkbox.

  13. In the left navigation, select Event Subscriptions.

  14. Set the Enable Events switch to ON.

  15. In the Request URL field, paste the webhook URL.

    After you enter the URL, a green Verified label should appear next to the Request URL label.

  16. Expand the Subscribe to bot events section of the page, click Add Bot User Event, and add the following event:

    • message.im
  17. If you plan to make the bot available in group chats, also add the following events:
    • app_mention
    • message.mpim
    • message.channels
  18. Click Save Changes.

  19. In the left navigation, select Manage Distribution.

  20. Click the Add to Slack button and then click Allow.

    At this point, you should get the message You've successfully installed your App in Slack.

Step 7: Test Your Bot in Slack

With the Slack channel and messaging configuration complete, you can test your bot (digital assistant or skill) in Slack.

  1. Open the Slack workspace where you have installed the app.

  2. In the left navigation bar, select the app that is associated with your digital assistant.

  3. In the Message field, enter text to start communicating with the digital assistant.
Note

If you see the message "Sending messages to this app has been turned off” in your Slack client, try restarting the Slack app. If this does not enable the field, check to make sure that you have granted all of the necessary permissions.

"New" vs. "Classic" Slack Apps

Starting with version 20.6 of Oracle Digital Assistant, creation of Slack channels is based on an updated OAuth flow in Slack apps. This updated flow enables more granular scopes. The instructions for channel setup in this guide are based on the new OAuth flow.

See https://api.slack.com/authentication/oauth-v2 for details on the updated OAuth flow.

Note

Any existing channels that were created before Digital Assistant 20.6 and that are based on "classic" Slack apps will continue to work. However, you should consider migrating those classic Slack apps to new Slack apps. See https://api.slack.com/authentication/migration for the details.

Supported Capabilities

Slack channels in Digital Assistant support the following capabilities:

  • text (both sending and receiving)
  • images (both sending and receiving)
  • files (partial support for sending, full support for receiving)
  • emojis (partial support for sending, full support for receiving)
  • links
  • postbacks
  • custom properties
  • carousel components (but rendered vertically instead of horizontally)
  • list components

Slack enables you to format messages using markdown. See https://api.slack.com/reference/surfaces/formatting in the Slack API documentation.

Note

If you are targeting your skill to multiple channels with different formatting capabilities and syntax, you can use basic HTML markup in your messages. If you do so, that markup will be automatically converted to Slack's markdown format when the message is transmitted to the channel. This is particularly useful if you are targeting your skills to other channels in addition to Slack. See Rich Text Formatting in Channels.

Message Constraints

Slack channels in Digital Assistant have the following message constraints:

  • Text Messages
    • Maximum length of text message: 3000 characters. If the length exceeds 3000, the text is split over multiple messages.
    • Maximum length of text action label: 30 characters
    • Types of text actions allowed: Postback, URL
  • Horizontal Cards
    • Supported?: No. Card is layout is converted to vertical.
  • Vertical Cards
    • Maximum length of title: 3000 characters
    • Maximum length of description: 3000 characters
    • Maximum length of card action label: 30 characters
    • Maximum number of cards: 100
    • Types of card actions allowed: Postback, URL
    • Types of card list actions allowed: Postback, URL
  • Attachment Messages
    • Supported?: Yes
    • Types of Actions Allowed: Postback, URL
  • Action Buttons
    • Maximum length of global action label: 30 characters
    • Types of global actions allowed: Postback, URL

Slack Channel Extensions

For Slack channels, you can extend the functionality of Common Response components with capabilities that are specific to Slack.

You access the extensions by using the channelCustomProperties element in the Common Response component's metadata and setting the appropriate properties. The code has the following format:

...
            channelCustomProperties:
            - channel: "slack"
              properties:
                PROPERTY_NAME: "PROPERTY_VALUE"
...

Here are the available custom properties for Slack channels:

Name Allowed Values Applies To... Description
dropDownPlaceholder
  • placeholder text
  • nested object with the following properties, each of which takes a string value:
    • postbackActions
    • cardPostbackActions
    • globalPostbackActions
Response items Use this property to specify the placeholder text shown within the dropdown list.
ephemeral
  • true
  • false
Response items Can be used in group chats to display a message to just one user, such as when that user attempts to authenticate.
fields
  • an array of strings
Response items of type text. The string values specified in this property are displayed as fields in a two-column layout (desktop) or a single column layout (mobile).
renderActionsAsDropDown
  • true
  • false
  • nested object with the following properties, each of which takes a Boolean value:
    • postbackActions
    • cardPostbackActions
    • globalPostbackActions
Response items By default (if you don't set this property), actions are displayed:
  • as buttons if there are five or fewer actions
  • in a dropdown list if there are six or more

If you want to display actions in a dropdown list, no matter how many actions there are, set this property to true.

If you want to display actions as buttons, no matter how many actions there are, set this propeorty to false.

If you want to have different behavior for different types of postback actions, you can use a nested object with Boolean values for each of the following type of actions:

  • postbackActions - postback actions defined at the response item level, including text, attachment, and card list items.
  • cardPostbackActions - postback actions defined for an individual card
  • globalPostbackActions - postback actions defined for global actions.

To render actions in a dropdown menu, Slack uses a select menu with static items. See https://api.slack.com/reference/messaging/block-elements#static-select.

showDatePicker
  • true
  • false
  • a nested object with show, initialDate and placeholder properties
Response items of type text. Set to true to show a date picker next to the text message.

In the Add State dialog, you can select the Slack Date Picker template to get sample code for displaying a date picker conditionally.

See also https://api.slack.com/reference/messaging/block-elements#datepicker.

showImageInAccessory
  • true
  • false
Response items of type cards. Set to true to show the card image at the right as a small image instead of a larger centered image.

Here's an example of using the renderActionsAsDropDown custom property.

responseItems:
- type:
 "text"
  text: "Here is a list of the UI features of the Common Response Component:"
  actions:
  - ...
  channelCustomProperties:
  - channel: "slack"
    properties:
      renderActionsAsDropDown: false

And here's an example of using the renderActionsAsDropDown custom property with nested properties for postbackActions, cardPostbackActions, and globalPostbackActions.

responseItems:
- type: "text"
  text: "Here is a list of the UI features of the Common Response Component:"
  actions:
  - ...
  channelCustomProperties:
  - channel: "slack"
    properties:
      renderActionsAsDropDown:
        postbackActions: false
        cardPostbackActions: true
        globalPostbackActions: true

For more general information on channelCustomProperties, see Channel-Specific Extensions.

Slack Modals

You can create a button to invoke a Slack modal in a Common Response component. To do so, you set the button's action property to system.openModal and include a variable named system.dialogPayload of type map. The action metadata should look something like this snippet:

          actions:
          - label: "Open Dialog"
            type: "postback"
            payload:
              action: "system.openModal" 
              variables:
                system.dialogPayload: ${dialogPayload}
Note

The Freemarker expression to reference the system.dialogPayload variable does not end with .value. This is because the variable holds a JSON object, and Freemarker expressions must always evaluate to a string. Using the expression ${dialogPayload.value} would throw an error. The JSON object-to-string conversion takes place when you omit .value.

The value of system.dialogPayload is typically set in a custom component, but also can be defined inline or using a Set Variable component.

Here is an example in YAML dialog mode using a Set Variable component:

  setSlackModalUI:
    component: "System.SetVariable"
    properties:
      variable: "dialogPayload"
      value:
        type: modal
        title:
          type: plain_text
          text: Edit expense
          emoji: true
        submit:
          type: plain_text
          text: Submit
          emoji: true
        close:
          type: plain_text
          text: Cancel
          emoji: true
        blocks:
        - type: input
          element:
            type: static_select
            initial_option:
              value: "${expense.value.Type!''}"
              text:
                type: "plain_text"
                text: "${expense.value.Type!''}"
                emoji: true
            placeholder:
              type: plain_text
              text: Select expense type
              emoji: true
            options:
            - text:
                type: plain_text
                text: Metro, bus, train
                emoji: true
              value: Public transport
            - text:
                type: plain_text
                text: Taxi
                emoji: true
              value: Taxi
            - text:
                type: plain_text
                text: Breakfast, lunch, dinner
                emoji: true
              value: Meal
            - text:
                type: plain_text
                text: Flight
                emoji: true
              value: Flight
            action_id: "expenseType"
          label:
            type: plain_text
            text: Expense Type
            emoji: true
        - type: input
          element:
            type: plain_text_input
            action_id: "expenseAmount"
            initial_value: "${expense.value.Amount?has_content?then(expense.value.Amount.totalCurrency,'')}"
            placeholder:
              type: plain_text
              text: Expense amount
              emoji: true
          label:
            type: plain_text
            text: Amount
            emoji: true
        - type: input
          element:
            type: datepicker
            initial_date: "${expense.value.Date?has_content?then(expense.value.Date.date?long?number_to_date?string['yyyy-MM-dd'],'')}"
            placeholder:
              type: plain_text
              text: Expense Date
              emoji: true
            action_id: "expenseDate"
          label:
            type: plain_text
            text: Date
            emoji: true
Note

If you set the system.dialogPayload variable in a custom component, you don't need to hard-code the entity values as options. Instead, you can iterate over all the entity values of a specific item and dynamically create a select element type with an options array for the allowable values.

When the user submits input in the Slack dialog, the Common Response component sets the system.dialogSubmitted transition to move to a state that processes the submitted values. The submitted values are stored in variables with the same name. For a custom component equivalent of the preceding System.SetVariable example, you would need to define the variables Type, Date and Amount, since those are are defined in dialogPayload.

Here's some sample code for handling the system.dialogSubmitted transition in a skill designed in YAML dialog mode.

    transitions:
      next: "nothingSubmitted"
      actions:
        system.dialogSubmitted: "displaySlackReturnValues"
          
  displaySlackReturnValues:
    component: "System.CommonResponse"
    properties:
      keepTurn: true
      metadata:
        responseItems:        
        - type: "text" 
          text: "Expense Type : ${expenseType}"
    transitions:
      return: "done"

It is up to you to determine how to process the submitted field values. The Common Response component does NOT perform any automatic updates of entity values. It only stores the values in context variables. You will typically process these values in a custom component, so you can do additional validations if needed. In its most simple form, you can store the submitted field values in a string variable and then use the Match Entity component to update entity values.

Here is an example for a dialog flow in YAML mode for using the submitted values to update the expense composite bag entity:


  matchEntity:
    component: "System.MatchEntity"
    properties:
      sourceVariable: "submittedFields"
      variable: "expense"  transitions:
      next: "resolveExpense"

Tip:

In the dialog flow editor (in both Visual and YAML dialog mode), there is a Slack Block Kit template that contains a heavily-nested metadata sample that is typical of output from the kit builder. If you need complex metadata for such a state and you want to make it easier to read, you can use flow-level map variables, paste whole JSON objects generated by the kit builder into them as default values, and incorporate the variables into the metadata.

For full documentation on the element types that are supported in the Slack dialog payload, see https://api.slack.com/reference/block-kit/block-elements. The structure you specify in the dialog payload should be identical to the structure described in the Slack documentation.

Note

The Slack dialog also supports having an error array sent back as the response when the modal is submitted. However, this functionality is currently not supported within Common Response components. Instead, you should handle custom validation and user feedback associated with validation errors in a custom component.

Slack Dialog Window

Note

Slack now recommends that you use Slack modals instead of Slack dialogs. See Slack Modals for details on incorporating Slack modals into your dialog flow and https://api.slack.com/block-kit/dialogs-to-modals for info on converting dialogs to modals.

You can create a button to invoke a Slack dialog in a Common Response component. To do so, you set the button's action property to system.openDialog and include a variable named system.dialogPayload. The action metadata should look something like this snippet:

            actions:
              - label: "Edit"
                type: "postback"
                payload:
                  action: "system.openDialog"
                  variables:
                    system.dialogPayload: ${dialogPayload}
Note

The Freemarker expression to reference the system.dialogPayload variable does not end with .value. This is because the variable holds a JSON object, and Freemarker expressions must always evaluate to a string. Using the expression ${dialogPayload.value} would throw an error. The JSON object-to-string conversion takes place when you omit .value.

The value of system.dialogPayload is typically set in a custom component, but also can be defined inline or using a Set Variable component.

Here is a simple example using a System.SetVariable component in a YAML-mode dialog flow:

  setDialogPayload:
    component: "System.SetVariable"
    properties:
      variable: "dialogPayload"
      value:
        callback_id: "editExpense"
        title: "Edit expense"
        submit_label": "Submit"
        elements:
          - type: "select"
            label: "Expense Type"
            name: "Type"
            value: "${expense.value.Type!''}"
            options:
              - value: "Public transport"
                label: "Metro, bus, train"
              - value: "Taxi"
                label: "Taxi"
              - value: "Meal"
                label: "Breakfast, lunch, dinner"
              - value: "Flight"
                label: "Flight"
          - type: "text"
            label: "Amount"
            name: "Amount"
            value: "${expense.value.Amount?has_content?then(expense.value.Amount.totalCurrency,'')}"
          - type: "text"
            label: "Date"
            name: "Date"
            value: "${expense.value.Date?has_content?then(expense.value.Date.date?number_to_date,'')}"
Note

If you set the system.dialogPayload variable in a custom component, you don't need to hard-code the entity values as options. Instead, you can iterate over all the entity values of a specific item and dynamically create a select element type with an options array for the allowable values.

When the user submits input in the Slack dialog, the Common Response component sets the system.dialogSubmitted transition to move to a state that processes the submitted values. The submitted values are stored in context variables with the same name. For a custom component equivalent of the preceding System.SetVariable example, you would need to define the context variables Type, Date and Amount, since those are are defined in dialogPayload.

Here's some sample code for handling the system.dialogSubmitted transition in a skill designed in YAML dialog mode.

  ...
    transitions:
      actions:
        cancel: "askTalkToAgent"
        match: "afterMatch"
        disambiguate: "disambiguate"
        system.dialogSubmitted: "processDialog"
 
  processDialog:
    component: "System.SetVariable"
    properties:
      variable: "submittedFields"
      value: "${Type} ${Amount} ${Date}"
    transitions:
      ...

It is up to you to determine how to process the submitted field values. The Common Response component does NOT perform any automatic updates of entity values. It only stores the values in context variables. You will typically process these values in a custom component, so you can do additional validations if needed. In its most simple form, you can store the submitted field values in a string variable and then use the Match Entity component to update entity values.

Here is an example for a dialog flow in YAML mode for using the submitted values to update the expense composite bag entity:


  matchEntity:
    component: "System.MatchEntity"
    properties:
      sourceVariable: "submittedFields"
      variable: "expense"  transitions:
      next: "resolveExpense"

For documentation on other properties and element types that are supported in the Slack dialog payload, see https://api.slack.com/dialogs#top-level_dialog_attributes. The structure of the dialog payload should be identical to the structure described in the Slack documentation.

Note

The Slack dialog also supports having an error array sent back as the response when the dialog is submitted. However, this functionality is currently not supported within Common Response components. Instead, you should handle custom validation and user feedback associated with validation errors in a custom component.