Create an Omnichannel Chatbot using Amazon Lex and Amazon Connect

Background

These days, chatbots are used pretty much everywhere. From getting quotes to resetting password, their use cases are endless. They also elevate the customer experience, as now customers don’t need to call during your helpdesk’s manned hours, instead they can call anytime that is convenient to them. One of the biggest business benefits is that of lessening the load on their support staff.

A good practice to adhere by, when deploying chatbots is to make them channel agnostic. This means that your chatbots are available via the internet and also via a phone call, and they provide the same customer experience. This enables your customers to choose whichever channel suits them best, without any loss of customer experience.

In this blog, I will demonstrate how you can use Amazon Connect and Amazon Lex, to create an omnichannel chatbot.

I will be extending one of my previous blogs, so if you haven’t read it already, I would highly recommend that you do so, prior to continuing. Here is the link to the blog https://nivleshc.wordpress.com/2020/04/08/create-a-web-chatbot-for-generating-life-insurance-quotes-using-amazon-lex/).

High Level Architecture Diagram

Below is the high-level architecture diagram for the solution. We will build the section inside the blue box.

For steps 1 – 5 please refer to https://nivleshc.wordpress.com/2020/04/08/create-a-web-chatbot-for-generating-life-insurance-quotes-using-amazon-lex/

For steps 6 – 8 please refer to https://nivleshc.wordpress.com/2020/05/24/publish-a-web-chatbot-frontend-using-aws-amplify-console/

Steps 9 – 12 will be created in this blog and are described below:

9. The customer calls the phone number for the chatbot. This is attached to a contact flow in Amazon Connect

