Slack2Watson(2): Connect Slack to a Watson Chatbot with Node-RED

Using:

  • Slash Commands in Slack,
  • Watson Conversation service to create a ChatBot,
  • Node-RED to configure the Application Flow,

Using a chatbot, I want to automate the following scenario:

  1. user: Hello
  2. chatbot: Hello. Where are you?
  3. user: hi, i am at the Rubin Museum.
  4. chatbot: I love the Rubin Museum. Shall I give you some recomendations of my personal favorites?
  5. user: oh yes, I would love some recommendations.
  6. chatbot: do you like sculpture, paintings or ornaments?
  7. user: i prefer paintings!
  8. chatbot: ok, here are my favorite paintings at the Rubin Museum: a, b, c

Steps:

  1. Create the Watson Conversation for the Rubin Museum Scenario,
  2. Test the Conversation for the Rubin Museum Scenario,
  3. Setup Slash Commands in Slack,
  4. Create the Node-RED Flow to Watson Conversation,
  5. Add Token Validation of the Slack Request to Node-RED Flow,

Create the Watson Conversation for the Rubin Museum Scenario

  • Go to IBM Bluemix and login to your account,
  • To create the Watson Conversation, click the ‘Create Service’ button, which will take you to the Catalog, or
  • Go to the Catalog, Under ‘Services’ filter by ‘Watson’, or in the catalog browse to the Watson section,
  • Click the ‘Conversation’ service,
  • Agree or change the ‘Service name’ and the ‘Credentials name’, and click the ‘Create’ button,
  • Under the ‘Credentials’ tab, you will find the username, password, and workspace ID that you need later to configure access to the conversation service,
  • Click the green ‘Launch tool’ button,
  • First create a workspace, click ‘Create’, name the workspace ‘Watson2Slack-Workspace’, and click ‘Create’,
  • You are now in your Conversation workspace, and you should see 3 tabs: Intents, Entities, and Dialog,

    1. Intents are the building blocks of the conversation, a user expression and its synonyms with a correspeonding reply and its synonyms,
    2. Entities are individual words and related synonyms,
    3. A Dialog is a series of links that form the chain of the Dialog, where conditions can trigger a Dialog to follow a certain path. The conditions are defined by Intents and Entities that are matched by user input,
  • I will create Intents first, and with the Intents I will design my initial Dialog,
  • Look at the chat scenario above that I want to automate, the first possible line by the user is a welcome message. A user can say welcome in multiple ways, so I will create an Intent ‘#hello’ with variations, and Watson will consequently recognize not only the defined example greetings but also related alternatives,
  • Click the Intents tab and click the ‘Create new’ button,
  • Add the Intent name ‘hello’, as you see Intents are referenced by prefixing an ‘#’ to the name.
  • Add the following user examples,
    • good day,
    • good evening,
    • hello
    • hey
    • hi
    • how are you?
    • what’s up?
    • yo

  • Add another Intent named ‘ask-recommendations’,
  • Add the following user examples,
    • can i get some recommendation?,
    • can you tell me what to see?,
    • do you have any suggestions?,
    • okay,
    • what can i go and see?,
    • what do you like about the collection?,
    • where should i go?,
    • yeah that would be useful,
    • yep please,
    • yes,
    • yes please,

  • Go to the ‘Entities’ tab, and click the ‘Create new’ button,
  • Call the Entity ‘Arts’, note that Entities are prefixed with an ‘@’ character,
  • Add a value ‘paintings’ with synonyms: ‘drawings’, ‘painting’, ‘visual arts’,
  • Add a value ‘sculpture’ with synonyms: ‘multi-media’, ‘sculpting’, ‘sculpture’,
  • Go to the ‘Dialog’ tab to build the actual Chatbot scenario now,
  • Click the ‘Create’ button,
  • Configure the default start node:
    • Name: Hello,
    • Trigger, if #hello,
    • Responses: Hello. Where are you?,

  • To the right of the ‘Hello’ node, click the + icon to add a new node after the ‘Hello’ node, and configure the new node:
    • Name: At the Rubin,
    • Trigger, if #at-the-rubin,
    • Responses: Do you want some suggestions?,

  • To the right of the ‘At-the-Rubin’ node, click the + icon to add a new node after the ‘At-the-Rubin’ node, and configure the new node:
    • Name: Ask Recommendations,
    • Trigger, if #ask-recommendations,
    • Responses: What kind of arts do you like? Do you like sculpture, paintings or decorative arts??,

  • To the right of the ‘Ask-Recommendations’ node, click the + icon to add a new node after the ‘Ask-Recommendations’ node, and configure the new node:
    • Name: Paintings,
    • Trigger, if @Arts:paintings,
    • Responses: Let me find you my favorite paintings at the Rubin.,

  • Note how Entities and Entity values are references here in the condition,
  • Under the ‘Paintings’ node, click the + icon to add a new node under the ‘Paintings’ node, and configure the new node:
    • Name: Sculpture,
    • Trigger, if @Arts:sculpture,
    • Responses: Let me find you my favorite works of sculpture at the Rubin.,

