logo image

A Slack Slash Command is one way to write an integration with Slack to plug custom functionality into Slack for your team to use. Specifically, a Slash Command is an application that can be invoked by users in your Slack workspace. You can define the user input, what is returned to the user, and what is happening in the workflow behind the scenes.

To show how you can connect to the RMS Intelligent Risk Platform™ from a Slack Slash Command, let’s step through creating a Slash Command that a user can use to return the status of a given Risk Modeler workflow ID.

Technologies Used

  • Slack Slash Command is used to call an API endpoint.
  • Serverless framework is used to create the AWS infrastructure.
  • AWS API Gateway is used to create the API endpoint.
  • AWS Lambda is triggered by the API call and is the function that calls Risk Modeler.
    • The Lambda function in this tutorial is written in Python.
  • AWS CloudWatch is used for function logging.
  • AWS System Manager SSM Parameter Store is used for storing environment variables.

Prerequisites

Architecture

The Serverless Framework provides a way to quickly create and manage the AWS architecture behind the API that the Slack Slash Command calls.


 picture 1

Creating a New Serverless Application

The Serverless framework allows you to easily deploy an API endpoint by creating and managing the AWS infrastructure.

Start by creating a new Serverless application.

serverless create --template aws-python3 --path WorkflowSlackSlashCommand

This command creates a new project named workflow-status, and automatically generates serverless.yml to define the configuration for the service and handler.py which declares the Lambda function.

picture 2


When you open serverless.yml, you can see additional configuration settings you are able to provide for your service. For this tutorial, update the file with the following code.

Close
Expand

Copy to

      
        service: WorkflowSlackSlashCommand
frameworkVersion: '2'

provider:
name: aws
runtime: python3.8
lambdaHashingVersion: 20201221
functions:
workflow_status:
handler: handler.workflow_status
events:
- httpApi:
path: "/"
method: post
environment:
API_KEY: ${ssm:api_key}
ENV_URL: ${ssm:env_url}
service: WorkflowSlackSlashCommand
frameworkVersion: '2'

provider:
name: aws
runtime: python3.8
lambdaHashingVersion: 20201221
functions:
workflow_status:
handler: handler.workflow_status
events:
- httpApi:
path: "/"
method: post
environment:
API_KEY: ${ssm:api_key}
ENV_URL: ${ssm:env_url}
Close
Expand

Copy to

  • Service: specifies the name of serverless application.
  • Provider: defines the provider and runtime details.
  • Functions: defines the lambda function, its handler, and trigger. The lambda function is named workflow_status. The events parameter will create and configure an API gateway that accepts post requests and triggers the lambda function.
  • Environment: The api_key and env_url will be accessed from the AWS SSM parameter store.

Install Python Requirements

In Python, the Requests library will be used to make calls to Risk Modeler software. Add a requirements.txt file to your application, the Requests library in the requirements file, and install the requirement using the following command:

pip install -t src/vendor -r requirements.txt

This will generate the src folder with the required dependencies.

picture 3
 

Add Environment Variables to the Parameter Store

The environment variables API_KEY and ENV_URL for your tenant will be referenced from the AWS SSM parameter store. To add your values for those parameters to the store, run:

aws ssm put-parameter --name "api_key" --type "String" --value "api-key value"

aws ssm put-parameter --name "env_url" --type "String" --value "env-url value"

Writing the Handler for the Lambda Function

You are now ready to write the actual Lambda function. The user Slack command will make a POST request to API Gateway and any user input passed in through the event is encoded in the text field of the event body.

When the user submits no input with the slash command, the handler returns the five most recent workflow names and IDs. When the user submits a valid workflow ID, the function returns the workflow status. Otherwise, an error message is returned.

Close
Expand

Copy to

C#

      
        import sys
sys.path.insert(0, 'src/vendor') # Add installed library to path
import os
import json
import requests
import base64


def workflow_status(event, context):

# Decode workflow ID from user input
event_body = base64.b64decode(event["body"], validate=True)
workflow_id = event_body.split(b"text=")[1].split(b"&")[0].decode('utf-8')

# Structure Risk Modeler API call
rm_base_url = os.environ['ENV_URL'] + workflow_id
api_key = os.environ['API_KEY']
headers = {
'Authorization': api_key
}
payload={}

# Make Risk Modeler API call
response = requests.request("GET", rm_base_url, headers=headers, data=payload)

# Return response from Risk Modeler
if response.status_code == 200:

# User provides no input workflow ID
if workflow_id == "":
all_workflows = json.loads(response.text)["workflows"]
last_5_workflows = {}
for i in range(5):
workflow = all_workflows[i]
last_5_workflows[workflow["submitTime"]] = {
'workflow ID': str(workflow["id"]),
'Analysis Name': workflow["name"]
}
return json.dumps(last_5_workflows, indent=4)

