Virtual Agent - Add Problem Area Skill Tag

Virtual agent for adding a problem area skill tag.

Request a Demo »

Note: The Virtual Agent can be downloaded here » Virtual Agent SDK (zip) (VirtualAgentSDK\Samples\CS-ScriptVirtualAgents\AddProblemAreaSkillTag.cs)

Overview

A powerful feature of Chime is skill tag routing. This feature allows the guest to select a problem area from the Web Client and be routed to an agent with a matching skill tag. This enhances the guest’s experience by routing them to an agent with expertise in the area they need help with.

However, what happens if the guests are not entering the queue from a Web Client and rather they are using Skype for Business to IM the queue? Enter Virtual Agents. This conversational Virtual Agent interviews guests by asking them to choose their problem area. When the selection is made, the Virtual Agent adds the Problem Area tag to the session just as if the guest had chosen it themselves from a Web Client. Then, with the queue setting set to skill tag routing, the session will route to any available agents with the matching skill tag.

Code Samples

This Virtual Agent uses an enum MyMultiLevelState to keep track of what state each session is in. There are three states that the session can be in with this virtual agent – Problem Area, Confirm, and Done. In the IncomingSeekerOffer method, the Virtual Agent caches the session ID and sets it’s state to the first state, Problem Area.

public bool IncomingSeekerOffer(int sessionId, string queueName, int queueID, string email, string question, PreviousSessionState? prevState)
{
    if (!_openSessions.ContainsKey(sessionId))
    {
        _openSessions.Add(sessionId, MyMultiLevelState.ProblemArea);
    }
    else
    {
        _openSessions[sessionId] = MyMultiLevelState.ProblemArea;
    }
    return true;
}

    
Next, when the SeekerConnected method is invoked, the Virtual Agent sends an IM to the guest prompting them to choose a problem area.

public bool SeekerConnected(int sessionId)
{
    _pluginManager.SendIMToSeeker(sessionId, ProblemAreaPrompt);
    return true;
}

    
In the ReceiveMessage method the virtual agent sanitizes the message from the guest and looks up the session’s state by the session ID. Then the Virtual Agent responds according to the state the session is in, either performing an action such as caching the problem area tag or sending an IM.

public bool ReceiveMessage(int sessionId, string email, string msg)
{
    _pluginManager.LogMessageInChime(LoggingLevel.Debug, "message received: " + msg);
    if (msg.Contains(ProblemAreaPrompt) //ignore messages from the virtual agent.
        || msg.Contains(Confirm0)
        || msg.Contains(Confirm1)
        || msg.Contains(Confirm2)
        || msg.Contains(Confirm3))
    {
        return true;
    }
    msg = SanitizeMessage(msg);

    if (msg.Length == 1)
    {
        if (_openSessions.ContainsKey(sessionId))
        {
            var currentState = _openSessions[sessionId];

            switch (currentState)
            {
                case MyMultiLevelState.ProblemArea:
                    switch (msg)
                    {
                        case "0":
                            _pluginManager.SendIMToSeeker(sessionId, Confirm0);
                            IncrementState(sessionId, currentState);
                            break;
                        case "1":
                            _pluginManager.SendIMToSeeker(sessionId, Confirm1);
                            StoreSkillTag(sessionId, "Hardware and Software");
                            IncrementState(sessionId, currentState);
                            break;
                        case "2":
                            _pluginManager.SendIMToSeeker(sessionId, Confirm2);
                            StoreSkillTag(sessionId, "Password");
                            IncrementState(sessionId, currentState);
                            break;
                        case "3":
                            _pluginManager.SendIMToSeeker(sessionId, Confirm3);
                            StoreSkillTag(sessionId, "Ariba");
                            IncrementState(sessionId, currentState);
                            break;
                        default:
                            _pluginManager.SendIMToSeeker(sessionId, "Unrecognized response");
                            break;
                    }
                    break;
                case MyMultiLevelState.Confirm:
                    switch (msg)
                    {
                        case "0": //Go Back
                            DecrementState(sessionId, currentState);
                            if (_sessionSkillTags.ContainsKey(sessionId))
                            {
                                _sessionSkillTags.Remove(sessionId);
                            }
                            _pluginManager.SendIMToSeeker(sessionId, ProblemAreaPrompt);
                            break;
                        case "1": //Confirm
                            _pluginManager.SendIMToSeeker(sessionId, "Thank you.");
                            SendSkillTagToChime(sessionId);
                            IncrementState(sessionId, currentState);
                            break;

                        default:
                            _pluginManager.SendIMToSeeker(sessionId, "Unrecognized response");
                            break;
                    }
                    break;
            }
        }
    }
    return true;
}


    

