handover-genesys dialogs

Description of the handover-genesys dialogs that use the bypass mode. Currently, these dialogs are only available for WhatsApp channel.

Introduction

The Github repository handover-genesys includes the available family of dialogs for the management of the handover use case for WhatsApp channel.

The dialog handover-bypass-dialog.ts uses the bypass mode to allow a direct connection with Genesys and, once activated, aura-bot directly sends the communication to a Genesys’ agent.

Remember that the main functionality of bypass mode, is that once we are in bypass mode within a conversation, any input message to the aura-bot will be directly sent to the external service. Likewise, any message from the external service will be shown to the user without going through aura-bot recognition system.

Settings

This section describes the configuration of handover-bypass-dialog.ts dialog in aura-configuration-api.

Currently, this dialog is exclusively configured for WhatsApp channel and certain intents. Check the configuration in the settings/ repository, by OB and language.

An extract of the dialog-config.json file is included below:

{
      "id": "handover-bypass",
      "suggestions": false,
      "triggerConditions": [
        {
          "intent": "intent.common.handover"
        },
        {
          "intent": "intent.common.help"
        },
        {
          "intent": "intent.miscellaneous.advice"
        }
      ],
      "onlyIn": [
        "whatsapp",
        "whatsapp2"
      ]
    },

I18n

key example (es-cr)
handover:handover.connect-to-agent Debido a la naturaleza de tu petición, vamos a intentar ponerte en contacto con un agente de nuestro servicio de atención.
handover:handover.end-of-handover Recuerda que puedo seguir ayudándote.
handover:handover.error-connecting-to-agent Se ha producido un error y no podemos contactar con los agentes, recuerda que seguimos atendiéndote en el 1004 y Movistar.es. También puedes intentarlo más tarde.
handover:handover.error-message-to-genesys Se ha producido un error al enviar tu mensaje.
handover:handover.off-hours-message Recuerda que seguimos atendiéndote en el 1004 y Movistar.es.
handover:handover.unexpected-error Se ha producido un error y no podemos contactar con los agentes, recuerda que seguimos atendiéndote en el 1004 y Movistar.es. También puedes intentarlo más tarde.

Flows

If the recognized intent for a user’s message is handled by handover-genesys dialogs, the main dialog will pass the conversational flow to it.

Validating the incoming message

aura-bridge sends all messages from Handover with auraCommand information in channelData. The auraCommand has the following format:

{
   type: AuraCommandType.Suggestion,
   value: { intent: env.AURA_GENESYS_AURA_COMMAND_DEFAULT_INTENT }
}

Therefore, if the AURA_GENESYS_AURA_COMMAND_DEFAULT_INTENT environment variable value is set with the intent associated with this dialog, all messages from Handover will be managed by this one regardless of the bypass state (the aura-bot recognizers will send it directly to the associated dialog with the intent).

This also implies that a Handover message can arrive and there is not a chat session opened with Handover. To deal with this behavior, a new step has been added: validatorMessageStep.

In this previous step to validate the incomming message, if the message has been sent from Handover and the bypass model is not in conversationData (bypass not created), then the message is ignored. Otherwise, the message will be processed by the next step: startStep.

Start bypass mode

The first time a user accesses this dialog, the cached information about bypass mode will not exist in the conversationData, so the OnInit step of the dialog will be invoked to start the communication with the Handover system.

At the beginning of the process, the dialog will create the bypass model with the following initial values:

  • Bypass state: Init
  • Genesys connection state: Connecting
  • Bypass model TTL: Value of the HANDOVER_BYPASS_MODEL_TTL variable

Afterwards, the dialog will send a information message to the user (handover:handover.connect-to-agent) and you will make a request to the Genesys Request Chat endpoint using genesis-api-client.

The request to connect with Genesys contains the following information:

{
      "nickname": "", // Obtained from the information sent by the bridge or at its defect activity.from.id
      "userData": {}  // Detailed in "User Data profiles" section
}

If the connection was made correctly, we will have a new chat to communicate with Handover identified by the field chatId. Immediately, and using the information obtained in the previous step, the previous message exchanged between the user and Aura will be sent to Genesys using Genesys Send Message endpoint.

Format is described in Message history format

Finally, the dialog will keep the bypass model in conversationData as follows:

  • Bypass state: Bypass
  • Genesys connection state: Connected
  • Session: Chat information obtained in response to the call Genesys Request Chat

If the variable HANDOVER_ALWAYS_USE_REMOTE_CACHE is configured to true, data will be saved remotely in the cache.

@startuml
title Start bypass mode

actor User
participant Channel #2f9c3c
participant Bridge #3275a8
participant Bot #ebba65
participant NLPRecognizerMiddleware
participant BypassModeMiddleware
participant BypassDialog
participant Genesys #ebdff7