The whole Dialog in your Conversation should look as follows now:

Test the Conversation for the Rubin Museum Scenario

In the sidebar of the Conversation builder you can test your conversation.

As you can see in my test, the last response ‘oh right on mate’ is not recognized by Watson, and we should at this type of geographic dialect response if we decide our Dialog should capture this option.

Setup Slash Commands in Slack

Another way to integrate bot messaging into Slack is by using Slash Commands, which are commands users can issue in the Slack command line. It is recommended to build Slash Commands as part of a Slack App.

When a Slash Command is triggered, the receiving custom application, in our case a Node-RED server, doesn’t HAVE to validate the request. The recommended way is however to validate the request token.

Use case:

  1. a Slack User types a command in the Slack command line: ‘/q i m at the Rubin’,
  2. Slack sends a message to the Request URL of the Node-RED server,
  3. the Node-RED server validates that the message is sent by Slack, by comparing the token value with the validation token of your Slack App,
  4. If validated, the Node-RED server calls the Watson Conversation service, which responds with a reply,
  5. the Node-RED server responds to the request by the Slash Commands in Slack,
  6. the user can repeat the process by entering a new command,

Let’s start to implement the above scenario. First, I need to create a Slack Application and enable the Slash Commands Feature. Slash Commands is the Feature in Slack that let users enter special commands from the command line in ‘/[command]’ syntax. We then can send the request that is triggered by a Slash Command to our own Request URL on the Node-RED server.

  • Sign in to Slack and go to https://api.slack.com/apps,
  • Click the ‘Create New App’ button,
  • For ‘App Name’ enter: slack2watson,
  • For ‘Development Slack Team’ select your Slack team, and click ‘Create App’,
  • Click the ‘Slash Commands’ Feature,
  • Click the ‘Create New Command’ button, and configure the App:
    • Command: /q
    • Request URL: https://<your-nodered-app>.mybluemix.net/slack/commands
    • Short Description: Ask Questions to Watson,
    • Usage Hint: /q
  • Click the ‘Save’ button,
  • Go to the ‘Basic Information’ link,
  • Click the ‘Install your app to your team’ link,
  • Login to your Slack team,
  • Click the ‘Install App to Team’ button,
  • Authorize the app,

Create the Node-RED Flow to Watson Conversation

Now the Slack setup is complete in its simplest form, I will create a Node-RED flow to process the requests from Slack, call the Watson Conversation service we created above, and return the response to Slack.

  • Go to IBM Bluemix and login to your account,
  • Click the ‘Create App’ button, which takes you to the Catalog, and filter by or browse to the ‘Boilerplates’, or
  • Go to the Catalog, and filter by or browse to the ‘Boilerplates’,
  • Click the ‘Node-RED Starter’ icon in the ‘Boilerplates’ section,
  • Under ‘App name’ enter an application name, e.g. ‘<username>-nodered-slackapp’. The application name is translated to the ‘subdomain’ or ‘Host name’, but you could change the ‘Host name’,
  • Click the ‘Create’ button,
  • Your application will be created and deployed, or staged, wait until the staging successfully finishes,
  • Once the application is started, a clickable URL is created to access your application,
  • Click the application URL, and open the Node-RED app, click the ‘Next’ button,
  • To ‘Secure your Node-RED editor’ enter a username and password, click ‘Next’, click ‘Next’, and click ‘Finish’,
  • To enter the Node-RED flow editor, click the ‘Go to your Node-RED flow editor’ button,
  • Enter your username and password credentials to Login,
  • Drag and drop nodes from the left menu onto the editor flow in the middle, and connect nodes together to create the flows,

