APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

【アップデート】Amazon Connectでスキル習熟度によるルーティングを実現

こんにちは、エーピーコミュニケーションズ クラウド事業部の山路です。

今回は昨年12月にアップデートされたAmazon ConnectのAgent Proficiencyの紹介です。

aws.amazon.com

背景

Amazon Connectのアップデートにより、エージェント毎にスキルの習熟度を設定し、その値に基づくルーティングを実現できるようになりました。

これにより、例えば特定の要件に対する問い合わせ対応を、スキルレベルの高いエージェントに優先して回すことができます。またルーティング設定には時間指定も出来るため、該当のエージェント以外にも段階的に着信を飛ばすことが可能です。

これまでエージェントごとに異なるルーティングを実現したい場合、Queue単位でルーティングを分けるといった方法がとられていたかと思いますが、エージェントレベルの細かい単位での振り分けも可能になった、という認識です。

検証

ユーザーへの権限付与

まずは既存のAgent proficiencyの設定を確認します。

Agent proficiencyを画面上で確認するには、ユーザーに対する権限付与が必要です。なお本機能アップデート後にインスタンスを作成した場合、初期ユーザーには初めから権限が付与されています。

docs.aws.amazon.com

ここでは test-user に対して、画面上で権限付与を行いました。

Predefined variablesの設定

Agent proficiencyでは Predefined variables (事前定義された属性) という設定を利用します。デフォルトでは connect:Language connect:Subtype という属性が設定されていますが、ここでは新規に作成します。

Agent proficiecnyは、ユーザーごとに設定したPredefined variablesの項目をもとに、ルーティングを制御します。そのため、Predefined variablesを作成後、ユーザーごとにその値とレベルを設定します。

今回は以下のCloudFormationファイルを使用して各リソースを作成しました。こちらにはPredefined variablesのほか、検証で使うユーザーなども定義しています。

agent-proficiency.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon Connect Agent proficiency test
Parameters:
  PJPrefix:
    Type: String
    Default: "connect-test-20240201"
  HoursOfOperationId:
    Type: String
  InstanceId:
    Type: String
  Password:
    Type: String

Resources:
  Queue01:
    Type: AWS::Connect::Queue
    Properties:
      HoursOfOperationArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}/operating-hours/${HoursOfOperationId}"
      InstanceArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
      Name: !Sub ${PJPrefix}-queue01
  RoutingProfile01:
    Type: AWS::Connect::RoutingProfile
    Properties:
      DefaultOutboundQueueArn: !GetAtt Queue01.QueueArn 
      Description: "routing profile for flow01"
      InstanceArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
      MediaConcurrencies: 
        - Channel: CHAT
          Concurrency: 1
        - Channel: TASK
          Concurrency: 1
        - Channel: VOICE
          Concurrency: 1
      QueueConfigs:
        - Delay: 0
          Priority: 1
          QueueReference: 
            Channel: VOICE
            QueueArn: !GetAtt Queue01.QueueArn 
      Name: !Sub "${PJPrefix}-routing-profile01"
  SecurityProfile:
    Type: AWS::Connect::SecurityProfile
    Properties:
      InstanceArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
      SecurityProfileName: !Sub "${PJPrefix}-security-profile-for-agent"
      Permissions:
        - BasicAgentAccess
        - OutboundCallAccess
  User01:
    Type: AWS::Connect::User
    Properties:
      IdentityInfo:
        FirstName: 'newcomer'
        LastName: 'newcomer'
        Email: 'example@email.com'
      InstanceArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
      Password: !Ref Password
      PhoneConfig:
        PhoneType: SOFT_PHONE
      RoutingProfileArn: !GetAtt RoutingProfile01.RoutingProfileArn
      SecurityProfileArns: 
        - !GetAtt SecurityProfile.SecurityProfileArn
      Username: "user-newcomer"
      UserProficiencies: 
        - AttributeName: "Skill"
          AttributeValue: "customer support"
          Level: 1
        - AttributeName: "Skill"
          AttributeValue: "technical support"
          Level: 1
  User02:
    Type: AWS::Connect::User
    Properties:
      IdentityInfo:
        FirstName: 'veteran'
        LastName: 'veteran'
        Email: 'example@email.com'
      InstanceArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
      Password: !Ref Password
      PhoneConfig:
        PhoneType: SOFT_PHONE
      RoutingProfileArn: !GetAtt RoutingProfile01.RoutingProfileArn
      SecurityProfileArns: 
        - !GetAtt SecurityProfile.SecurityProfileArn
      Username: "user-veteran"
      UserProficiencies: 
        - AttributeName: "Skill"
          AttributeValue: "customer support"
          Level: 5
        - AttributeName: "Skill"
          AttributeValue: "technical support"
          Level: 5
  PredefinedAttributes:
    Type: AWS::Connect::PredefinedAttribute
    Properties:
      InstanceArn: !Sub "arn:aws:connect:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
      Name: "Skill"
      Values: 
        StringList: 
          - "customer support"
          - "technical support"

docs.aws.amazon.com

フローの作成

続いてフローの作成です。ここでは以下のようなシナリオに基づいたテスト用フローを作成しました。

  • 同じQueueの中には、スキルレベルの異なる2人のエージェント (スキルレベルの高い user-veteran 、スキルレベルの低い user-newcomer) が属する。
  • 最初にスキルレベルの高いエージェントに優先してルーティングをし、出られない場合はスキルレベルの低いエージェントも対応可能にする。

フローの全体図は以下の通りです。

このうちAgent proficiencyは ルーティング条件の設定 (Set routing criteria) というブロックを利用します。このブロックはPredefined variablesのキーと値、条件に合致するレベルを設定します。またこのルーティングの有効期限も設定できます。