Full Source Code


using System;
using System.Collections.Generic;

public class AddProblemAreaSkillTag : IVirtualAgent
{
    IPluginManager _pluginManager;
    VirtualAgentState va_state;
    private Dictionary<int, MyMultiLevelState> _openSessions = new Dictionary<int, MyMultiLevelState>();
    private Dictionary<int, string> _sessionSkillTags = new Dictionary<int, string>();

    VirtualAgentProps vaData = new VirtualAgentProps("Add Problem-Area Skill Tag", "1", VirtualAgentType.Conversational, "Adds skill tag for the guest's problem area", "Instant Technologies");

    public Tuple<bool, VirtualAgentProps> Load()
    {
        va_state = VirtualAgentState.Online;
        return new Tuple<bool, VirtualAgentProps>(true, vaData);
    }

    public bool UnLoad()
    {
        _openSessions.Clear();
        return true;
    }

    public void SetPluginManager(IPluginManager pm)
    {
        _pluginManager = pm;
    }

    public VirtualAgentState GetState()
    {
        return va_state;
    }

    public bool IncomingSeekerOffer(int sessionId, string queueName, int queueID, string email, string question, PreviousSessionState? prevState)
    {
        if (!_openSessions.ContainsKey(sessionId))
        {
            _openSessions.Add(sessionId, MyMultiLevelState.ProblemArea);
        }
        else
        {
            _openSessions[sessionId] = MyMultiLevelState.ProblemArea;
        }
        return true;
    }

    public bool SeekerConnected(int sessionId)
    {
        _pluginManager.SendIMToSeeker(sessionId, ProblemAreaPrompt);
        return true;
    }

    public void SeekerDisconnected(int sessionId)
    {
        if (_openSessions.ContainsKey(sessionId))
        {
            _openSessions.Remove(sessionId);
        }
    }

    public bool ReceiveMessage(int sessionId, string email, string msg)
    {
        _pluginManager.LogMessageInChime(LoggingLevel.Debug, "message received: " + msg);
        if (msg.Contains(ProblemAreaPrompt) //ignore messages from the virtual agent.
            || msg.Contains(Confirm0)
            || msg.Contains(Confirm1)
            || msg.Contains(Confirm2)
            || msg.Contains(Confirm3))
        {
            return true;
        }
        msg = SanitizeMessage(msg);

        if (msg.Length == 1)
        {
            if (_openSessions.ContainsKey(sessionId))
            {
                var currentState = _openSessions[sessionId];

                switch (currentState)
                {
                    case MyMultiLevelState.ProblemArea:
                        switch (msg)
                        {
                            case "0":
                                _pluginManager.SendIMToSeeker(sessionId, Confirm0);
                                IncrementState(sessionId, currentState);
                                break;
                            case "1":
                                _pluginManager.SendIMToSeeker(sessionId, Confirm1);
                                StoreSkillTag(sessionId, "Hardware and Software");
                                IncrementState(sessionId, currentState);
                                break;
                            case "2":
                                _pluginManager.SendIMToSeeker(sessionId, Confirm2);
                                StoreSkillTag(sessionId, "Password");
                                IncrementState(sessionId, currentState);
                                break;
                            case "3":
                                _pluginManager.SendIMToSeeker(sessionId, Confirm3);
                                StoreSkillTag(sessionId, "Ariba");
                                IncrementState(sessionId, currentState);
                                break;
                            default:
                                _pluginManager.SendIMToSeeker(sessionId, "Unrecognized response");
                                break;
                        }
                        break;
                    case MyMultiLevelState.Confirm:
                        switch (msg)
                        {
                            case "0": //Go Back
                                DecrementState(sessionId, currentState);
                                if (_sessionSkillTags.ContainsKey(sessionId))
                                {
                                    _sessionSkillTags.Remove(sessionId);
                                }
                                _pluginManager.SendIMToSeeker(sessionId, ProblemAreaPrompt);
                                break;
                            case "1": //Confirm
                                _pluginManager.SendIMToSeeker(sessionId, "Thank you.");
                                SendSkillTagToChime(sessionId);
                                IncrementState(sessionId, currentState);
                                break;

                            default:
                                _pluginManager.SendIMToSeeker(sessionId, "Unrecognized response");
                                break;
                        }
                        break;
                }
            }
        }
        return true;
    }