You just created and setup the Node-RED Starter application that is going to be our server application, while Slack is going to be our client application. Node-RED itself is going to use the Watson Conversation service. Let’s piece it all together. First create the workflow skeleton:

  • From the ‘input’ category, drag the ‘http input’ node to the flow,
  • I need to prepare the data received from Slack in the Slash Commands request, and properly format the input data for the Conversation node,
  • Add a ‘function’ node to the flow after the ‘http request’ node,
  • Double click to configure the ‘function’ node:
    • Name: ‘Set Conversation Input’,
    • Function:
      msg.payload = msg.payload.text;
      return msg;
  • Under the ‘IBM_Watson’ category, find the ‘conversation’ node and drag it after the previous ‘function’ node onto the flow,
  • Before sending Conversation data back to Slack in a correct response format, I must prepare the output data from the Conversation node,
  • From the ‘function’ category, drag the ‘function’ node to the flow after the ‘conversation’ node,
  • From the ‘output’ category, drag the ‘http response’ node to the flow, and connect the ‘http response’ node to the ‘function’ node,
  • Connect the nodes together to complete the flow,
  • Click the red ‘Deploy’ button to make the flow live,

We created the workflow skeleton, but none of the nodes are configured yet. Let’s configure the nodes:

  • Open and configure the ‘http input’ node:
    • Method: GET
    • URL: /slack/commands
    • Name: GET /slack/commands

  • Click the ‘Done’ button,
  • Open and configure the first ‘function’ node:
    • Name: Set Conversation Input
    • Function:
      msg.payload = msg.payload.text;
      return msg;

  • Click the ‘Done’ button,
  • Open and configure the ‘conversation’ node:
    • Username: <watson-conversation-username>
    • Password: <watson-conversation-password>
    • Name: Watson Conversation
    • Workspace ID: <watson-conversation-workspace-id>
    • Make sure the ‘Save context’ checkbox is checked,
  • Click the ‘Done’ button,
  • Open and configure the last ‘function’ node:
    • Name: Format Response
    • Function:
      msg.payload = msg.payload.output.text[0];
      return msg;
  • Click the ‘Done’ button,
  • Click the red ‘Deploy’ button to make the flow live,

To help you debug you can add ‘Debug’ nodes to different places in your workflow.

Add Token Validation of the Slack Request to Node-RED Flow

Right now, the origin of the Slack requests is not validated. I want to add validation of the origin, and I want to add a Redirect URL for the OAuth token validation step.

If you look at the Slack request’s body, by outputting the msg.payload to a Debug node, it looks as follows:
{
"token":"KGx1lat2rw3MQ0ajvQHJ1Bgl",
"team_id":"S1YABPGBD",
"team_domain":"remkohdev",
"channel_id":"A1VAGT3EE",
"channel_name":"general",
"user_id":"B1Z3VJSTR",
"user_name":"remkohdev",
"command":"/q",
"text":"hello",
"response_url":"https://hooks.slack.com/commands/S1YABPGBD/171555435546/bgdt4n4xPgSOwlv10FZOknae"
}

To add token validation, compare the token value in the request body to the token that is defined in the ‘App Credentials’ under ‘Basic Information’ of your Slack Application. I will add a token validation in Node-RED to compare the two values.

  • In your Node-RED flow, under the ‘funtion’ category, find the ‘switch’ node and drag the ‘switch’ node onto your flow. Double click the ‘switch’ node and configure the node with 2 conditions to compare the ‘msg.payload.token’ of the request:
    • Name: Validate Slack Token,
    • Property: msg.payload.token,
    • 1. == <copy-paste the token value from the App Credentials here>,
    • 2. otherwise,
  • Click the ‘Done’ button,
  • For ‘case 1’ when the token is valid, connect the ‘case 1’ dot to the previous Conversation flow starting with the ‘Set Conversation Input’ function node,
  • For ‘case 2’ for ‘otherwise’, add a ‘template’ node to the flow after the switch, and connect the ‘case 2’ dot to the ‘template’ node,
  • Double click to configure the ‘template’ node:
    • Name: Invalid Token Response,
    • Set Property: msg.payload,
    • Template: Your token is not a valid Slack token: {{payload.token}} !
  • Add an ‘http response’ node to return the ‘Not a valid Slack token’ message,
  • Your flow to handle the Slash Command from Slack with token validation should look as follows now:

Leave a Reply

Your email address will not be published. Required fields are marked *