ここでは、CloudFormationで作成した Skill というPredefined variablesに含まれる customer support technical support という2つの値について、それぞれレベル3以上のエージェントに優先してルーティングするよう設定しました。

docs.aws.amazon.com

なお、今回のフローをContact flow languageで表現したものは以下になります。

Contact Flow

{
  "Version": "2019-10-30",
  "StartAction": "voice",
  "Metadata": {
    "entryPointPosition": {
      "x": 40,
      "y": 40
    },
    "ActionMetadata": {
      "voice": {
        "position": {
          "x": 141.6,
          "y": 41.6
        },
        "isFriendlyName": true,
        "overrideConsoleVoice": true
      },
      "workqueue": {
        "position": {
          "x": 140,
          "y": 253.6
        },
        "isFriendlyName": true,
        "parameters": {
          "QueueId": {
            "displayName": "connect-test-20240201-queue01"
          }
        },
        "queue": {
          "text": "connect-test-20240201-queue01"
        }
      },
      "queue": {
        "position": {
          "x": 670.4,
          "y": 36
        },
        "isFriendlyName": true
      },
      "routing-condition": {
        "position": {
          "x": 392,
          "y": 36.8
        },
        "isFriendlyName": true,
        "parameters": {
          "RoutingCriteria": {
            "Steps": [
              {
                "Expiry": {
                  "DurationInSeconds": {
                    "unit": 1
                  }
                }
              }
            ]
          }
        }
      },
      "prompt": {
        "position": {
          "x": 392.8,
          "y": 255.2
        },
        "isFriendlyName": true
      },
      "disconnect": {
        "position": {
          "x": 710.4,
          "y": 327.2
        },
        "isFriendlyName": true
      }
    },
    "Annotations": []
  },
  "Actions": [
    {
      "Parameters": {
        "TextToSpeechEngine": "Neural",
        "TextToSpeechStyle": "None",
        "TextToSpeechVoice": "Kazuha"
      },
      "Identifier": "voice",
      "Type": "UpdateContactTextToSpeechVoice",
      "Transitions": {
        "NextAction": "workqueue"
      }
    },
    {
      "Parameters": {
        "QueueId": "arn:aws:connect:ap-northeast-1:<AWS Account>:instance/<Instance ID>/queue/<Queue ID>"
      },
      "Identifier": "workqueue",
      "Type": "UpdateContactTargetQueue",
      "Transitions": {
        "NextAction": "routing-condition",
        "Errors": [
          {
            "NextAction": "disconnect",
            "ErrorType": "NoMatchingError"
          }
        ]
      }
    },
    {
      "Parameters": {},
      "Identifier": "queue",
      "Type": "TransferContactToQueue",
      "Transitions": {
        "NextAction": "disconnect",
        "Errors": [
          {
            "NextAction": "disconnect",
            "ErrorType": "QueueAtCapacity"
          },
          {
            "NextAction": "disconnect",
            "ErrorType": "NoMatchingError"
          }
        ]
      }
    },
    {
      "Parameters": {
        "RoutingCriteria": {
          "Steps": [
            {
              "Expression": {
                "AndExpression": [
                  {
                    "AttributeCondition": {
                      "Name": "Skill",
                      "Value": "customer support",
                      "ProficiencyLevel": 3,
                      "ComparisonOperator": "NumberGreaterOrEqualTo"
                    }
                  },
                  {
                    "AttributeCondition": {
                      "Name": "Skill",
                      "Value": "technical support",
                      "ProficiencyLevel": 3,
                      "ComparisonOperator": "NumberGreaterOrEqualTo"
                    }
                  }
                ]
              },
              "Expiry": {
                "DurationInSeconds": 10
              }
            }
          ]
        }
      },
      "Identifier": "routing-condition",
      "Type": "UpdateContactRoutingCriteria",
      "Transitions": {
        "NextAction": "prompt",
        "Errors": [
          {
            "NextAction": "disconnect",
            "ErrorType": "NoMatchingError"
          }
        ]
      }
    },
    {
      "Parameters": {
        "Text": "こちらはagent proficiencyのテスト用フローです。"
      },
      "Identifier": "prompt",
      "Type": "MessageParticipant",
      "Transitions": {
        "NextAction": "queue",
        "Errors": [
          {
            "NextAction": "disconnect",
            "ErrorType": "NoMatchingError"
          }
        ]
      }
    },
    {
      "Parameters": {},
      "Identifier": "disconnect",
      "Type": "DisconnectParticipant",
      "Transitions": {}
    }
  ]
}

動作確認

ここで動作確認をします。

まずは2人のエージェントがどちらも Available の場合です。

インスタンス宛に電話をすると、まずはスキルレベルの高い veteran が着信を受け取ります。

エージェントはデフォルトで20秒以内に応答しないと別のエージェントに着信が飛びます。ここでは約20秒経つと newcomer に切り替わりました。

次に veteran がOfflineの場合です。

ここではルーティング設定の通り、10秒ほど経過してから newcomer に着信する様子を確認しました。

さいごに

Agent proficiencyにより、これまで実装が難しかったルーティングも設定できるようになったのではないかと思います。今回はスキルレベルの高い人を優先しましたが、例えば新人エージェントを識別するようなPredefined variableを設定すれば、新人教育のため優先して着信を飛ばすことも出来そうです。

最後に、弊社はAWSアドバンスドティアサービスパートナー認定を受けております。また以下のようにAWSの活用を支援するサービスも行っているので、何かご相談したいことがあればお気軽にご連絡ください。

www.ap-com.co.jp