Wednesday, June 17, 2020

AWS Connect Chat/Lex Bot - Web Client via SDK


Summary

In this post, I cover development of a demo-grade chat web client against AWS Connect via direct integration with the Javascript SDK.  The Connect application utilizes a Lex chat-bot initially and allows escalation to an agent if self-service is not possible.

The code in this post was an interim step to a full AWS cloud integration that will be covered in a future posting.

Architecture

Diagram below of the overall architecture.  The AWS Javascript SDK is utilized for a customer-facing client application.  Agents use the out-of-box Contact Control Panel (CCP) application.  The overall interaction is managed via a AWS Connect flow that calls a Lex bot application.  The Lex bot application provides dialog and fulfillment validations via AWS Lambda function calls.

 

 

Call Flow

AWS Connect flow below.  This flow sends a chat interaction into a Lex bot that services intents for either self-service orders for firewood or a request for an agent.  If the agent intent is triggered, the interaction is sent to a queue for an agent.

 

Lex Bot

AWS Lex console screen-shot below of this simple firewood ordering bot.




AWS SDK Build 

The standard AWS Javascript SDK doesn't include the Connect and ConnectParticipant services, so you have to build your own browser include file.  Below are the steps to do that:

git clone git://github.com/aws/aws-sdk-js
cd aws-sdk-js
npm install
node dist-tools/browser-builder.js connect,connectparticipant > aws-connect.js

 

Web Client

Diagram and screen-shot below of the client app.  Its composition is a HTML page with vanilla Javascript.  The AWS Connect chat flow has multiple API calls to establish connectivity.  Once connectivity is established, Connect agents/Lex transmit chat messages over a Websocket to the client app.  The client app transmits chat messages via API calls to Connect.




Code Snippets


Main UI Driver

window.addEventListener('DOMContentLoaded', function() {
 const chat = new Chat();
    UIHelper.show(UIHelper.id('start'));
    UIHelper.hide(UIHelper.id('started'));
    UIHelper.id('startButton').onclick = function() {
        chat.start(UIHelper.id('firstName').value, UIHelper.id('lastName').value);
    }.bind(chat);
    UIHelper.id('sendButton').onclick = chat.send.bind(chat);
    UIHelper.id('leaveButton').onclick = chat.leave.bind(chat);
    UIHelper.id('firstName').autocomplete = 'off';
    UIHelper.id('firstName').focus();
    UIHelper.id('lastName').autocomplete = 'off';
    UIHelper.id('phrase').autocomplete = 'off';
    UIHelper.id('phrase').onkeyup = function(e) {
        if (e.keyCode === 13) {
            chat.send();
        }
    }.bind(chat);
        
    window.onunload = function() {
  if (chat) {
   chat.disconnect();
  }
    }.bind(chat); 
});

AWS SDK Driver Snippets

 async start(firstName, lastName) {
  if (!firstName || !lastName) {
   alert('Please enter a first and last name');
   return;
  } 
  else {
   this.firstName = firstName;
   this.lastName = lastName;
   await this._getToken();
   await this._connect();
   UIHelper.displayText('System:', 'Connecting...');
  }
 }

async _connect() {  
  try {
   const connectPart = new AWS.ConnectParticipant();
   const params = {
    ParticipantToken: this.partToken,
    Type: ['WEBSOCKET', 'CONNECTION_CREDENTIALS']
   };  
   const response = await connectPart.createParticipantConnection(params).promise();
   const diff = Math.abs(new Date() - Date.parse(response.Websocket.ConnectionExpiry));
   this.refreshTimer = setTimeout(this._connect, diff - 5000); //refresh the websocket
   this.connToken = response.ConnectionCredentials.ConnectionToken;
   this._subscribe(response.Websocket.Url);
  }
  catch (err) {
   console.log(err);
  }
 }

 async _getToken() {  
  try {
   const connect = new AWS.Connect();
   const partDetails = {
    DisplayName: this.firstName + ' ' + this.lastName
   }
   const params = {
    ContactFlowId: FLOW_ID,
    InstanceId: INSTANCE_ID,
    ParticipantDetails: partDetails
   };
   const response = await connect.startChatContact(params).promise();
   this.partToken = response.ParticipantToken;
  }
  catch (err) {
   console.error(err)
  }
 }

Source

https://github.com/joeywhelan/awsConnectSDKClient

Copyright ©1993-2024 Joey E Whelan, All rights reserved.