Contact Center Ticket Automation with Amazon Connect, Lex and Lambda

Using serverless systems inside your Amazon Connect workflow can simplify and automate business processes.

Wed, 02 Oct 2019

Integrating LexBots and Lambda functions into your Amazon Connect workflows can help solve your call center automation needs. At Trek10, we use Lex and Lambda in our call center workflow to convert verbal inputs from a caller to text and use those values to automatically submit a support ticket from the caller’s organization. This blog will explain how Trek10 integrated AWS serverless systems into a manual process to solve a business need.

The Problem

Here at Trek10, we have a call center to handle inbound client phone calls. If an end-user needs assistance and calls Trek10’s support number, the call center agent handles the call, takes some necessary information such as the caller name, caller organization, and a brief message. The call center agent then takes this information and puts it into an email which submits an urgent ticket into Trek10’s ticketing system. These tickets are not tied to specific clients when they enter the system. Instead, a Trek10 agent has to decipher what client has an issue, what that issue is, and if that issue is an urgent or normal priority. Calls like this are not as frequent these days due to the level of monitoring Trek10 provides in the client environment. Usually, any issues within a client’s AWS environment arise before the client notices as monitors trigger and alert Trek10 agents. Clients can submit tickets via email if needed but calling a number, as old school as that may seem nowadays, needs to be an option for the client no matter what.

As seasoned and refined as the processes above may be, there are some issues with the above system:

  • Tickets submitted by the call center are all urgent priority no matter the issue
  • Inability to filter tickets by client organization and end-user when a ticket is submitted

The Solution

Like many things AWS, Amazon has a solution: Amazon Connect. When AWS came out with Amazon Connect, Trek10 found that making workflows for call centers was incredibly powerful, and over time, discovered how to integrate other AWS services into workflows. Recognizing this was a game changer. We were able to create an automated workflow that solved all of our call center ticketing problems.

Here is a snippet of the Connect workflow we created to automate caller support tickets:

Connect workflow with Lambda and Lex integrations

The AWS serverless services we tie together in this workflow are Connect, Lambda, Lex, and DynamoDB as well as our ticketing system’s API. All services work together to take a client’s call, know who the client is right away, allow the client to input ticket information via voice, convert voice inputs to text, store the caller information and voice inputs in a database, and create a ticket in Trek10’s ticketing service.

Before fully going live with this workflow, we needed to come up with a solution to get around a limitation with our ticketing system. To route tickets to the correct client organization, the ticketing system requires a client email address. However, Amazon Connect does not readily store this information. To resolve this, we created a DynamoDB table with the names, email addresses, and phone numbers of the clients using the system. Now, when a client calls in, a Lambda function is triggered that grabs the users information from the DynamoDB table, and a LexBot voice welcomes the caller with their name and organization before asking the caller anything. It is certainly a nice touch, even if it is a robot talking to you.

After the initial niceties, the LexBot asks for the ticket priority and for the caller to summarize the issue. The caller’s responses convert to text, and a Lambda function takes those LexBot responses and inputs them into a DynamoDB table once the call is over. The same Lambda function takes the caller’s email address, ticket priority and issue, and submits a ticket using the ticketing system API. The ticket enters the system under the caller’s organization with the correct priority. (Note: If an unknown caller calls in, the workflow directs the caller to a separate LexBot that asks for the caller’s name, organization, ticket priority and issue. This process then creates a general ticket with the priority stated by the caller along with the remaining information provided by the caller.)

The LexBot used to receive information from a known caller is listed below:

Lexbot with ticket creation Lambda function as fulfillment

The above LexBot has slots for priority type and issue. The LexBot asks the caller if their issue is of lower priority or a more urgent matter. The caller also explains the issue in a few words.

When the caller inputs are complete, a Lambda function fulfills the request by storing all of the information in a DynamoDB table and creates a ticket in Trek10’s ticketing system via API. A snippet of the Lambda function is below:

import logging
import boto3
import json
from boto3.dynamodb.conditions import Key
from zdesk import Zendesk


logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# Get the service resource.
dynamodb = boto3.resource('dynamodb')

# Instantiate a table resource object
db_table = dynamodb.Table('dynamotableA')
br_table = dynamodb.Table('dynamotableB')

""" --- Main handler --- """

def lambda_handler(event, context):
    logger.debug(json.dumps(event))
    logger.debug('event.bot.name={}'.format(event['bot']['name']))
    logger.debug('dispatch userId={}, intentName={}'.format(event['userId'], event['currentIntent']['name']))
    logger.debug('entire.event={}'.format(event))


    # Validate intent name
    intent_name = event['currentIntent']['name']
    if intent_name != 'lexbotintent':
        raise Exception('Intent with name ' + intent_name + ' not supported!')

    # Validate invocation source
    source = event['invocationSource']
    if source == 'DialogCodeHook':
        raise Exception('This Lambda function only support fulfillment')

    # Get bot slot values
    issue = event['currentIntent']['slots']["issue"]
    prioritytype = event['currentIntent']['slots']["prioritytype"]

    ## Get customer number from DynamoDB table
    response = br_table.query(
        TableName='dynamotableB',
        IndexName='constant-timestamp-index',
        Select='ALL_ATTRIBUTES',
        Limit=1,
        ConsistentRead=False,
        ScanIndexForward=False,
        KeyConditionExpression=Key("constant").eq("a")
    )
    phoneNumber = response['Items'][0]['phoneNumber']
    
    update_response = db_table.update_item(
        Key={
            "phoneNumber": phoneNumber,
        },
        UpdateExpression='SET issue = :issue, prioritytype = :prioritytype',
        ExpressionAttributeValues={
            ":prioritytype": prioritytype,
            ":issue": issue
        }
    )
    
    get_customer_info = db_table.get_item(
        TableName='dynamotableA',
        Key={
            "phoneNumber": phoneNumber,
        },
    )['Item']
    
    #create ticket in zendeks with dynamodb and lexbot values
    SSM_CLIENT = boto3.client('ssm')
    zd_secret = SSM_CLIENT.get_parameter(
        Name='ssm_secret_key_name',
        WithDecryption=True
    )['Parameter']['Value']
    zendesk = Zendesk('companyzendeskurl', 'zendesk_user_email', zd_secret, True)
    new_ticket = {
    'ticket': {
        'requester': {
            #'name': get_customer_info['firstName'],
            'email': get_customer_info['email'],
        },
        'subject': 'Ticket Subject Here',
        'description': get_customer_info['issue'],
        'tags': ['key1', 'value1'],
        'priority': get_customer_info['prioritytype']
        }
    }
    zd = zendesk.ticket_create(data=new_ticket)
    logger.debug(zd)
    
 # Define the return response to the Lex bot in the required Lex response format. The
    # The Lex response format is documented here: http://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html#using-lambda-response-format
    intent_fulfillment_response = { 'sessionAttributes': event["sessionAttributes"],
       'dialogAction': {
            'type': 'Close',
            'fulfillmentState': 'Fulfilled',
            'message':
            {'contentType': 'SSML',
            # Message to return to the Lex bot 
             'content': 'Thank you. A ticket was sucessfully created. A Trek10 agent will be online and respond shortly. Have a great day.'}
        }
    }

    return intent_fulfillment_response

After a successful invocation, the Connect workflow confirms to the caller that a ticket has been created and ends the call. A ticket is submitted, and a Trek10 agent assists based on the priority level.

With the combined power of the AWS services above, we have alleviated all of the original issues. You can start to see the power of AWS and how different AWS systems can work together to solve business process needs. If you are looking to create your own Amazon Connect call center, if you would like to integrate automation or other services into your already created Amazon Connect workflow, or get expert advice with any AWS system, please contact us at Trek10 and we’ll be happy to explore the possibilities of how we can help.

Loading...
James Foley

James Foley

CloudOps Process Engineer

James comes from a background in project management and operations. He brings that experience to Trek10 working to improve internal processes with a focus on scalability.More Posts by James