    private string SanitizeMessage(string msg)
    {
        msg = msg.Replace("\n", ""); //remove line breaks
        if (msg.Contains(":"))
        {
            int colonIndex = msg.IndexOf(":");
            msg = msg.Remove(0, colonIndex + 1).Trim(); //remove client's name prefix such as "Jane Doe: Hi"
        }
        if (msg.Contains("-"))
        {
            int colonIndex = msg.IndexOf("-");
            msg = msg.Remove(0, colonIndex + 1).Trim(); //remove client's name prefix such as "Jane Doe- Hi"
        }
        return msg;
    }

    private void StoreSkillTag(int sessionId, string skillTag)
    {
        if (_sessionSkillTags.ContainsKey(sessionId))
        {
            _sessionSkillTags[sessionId] = skillTag;
        }
        else
        {
            _sessionSkillTags.Add(sessionId, skillTag);
        }
    }
    private void SendSkillTagToChime(int sessionId)
    {
        if (_sessionSkillTags.ContainsKey(sessionId))
        {
            var skillTag = _sessionSkillTags[sessionId];
            _pluginManager.AddSkillTags(sessionId, new List<string>() { skillTag });
        }
    }
    private static MyMultiLevelState? Next(MyMultiLevelState myEnum)
    {
        switch (myEnum)
        {
            case MyMultiLevelState.ProblemArea:
                return MyMultiLevelState.Confirm;
            case MyMultiLevelState.Confirm:
                return MyMultiLevelState.Done;
            default:
                return null;
        }
    }
    private void IncrementState(int sessionId, MyMultiLevelState currentState)
    {
        MyMultiLevelState? nextState = Next(currentState);
        if (nextState != null)
        {
            _openSessions[sessionId] = (MyMultiLevelState)nextState;

            if (nextState == MyMultiLevelState.Done)
            {
                _openSessions.Remove(sessionId);
                if (_sessionSkillTags.ContainsKey(sessionId))
                {
                    _sessionSkillTags.Remove(sessionId);
                }
                _pluginManager.DisconnectVirtualAgent(sessionId, true);
            }
        }
    }
    private static MyMultiLevelState? Previous(MyMultiLevelState myEnum)
    {
        switch (myEnum)
        {
            case MyMultiLevelState.Confirm:
                return MyMultiLevelState.ProblemArea;
            case MyMultiLevelState.Done:
                return MyMultiLevelState.Confirm;
            default:
                return null;
        }
    }
    private void DecrementState(int sessionId, MyMultiLevelState currentState)
    {
        MyMultiLevelState? prevState = Previous(currentState);
        if (prevState != null)
        {
            _openSessions[sessionId] = (MyMultiLevelState)prevState;
        }
    }



    public string ProblemAreaPrompt =
        string.Format("You have reached the IT Service Desk.  Please make a selection from the following menu.{0}{1}" +
                      "1: Computer Hardware or Software Support, including Outlook and Skype{0}{1}" +
                      "2: Password Assistance {0}{1}" +
                      "3: Ariba Application Support{0}{1}" +
                      "0: All Other Issues{0}{1}", Environment.NewLine, "</br>");

    public static string Confirm = "1: Confirm "+ Environment.NewLine + "</br>0: Go back</br>" + Environment.NewLine;
    public string Confirm0 = string.Format("You selected All Other Issues.{0}{1}{2}", Environment.NewLine, "</br>", Confirm);
    public string Confirm1 = string.Format("You selected Computer Hardware or Software Support.{0}{1}{2}", Environment.NewLine, "</br>", Confirm);
    public string Confirm2 = string.Format("You selected Password Assistance.{0}{1}{2}", Environment.NewLine, "</br>", Confirm);
    public string Confirm3 = string.Format("You selected Ariba Application Support.{0}{1}{2}", Environment.NewLine, "</br>", Confirm);
}

public enum MyMultiLevelState
{
    ProblemArea, Confirm, Done
}

    

Questions?

Have a question about Chime virtual agents? Ask one of our developers at InstantDev@instant-tech.com.