User->Channel: Write: "I want to speak with agent"
Channel->Bridge: Channel Message Request
Note right of Channel: <example>
Bridge->Bot: DL Message
Note right of Bridge: <example>
Bot->NLPRecognizerMiddleware: recognize from context
NLPRecognizerMiddleware->NLPRecognizerMiddleware: recognized intent: intent.common.handover
NLPRecognizerMiddleware->BypassModeMiddleware: request context
Note right of BypassModeMiddleware: does nothing
BypassModeMiddleware->BypassDialog: request context
BypassDialog->BypassDialog: OnInit
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "handover:WA.handover.connect-to-agent"
Note right of BypassDialog: Set bypass to "Init" state
BypassDialog->Genesys: Request Chat
Genesys->BypassDialog:
BypassDialog->Genesys: Send Message (message history)
Genesys->BypassDialog:
Note right of BypassDialog: Set bypass to "Bypass" state
Genesys->Bridge: PushNotification - Conversation starter messages with genesys
Bridge->Bot:
Note right of Bot: For simplicity, we did not add the full bot sequence diagram
Bot->Bridge:
Bridge->Channel:
Channel->User: Conversation starter messages with genesys

@enduml

Error connecting with Handover

In case of error when the request is made to the Genesys Request Chat endpoint using genesis-api-client, the bypass model information will be deleted in conversationData, error logs informations will be generated and the message handover:handover.error-connecting-to-agent to the user will be sent.

@startuml
title Error connecting with handover

actor User
participant Channel #2f9c3c
participant Bridge #3275a8
participant Bot #ebba65
participant NLPRecognizerMiddleware
participant BypassModeMiddleware
participant BypassDialog
participant Genesys #ebdff7

User->Channel: Write: "I want to speak with agent"
Channel->Bridge: Channel Message Request
Note right of Channel: <example>
Bridge->Bot: DL Message
Note right of Bridge: <example>
Bot->NLPRecognizerMiddleware: recognize from context
NLPRecognizerMiddleware->NLPRecognizerMiddleware: recognized intent: intent.handover.bypass.init
NLPRecognizerMiddleware->BypassModeMiddleware: request context
Note right of BypassModeMiddleware: does nothing
BypassModeMiddleware->BypassDialog: request context
BypassDialog->BypassDialog: OnInit
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "handover:WA.handover.connect-to-agent"
BypassDialog->Genesys: Request Chat
Genesys->BypassDialog:
BypassDialog->BypassDialog: Capture and log error
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "handover:WA.handover.error-connecting-to-agent"

@enduml

Sending user messages

Being in a bypass state, any message received in the dialog will be processed by the onByPass method.

Once the bypass mode has started (see Start bypass mode), any user message will be sent to Genesys using sendGenesysMessageToAgent (genesis-api-client).

Then, the bypass model is updated with the alias field returned by the previous call.

If an error occurs, error logs will be generated and an error message will be sent to the user with handover:handover.error-message-to-genesys key.

Receiving agent or system messages

Being in a bypass state, any message received in the dialog will be processed by the onByPass method.

When a message is received from Genesys, the message handler returns a function to handle this message using participantType and eventType fields.

Messages currently handled (using eventType) for agent or system:

  • message. Debug logs will be generated and the message of context.activity.text is sent to the user using sendActivity.
@startuml
title Agent or System send information

actor User
participant Agent #ebdff7
participant Channel #2f9c3c
participant Bridge #3275a8
participant Bot #ebba65
participant BypassModeMiddleware
participant BypassDialog

Agent->Bridge: Write: "Hello, I am an Agent, how can I help you?"
Bridge->Bot: DL Message
Bot->BypassModeMiddleware: request context
Note right of BypassModeMiddleware: bypass state (continue)
BypassModeMiddleware->BypassDialog: request context
BypassDialog->BypassDialog: OnBypass
BypassDialog->BypassDialog: externalMessageHandler.message
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "Hello, I am an Agent, how can I help you?"

@enduml

Conversation close

The conversation can only be closed by Genesys. To close the conversation, Genesys will send a closing message with quit-reason-code information (GCTI_SYSTEM field).

When the dialog receives this information, the message handler returns a function to handle this message using participantType (Client) and eventType (ParticipantLeft) fields:

  • participantLeft. It closes the bypass (the bypass model information will be deleted in conversationData) and sends activity to the user with handover:handover.end-of-handover message.

The Handover offhours section describes the closing process in detail.

Handover offhours

When Genesys is in offhours state, the connection will normally be done as described by the process Start bypass mode, but it will immediately send information indicating that it is in offhours state.

Any information message sent by Genesys will be sent to the user using sendActivity. After this, Genesys will send a closing message with quit-reason-code equal to 5 (GCTI_SYSTEM field).

{
   "from": {
         "nickname": "UserNickname",
         "participantId": 1,
         "type": "Client"
   },
   "index": 4,
   "type": "ParticipantLeft",
   "utcTime": 1616662697000,
   "eventAttributes": {
         "GCTI_SYSTEM": {
            "quit-reason-code": "5"
         }
   }
}

In this case, the message handler returns a function to handle this message using participantType (Client) and eventType (ParticipantLeft) fields.

  • participantLeft. It closes the bypass (the bypass model information will be deleted in conversationData) and sends activity to user with handover:handover.off-hours-message message.
@startuml
title Handover off hours

actor User
participant Channel #2f9c3c
participant Bridge #3275a8
participant Bot #ebba65
participant NLPRecognizerMiddleware
participant BypassModeMiddleware
participant BypassDialog
participant Genesys #ebdff7