10. Amazon Connect proxies the customer to the Amazon Lex chatbot (this is the web chatbot created in https://nivleshc.wordpress.com/2020/04/08/create-a-web-chatbot-for-generating-life-insurance-quotes-using-amazon-lex/ )

11. The output from the Amazon Lex chatbot is sent back to Amazon Connect.

12. Amazon Connect converts the output from the Amazon Lex chatbot into audio and then plays it to the customer.

Prerequisites

This blog assumes the following:

  • you already have an Amazon Connect instance deployed and configured.
  • you have a working Amazon Lex web chatbot

You can refer to the following blogs, if you need to deploy either of the above prerequisites

https://nivleshc.wordpress.com/2020/04/08/create-a-web-chatbot-for-generating-life-insurance-quotes-using-amazon-lex/

https://nivleshc.wordpress.com/2020/05/24/publish-a-web-chatbot-frontend-using-aws-amplify-console/

Implementation

Let’s get started.

  1. Login to your AWS Management Console, open the Amazon Connect console and change to the respective AWS region.
  2. Within the Amazon Connect console, choose the instance that will be used and click its Instance Alias.
  3. In the next screen, from the left-hand side menu, click Contact flows. Then, in the right-hand side screen, under Amazon Lex select the Region where the Amazon Lex bot resides. From the Bot drop-down list, select the name of the Amazon Lex bot. Once done, click +Add Lex Bot.
  4. Click Overview from the left-hand side menu, and then click Login URL to open the Amazon Connect administration portal. Enter your administrator credentials (currently only the following internet browsers are supported – latest three versions of Google Chrome, Mozilla Firefox ESR, Mozilla Firefox).
  5. Once logged in, from the left hand-side menu, click Routing and then Contact flows.
  6. Click Create contact flow (located on the top-right). You will now see the contact flow designer.
  7. Enter a name for the contact flow (top left where it says Enter a name)
  8. From the left-hand side menu, expand Interact and drag Get customer input to the right-hand side screen.
  9. Click on the circle to the right of Start in the Entry point block and drag the arrow to the Get customer input block. This will connect the two blocks.
  10. Click on the title of the Get customer input block to open its configuration.
  11. Select Text-to-speech or chat text. Click Enter text and in the textbox underneath, type the message you want to play to the customer when they call the chatbot.
  12. Click Amazon Lex and then under Lex bot Name select the Amazon Lex bot that you had created earlier (if the bot doesn’t show, ensure you had carried out step 3 above). Under Intents type the Amazon Lex bot intent that should be invoked. Click Save.

13. From the left-hand side menu, expand Interact and drag two Play prompt blocks to the right-hand side screen.

14. The first Play prompt block will be used to play a goodbye message, after the Amazon Lex bot has finished execution. Click on the title of this block to open its configuration. Click Text-to-speech or chat text and then click Enter text. Enter a message to be played before the call is ended. Click Save.

  15. The second Play prompt block will be used to play a message when an error occurs. Click on the title of this block to open its configuration. Click Text-to-speech or chat text and then click Enter text. Enter a message to be played when an error occurs. Click Save.

16. From the left-hand side menu, expand Terminate / Transfer and drag the Disconnect / hang up block to the right-hand side screen.

17. In the designer (right-hand side screen), in the Get customer input block, click the circle beside startConversation (this is the name of your Amazon Lex bot intent) and drag the arrow to the first Play prompt block.

18. Repeat step 17 for the circle beside Default in the Get customer input block.

19. In the Get customer input block, click the circle beside Error and drag it to the second Play prompt block.

20. Inside both the Play prompt blocks, click the circle beside Okay and drag the arrow to the Disconnect / hang up block.

21. From the top-right, click Save. This will save the work you have done.

22. From the top-right, click Publish. You will get a prompt Are you sure you want to publish this content flow? Click Publish.

23. Once done, you should see a screen similar to the one below:

24. Next, we need to ensure that whenever someone calls, the newly created contact flow is invoked. To do this, from the left-hand side menu, click Routing and then click Phone numbers.

25. In the right-hand side, click the phone number that will be used for the chatbot. This will open its settings. Enter a description (optional) and then from the drop-down list underneath Contact flow / IVR, choose the contact flow that was created above. Click Save.

Give it a few minutes for the settings to take effect. Now, call the phone number that was assigned to the contact flow above. You should be greeted by the welcome message you had created above. The phone chatbot experience would be the same as what you experienced when interacting with the chatbot over the internet!

Congratulations! You just created your first omnichannel chatbot! How easy was that?

Till the next time, Enjoy!

Creating a Contact Center in minutes using Amazon Connect

Background

In my previous blog (https://nivleshc.wordpress.com/2019/10/09/managing-amazon-ec2-instances-using-amazon-ses/), I showed how we can manage Amazon EC2 instances using emails. However, what if you wanted to go further than that? What if, instead of sending an email, you instead wanted to dial in and check the status of or start/stop your Amazon EC2 instances?

In this blog, I will show how I used the above as a foundation to create my own Contact Center. I enriched the experience by including an additional option for the caller, to be transferred to a human agent. All this in minutes! Still skeptical? Follow on and I will show you how I did all of this using Amazon Connect.

High Level Solution Design

Below is the high-level solution design for the Contact Center I built.

The steps (as denoted by the numbers in the diagram above) are explained below

  1. The caller dials the Direct Inward Dial (DID) number associated with the Amazon Connect instance
  2. Amazon Connect answers the call
  3. Amazon Connect invokes the AWS Lambda function to authenticate the caller.
  4. The AWS Lambda function authenticates the caller by checking their callerID against the entries stored in the authorisedCallers DynamoDB table. If there is a match, the first name and last name stored against the callerID is returned to Amazon Connect. Otherwise, an “unauthorised user” message is returned to Amazon Connect.
  5. If the caller is unauthorised, Amazon Connect informs them of this and hangs up the call.
  6. If the caller is authorised, Amazon Connect uses the first name and last name provided by AWS Lambda function to personalise a welcome message for them. Amazon Connect then provides the caller with two options:
      •  (6a) press 1 to get the status of the Amazon EC2 instances. If this is pressed, Amazon Connect invokes an AWS Lambda function to get the status of the Amazon EC2 instances and plays the results to the caller
      • (6b) press 2 to talk to an agent. If this is pressed, Amazon Connect places the call in a queue,  where it will be answered by the next available agent

     

Preparation

My solution requires the following components

  • Amazon DynamoDB table to store authorised callers (an item in this table will have the format phonenumber, firstname,  lastname)
  • AWS Lambda function to authenticate callers
  • AWS Lambda function to get the status of all Amazon EC2 instances in the region

I created the following AWS CloudFormation template to provision the above resources.

AWSTemplateFormatVersion: "2010-09-09"
Description: Template for deploying Amazon DynamoDB and AWS Lambda functions that will be used by the Amazon Connect instance
Parameters:
authorisedUsersTablename:
Description: Name of the Amazon DynamoDB Table that will be created to store phone numbers for approved callers to Amazon Connect
Type: String
Default: amzn-connect-authorisedUsers
DynamoDBBillingMode:
Description: Billing mode to be used for authorisedUsers Amazon DynamoDB Table
Type: String
AllowedValues: [PAY_PER_REQUEST]
Resources:
authoriseCallerLambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service:
lambda.amazonaws.com
Action:
sts:AssumeRole
Path: "/"
Policies:
PolicyName: logsStreamAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Action:
logs:CreateLogGroup
logs:CreateLogStream
logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
PolicyName: DynamoDBAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Action:
dynamodb:Query
Resource: !GetAtt authorisedUsersTable.Arn
getInstanceStatusLambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service:
lambda.amazonaws.com
Action:
sts:AssumeRole
Path: "/"
Policies:
PolicyName: logsStreamAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Action:
logs:CreateLogGroup
logs:CreateLogStream
logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
PolicyName: EC2DescribeAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Action:
"ec2:Describe*"
Resource: "*"
authoriseCallerFunctionPolicy:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt
authoriseCaller
Arn
Principal: connect.amazonaws.com
getInstanceStatusFunctionPolicy:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt
getInstanceStatus
Arn
Principal: connect.amazonaws.com
authorisedUsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Ref authorisedUsersTablename
AttributeDefinitions:
AttributeName: phoneNumber
AttributeType: S
KeySchema:
AttributeName: phoneNumber
KeyType: HASH
BillingMode: !Ref DynamoDBBillingMode
authoriseCaller:
Type: AWS::Lambda::Function
Properties:
FunctionName: "amzn-connect-authoriseCaller"
Description: "This function checks if the caller is authorised to use the Amazon Connect Service"
Handler: index.lambda_handler
Runtime: python3.6
Role: !GetAtt 'authoriseCallerLambdaExecutionRole.Arn'
Environment:
Variables:
AUTHORISEDUSERSTABLE: !Ref authorisedUsersTable
Code:
ZipFile: |
import boto3
import os
from boto3.dynamodb.conditions import Key, Attr
def lambda_handler(event, context):
print("event:",event)
print("context:",context)
authorisedUsersTable = os.environ['AUTHORISEDUSERSTABLE']
callerID = event["Details"]["ContactData"]["CustomerEndpoint"]["Address"]
#Establish connection to dynamoDB and retrieve table
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(authorisedUsersTable)
response = table.query(KeyConditionExpression=Key('phoneNumber').eq(callerID))
if (len(response['Items']) > 0):
firstName = response['Items'][0]['firstName']
lastName = response['Items'][0]['lastName']
else:
firstName = 'unauthorised'
lastName = 'unauthorised'
callerDetails = {
'phoneNumber' : callerID,
'firstName' : firstName,
'lastName' : lastName
}
print("CallerDetails:",str(callerDetails))
return callerDetails
getInstanceStatus:
Type: AWS::Lambda::Function
Properties:
FunctionName: "amzn-connect-getInstanceStatus"
Description: "This function checks and reports the number of EC2 instances that are running and stopped in the AWS region where this AWS Lambda function is running"
Handler: index.lambda_handler
Runtime: python3.6
Role: !GetAtt 'getInstanceStatusLambdaExecutionRole.Arn'
Code:
ZipFile: |
import boto3
def lambda_handler(event, context):
print("event:",event)
print("context",context)
ec2 = boto3.client("ec2")
ec2_status_running = ec2.describe_instances(
Filters=[
{
'Name':'instance-state-name',
'Values':['running']
}
]
)
ec2_status_running = ec2.describe_instances(
Filters=[
{
'Name':'instance-state-name',
'Values':['running']
}
]
)
ec2_status_stopped = ec2.describe_instances(
Filters=[
{
'Name':'instance-state-name',
'Values':['stopped']
}
]
)
num_ec2_running = len(ec2_status_running['Reservations'])
num_ec2_stopped = len(ec2_status_stopped['Reservations'])
result = {
'numberEC2Running': num_ec2_running,
'numberEC2Stopped': num_ec2_stopped
}
print("Number of EC2 instances running:",num_ec2_running)
print("Number of EC2 instances stopped:",num_ec2_stopped)
return result

The above AWS CloudFormation template can be downloaded from https://gist.github.com/nivleshc/926259dbbab22dd4890e0708cf488983

Implementation

Currently AWS CloudFormation does not support Amazon Connect. The implementation must be done manually.

Leveraging on my own experience with setting up Amazon Connect solutions,  I observed that there are approximately three stages that are required to get a Contact Center up and running. These are:

  • Provisioning an Amazon Connect instance – this is straight forward and essentially is where an Amazon Connect instance is provisioned and made ready for your use
  • Configuring the Amazon Connect instance – this contains all the tasks to customise the Amazon Connect instance. It includes the configuration of the Direct Inward Dial (DID), hours or operations for the Contact Center, Routing profiles, users etc
  • Creating a custom Contact flow – a Contact flow defines the customer experience of your Contact Center, from start to finish. Amazon Connect provides a few default Contact flows however it is highly recommended that you create one that aligns with your own business requirements.

Follow along and I will show you how to go about setting up each of the above mentioned stages.

Provision the Amazon Connect Instance

  1. From the AWS Console, open the Amazon Connect service. Select the Sydney region (or a region of your choice, however do keep in mind that at the moment, Amazon Connect is only available in a few regions)
  2. Enter an Access URL for your Amazon Connect Instance. This URL will be used to access the Amazon Connect instance once it has been provisioned.
  3. In the next screen, create an administrator account for this Amazon Connect instance
  4. The next prompt is for Telephony options. For my solution, I selected the following:
    1. Incoming calls: I want to handle incoming calls with Amazon Connect
    2. Outgoing calls: I want to make outbound calls with Amazon Connect
  5. In the next screen, Data Storage options are displayed. For my solution, I left everything as default.
  6. In the next screen, review the configuration and then click Create instance

Configure the Amazon Connect Instance

After the Amazon Connect instance has been successfully provisioned, use the following steps to configure it:

  1. Claim a phone number for your Amazon Connect Instance. This is the number that users will be calling to interact with your Amazon Connect instance (for claiming non toll free local numbers, you must open a support case with AWS, to prove that you have a local business in the country where you are trying to claim the phone number. Claiming a local toll-free number is easier however it is more expensive)
  2. Create some Hour of operation profiles. These will be used when creating a queue
  3. Create a queue. Each queue can have different hours of operation assigned
  4. Create a routing profile. A user is associated with a routing profile, which defines their inbound and outbound queues.
  5. Create users. Once created, assign the users to a predefined security profile (administrator, agent etc) and also assign them to a specific routing profile

Create a custom Contact flow

A Contact flow defines the customer experience of your Contact Center, from start to finish. By default, Amazon Connect provides a few Contact flows that you can use. However, it is highly recommended that you create one that suits your own business requirements.

To create a new Contact flow, follow these steps:

  • Login to your Amazon Connect instance using the Access URL and administrator account (you can also access your Amazon Connect instance using the AWS Console and then click on Login as administrator)
  • Once logged in, from the left-hand side menu, go to Routing and then click on Contact flows
  • In the next screen, click on Create contact flow
  • Use the visual editor to create your Contact flow

Once the Contact flow has been created, attach it to your Direct Inward Dial (DID) phone number by using the following steps:

  • from the left-hand side menu, click on Routing and then Phone numbers.
  • Click on the respective phone number and change its Contact flow / IVR to the Contact flow you want to attach to this phone number.

Below is a screenshot of the Contact flow I created for my solution. It shows the flow logic I used and you can easily replicate it for your own environment. The red rectangles show where the AWS Lambda functions (mentioned in the pre-requisites above) are used.

This is pretty much all that is required to get your Contact Center up and running. It took me approximately thirty minutes from start to finish (this does not include the time required to provision the Amazon DynamoDB tables and AWS Lambda functions). However, I would recommend spending time on your Contact flows as this is brains of the operation. This must be done in conjunction with someone who understands the business really well and knows the outcomes that must be achieved by the Contact Center solution. There is a lot that can be done here and the more time you invest in your Contact flow, the better outcomes you will get.

The above is just a small part of what Amazon Connect is capable of. For its full set of capabilities, refer to https://aws.amazon.com/connect/

So, if you have been dreaming of building your own Contact Center, however were worried about the cost or effort required? Wait no more! You can now easily create one in minutes using Amazon Connect and pay for only what you use and tear it down if you don’t need it anymore. However, before you start, I would strongly recommend that you get yourself familiar with the Amazon Connect pricing model. For example – you get charged a daily rate for any claimed phone numbers that are attached to your Amazon Connect Instance (this is similar to a phone line rental charge). Full pricing is available at https://aws.amazon.com/connect/pricing/).

I hope the above has given you some insights into Amazon Connect. Till the next time, Enjoy!