# User provides workflow ID
else:
status = json.loads(response.text)['status']
return {
"text": 'workflow ID: ' + workflow_id + "\nstatus: " + status
}

else:
return response.text
import sys
sys.path.insert(0, 'src/vendor') # Add installed library to path
import os
import json
import requests
import base64


def workflow_status(event, context):

# Decode workflow ID from user input
event_body = base64.b64decode(event["body"], validate=True)
workflow_id = event_body.split(b"text=")[1].split(b"&")[0].decode('utf-8')

# Structure Risk Modeler API call
rm_base_url = os.environ['ENV_URL'] + workflow_id
api_key = os.environ['API_KEY']
headers = {
'Authorization': api_key
}
payload={}

# Make Risk Modeler API call
response = requests.request("GET", rm_base_url, headers=headers, data=payload)

# Return response from Risk Modeler
if response.status_code == 200:

# User provides no input workflow ID
if workflow_id == "":
all_workflows = json.loads(response.text)["workflows"]
last_5_workflows = {}
for i in range(5):
workflow = all_workflows[i]
last_5_workflows[workflow["submitTime"]] = {
'workflow ID': str(workflow["id"]),
'Analysis Name': workflow["name"]
}
return json.dumps(last_5_workflows, indent=4)

# User provides workflow ID
else:
status = json.loads(response.text)['status']
return {
"text": 'workflow ID: ' + workflow_id + "\nstatus: " + status
}

else:
return response.text
Close
Expand

Copy to

Deploying the Serverless Application

Deploying the Lambda function handler and Serverless application configuration is done using the Serverless deploy command.

sls deploy -v

This command creates an AWS CloudFormation template and deploys the stack in AWS. The stack outputs will be returned on the command line, including an HttpApiUrl to point the Slack application to.

You can view the progress in the Cloudformation dashboard, and once complete, you can also view the API Gateway and Lambda dashboards in AWS. Logging for requests made to the Lambda function are captured in AWS CloudWatch.

Configuring the Slack Slash Command

Now that you have an API URL, you can create a Slack app here to call the API. Create an app from scratch, provide an App Name and Workspace, and click Create App. You may need to request admin approval to install your app to the workspace.

rms

Navigate into the App you created and click on  Slash Commands under Add Features and Functionality, then click on Create New Command.

rms
 
The fields for the new command should be filled out as follows:

  • Command: name of the slash command to be accessed from Slack. The command must start with a /, be all lowercase, and have no spaces.
  • Request URL: API endpoint from AWS API Gateway, returned as  HttpApiUrl above.
  • Short Description: description to be shown to the user in the Slack App.
  • Usage Hint:  hint for users, including any parameters that can be passed into the command.

Test Out Your New Slack Slash Command

Finally, let’s test our new Slack Slash Command!

Once the application is installed on your Slack workspace, you will be able to preview the application functions and autocomplete entries when you type /workflow in Slack.

rms

The command /workflow with no user input returns the five most recent workflow names and IDs.

rms

The command with a valid workflow ID /workflow 4406222 returns the workflow status.

rms

The command with an invalid workflow ID /workflow 123 returns an error message from Risk Modeler .


rms

Manage Message Visibility

By default, the message will be visible only to the user who triggered the command. This is because the JSON returned from API Gateway to Slack has response_type = ephemeral in the response.

To make the command visible to all members of the channel where the command was triggered, response_type can be set to in_channel. For example, the sample response in the function handler that is passed out of API Gateway:

return {

"text": 'workflow ID: ' + workflow_id + "\nstatus: " + status

}

Becomes:

return {

"response_type": "in_channel"

"text": 'workflow ID: ' + workflow_id + "\nstatus: " + status

}

Redeploy using sls deploy and the command will be visible to all members of the channel where the command is triggered.

Alexandria Julius
Alexandria Julius
Technical Consultant

Alexandria Julius is a technical consultant on RMS’s Consulting team. As a technical consultant, she works on custom solution implementations to integrate clients with RMS products. She is responsible for workflow design, custom software development, testing, and reporting. She holds a BS in Engineering Science from Smith College and a MS in Geodetic Engineering and Remote Sensing from The Ohio State University. Alexandria is based in the RMS Hoboken, New Jersey office.

Tech Banner

Questions or Feedback on Current Blog Posts? Suggestions for Upcoming Blog Posts?

close button
Overlay Image
Video Title

Thank You

You’ll be contacted by an Moody's RMS specialist shortly.