User->Channel: Write: "I want to speak with agent"
Channel->Bridge: Channel Message Request
Bridge->Bot: DL Message
Bot->NLPRecognizerMiddleware: recognize from context
NLPRecognizerMiddleware->NLPRecognizerMiddleware: recognized intent: intent.handover.bypass.init
NLPRecognizerMiddleware->BypassModeMiddleware: request context
Note right of BypassModeMiddleware: does nothing
BypassModeMiddleware->BypassDialog: request context
BypassDialog->BypassDialog: OnInit
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "handover:WA.handover.connect-to-agent"
BypassDialog->Genesys: Request Chat
Genesys->BypassDialog:
Note right of BypassDialog: Create conversationData.bypassMode with default data and status BYPASS
Genesys->Bridge: Hello! Yes, this is an automated message because we are not available right now ...
Bridge->Bot: DL Message
Bot->BypassModeMiddleware: request context
Note right of BypassModeMiddleware: bypass state (continue)
BypassModeMiddleware->BypassDialog: request context
BypassDialog->BypassDialog: OnBypass
BypassDialog->BypassDialog: externalMessageHandler.message
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "Hello! Yes, this is an automated ..."

Genesys->Bridge: ParticipantLeft (quit-reason-code: "5")
Bridge->Bot: DL Message
Bot->BypassModeMiddleware: request context
Note right of BypassModeMiddleware: bypass state (continue)
BypassModeMiddleware->BypassDialog: request context
BypassDialog->BypassDialog: OnBypass
BypassDialog->BypassDialog: clientMessageHandler.participantLeft
Note right of BypassDialog: close bypass
BypassDialog->Bot:
Bot->Bridge:
Bridge->Channel:
Channel->User: Message: "handover:handover.off-hours-message"

@enduml

Non-controlled exceptions

If an error not indicated previously in the flows occurs in any procedure, error logs information will be generated and the message handover:handover.unexpected-error to the user will be sent.

Settings

This section lists and describes all the variables the handover-genesys dialog uses and that can be configured to adapt the environment:

Property Type Description
HANDOVER_BYPASS_MODEL_TTL number Bypass model TTL. By default: 25
HANDOVER_CHAT_SERVICE_NAME string Genesys chat service name. By default: request-whatsapp-aura
HANDOVER_CHECK_STATUS_CHAT_SERVICE_NAME string Genesys chat service name to testing. By default: request-whatsapp-testaura
HANDOVER_USERDATA_GCTI_GMS_NODEGROUP string userData value to GCTI_GMS_NODEGROUP. By default: GMS_Cluster
HANDOVER_CLIENT_BASIC_AUTH_NAME string User for basic authentication in genesys api. By default ``
HANDOVER_CLIENT_BASIC_AUTH_PASSWORD string Password for basic authentication in genesys-api. By default ``
HANDOVER_CLIENT_BASE_PATH_URL string Base path to genesis-api-client.
HANDOVER_ALWAYS_USE_REMOTE_CACHE boolean Always use remote cache to keep conversation. By default: false

Message history format

As mentioned above, after connecting with Genesys, the message history is sent as an ordinary message. This message must meet the following format:

  (<DATE_ISO_FORMAT>)[<Usuario|AURA>]:<MESSAGE>

Example of message historic in the correct format:

   (2021-03-15T09:48:23)[Usuario]:Hola
   (2021-03-15T09:48:24)[AURA]:Hola. ¿Qué puedo hacer por ti?
   (2021-03-15T09:48:26)[Usuario]:¿Cuál es el importe de mi factura?

Connection’s profiles

The dialog can use a different profile to send specific data in userData on the request to Genesys Request Chat for each OB.

Currently, only the configuration for es is available.

es

userData field value
userData[GCTI_GMS_PushDeviceId] AuraConversationData model in base64
userData[GCTI_GMS_NodeGroup] Value of HANDOVER_USERDATA_GCTI_GMS_NODEGROUP variable
userData[GCTI_Chat_AsyncMode] true
userData[GCTI_Chat_PushSubscribe] true
userData[GCTI_GMS_PushDeviceType] customhttp
userData[GCTI_GMS_NotifyRequestor] true
userData[GCTI_GMS_PushIncludePayload] true
userData[GCTI_GMS_PushDebug] true
userData[nickname] Obtained from the information sent by the bridge or, failing that, from activity.from.id
userData[telefono] activity.from.id
userData[TipoAtencion] ‘GP_Atencion’
userData[Origen_N1] ‘Whatsapp’
userData[RoutingEspecifico] ''

the field userData[GCTI_GMS_PushDeviceId] is an object that must implement the auraConversationData interface (defined in @telefonica/aura-utilities/lib/aura-models), but it is coded in base64 to be sent in the request as a string.

/**
 * @interface AuraConversationData
 * @description Information needed to keep the conversation between handover and the bot.
 */
export interface AuraConversationData {
    auraId: string;
    auraChannelId: string;
    conversationId: string;
    correlator: string;
    answerCallback?: string;
}

This field, therefore, must be decoded in base64 to be managed correctly.