はじめに
近年コンタクトセンター業務では、カスタマーハラスメントと呼ばれる理不尽なクレームな暴力的な言動が多く見受けられ、エージェントを守るために様々な対策を行う必要性が出てきています。
Amazon Connectでは「ルール」という機能を使用することにより、禁止ワード発話時にアクションを起こすことができます。
この記事では、Amazon Connectの「ルール」と、Salesforceの「カスタム通知」の機能を組み合わせて、禁止ワード発話時に、スーパーバイザーのSalesforceアカウントへ通知する方法を記載します。
※この記事では、Amazon Connectの通話開始時にSalesforceのケースが作成されることを前提とします。
システム構成図
- 禁止ワード発火検知
- EventBridgeからLambda呼び出し
- LambdaよりSalesforce Platform Event発火
- Platform Eventトリガーが呼び出され、カスタム通知送信
- カスタム通知表示
- カスタム通知をクリックすることで対象のケースレコードにアクセスできる
実際の通知
Salesforce右上を確認することで禁止ワード通知を確認することができる。
通知をクリックすることで、対象のケースレコードにアクセスすることができる。
設定方法 Salesforce
プラットフォームイベントの作成
- 表示ラベル : 任意の表示ラベル
- 表示ラベル(複数形) : 任意の表示ラベル
- オブジェクト名 : 任意のオブジェクト名(例 : CustomNotificationPlatformEvent)
- カスタム項目
- コンタクトID
- API参照名 : ContactID__c
- データ型 : テキスト
- コンタクトID
カスタム通知の作成
- カスタム通知名 : 任意の名前
- API参照名 : 任意のAPI参照名(例 : NGWordNotification)
- サポートされるチャネル : デスクトップ
フローの作成
- フロー種別 : プラットフォームイベントトリガーフロー
- プラットフォームイベントを選択 : 作成したプラットフォームイベントを選択
- ブロック
- レコードを取得
- このオブジェクトのレコードを取得 :
ケース
- ケースレコードの絞り込み
- 条件の要件 :
すべての条件に一致(AND)
- 項目 :
amazonconnect__AC_Contact_Id__c
- 演算子 :
次の文字列と一致する
- 値 :
{!$Record.ContactID__c}
- 条件の要件 :
- このオブジェクトのレコードを取得 :
- レコードを取得
- このオブジェクトのレコードを取得 :
カスタム通知種別
- ケースレコードの絞り込み
- 条件の要件 :
すべての条件に一致(AND)
- 項目 :
DeveloperName
- 演算子 :
次の文字列と一致する
- 値 : 作成したカスタム通知のAPI名
- 条件の要件 :
- このオブジェクトのレコードを取得 :
- 割り当て
- 変数 :
{!MentionMembers}
- 演算子 :
追加
- 値 : 通知を送信したSalesforceユーザーのSalesforceID
- 変数 :
- カスタム通知を送信
- カスタム通知種別ID : 取得したカスタム通知種別のID
- 受信者ID :
{!MentionMembers}
- 通知タイトル :
禁止ワードが検出されました
- 通知本文 :
禁止ワードが検出されました。エージェントのサポートをお願いいたします。
- 対象ID : 取得したケースのID
- レコードを取得
設定方法 AWS
Lambda作成
1. 設定値
- 関数名 : 任意の名前
- ランタイム :
Node.js 22.x
- アーキテクチャ :
x86_64
2. 環境変数
- CUSTOM_NOTIFICATION_TYPE_API_NAME : Salesforce カスタム通知のAPI名
- SALESFORCE_PLATFORM_EVENT_API_NAME : Salesforce プラットフォームイベントのAPI名
- SALESFORCE_API_VERSION :
63.0
- SECRET_NAME : Salesforceの認証情報を保存しているSecrets Managet名
- SALESFORCE_LOGIN_URL : 使用するSalesforceのログインURL
3. コード
import axios from 'axios';
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
export const handler = async (event) => {
const contactArn = event.detail.contactArn;
const parts = contactArn.split('/');
const contactId = parts[parts.length - 1];
const secretsManagerClient = new SecretsManagerClient({ region: 'ap-northeast-1' });
// 環境変数の取得
const loginUrl = process.env.SALESFORCE_LOGIN_URL;
const apiVersion = process.env.SALESFORCE_API_VERSION;
const customNotificationTypeApiName = process.env.CUSTOM_NOTIFICATION_TYPE_API_NAME;
const platformEventName = process.env.SALESFORCE_PLATFORM_EVENT_API_NAME;
const secretName = process.env.SECRET_NAME;
try {
// Secret Managerから認証情報を取得
const secretData = await getSecret(secretsManagerClient, secretName);
const secrets = JSON.parse(secretData.SecretString);
const consumerKey = secrets.SALESFORCE_CONSUMER_KEY;
const secretKey = secrets.SALESFORCE_SECRET_KEY;
if (!consumerKey || !secretKey || !loginUrl || !apiVersion || !customNotificationTypeApiName || !platformEventName) {
console.error('必要な環境変数が設定されていません (Secret Managerまたは環境変数)。');
return {
statusCode: 400,
body: JSON.stringify({ message: '必要な環境変数が設定されていません (Secret Managerまたは環境変数)。' }),
};
}
// 認証エンドポイントの構築
const tokenUrl = `${loginUrl}/services/oauth2/token`;
// 認証リクエストのデータ
const tokenData = {
grant_type: 'client_credentials',
client_id: consumerKey,
client_secret: secretKey,
};
// 認証リクエストの送信
const tokenResponse = await axios.post(tokenUrl, tokenData, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const accessToken = tokenResponse.data.access_token;
const instanceUrl = tokenResponse.data.instance_url;
const notificationUrl = `${instanceUrl}/services/data/v${apiVersion}/sobjects/${platformEventName}/`;
const notificationResponse = await axios.post(notificationUrl, {'ContactID__c': contactId},{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
return {
statusCode: 200,
body: JSON.stringify({ message: 'プラットフォームイベントを送信しました。', response: notificationResponse.data }),
};
} catch (error) {
console.error('エラー発生:', error);
return {
statusCode: 500,
body: JSON.stringify({ message: 'プラットフォームイベントの送信に失敗しました。', error: error.message }),
};
}
async function getSecret(secretsManagerClient, secretName) {
const command = new GetSecretValueCommand({
SecretId: secretName,
});
try {
const response = await secretsManagerClient.send(command);
return response;
} catch (error) {
console.error("エラー発生:", error);
throw error;
}
}
};
EventBridge作成
EventBridge > ルール > ルールを作成
1. ルールの詳細を定義
- 名前 : 任意の名前
- イベントバス :
default
- ルールタイプ :
イベントパターンを持つルール
2. イベントパターンを構築
- イベントソース :
AWS イベントまたは EventBridge パートナーイベント
- イベントパターン :
パターンフォームを使用する
- イベントソース :
AWSのサービス
- AWSのサービス :
Amazon Connect
- イベントタイプ :
Contact Lens Realtime Rules Matched
- イベントタイプの仕様 : 任意のアクションタイプ
- イベントソース :
3. ターゲットを選択
- ターゲットタイプ :
AWSのサービス
- ターゲットを選択 :
Lambda関数
- ターゲットの場所 :
このアカウントのターゲット
- ターゲット名 : 作成したLambda関数名
- 許可 :
実行ロールを使用
- ターゲットの場所 :
Amazon Connectルール作成
Amazon Connect > 分析と最適化 > ルール > ルールを作成 > 会話分析
1. 条件を定義
- いつ :
Contact Lens リアルタイム通話分析が可能
- 仮定 :
すべて
- 単語またはフレーズ - 完全一致 : 禁止ワードとしたい単語を入力(例として「NG」と発話した際に発火するようにしています)
2. アクションを定義
- コンタクトカテゴリの割り当て : 任意のカテゴリ名
- EventBeidgeイベントの生成 : 作成したEventBridge名
おわりに
今回通知対象をSalesforceIDで設定していますが、Salesforceの環境設定次第で動的に通知相手を決定することも可能です。
例えば、Salesforceで設定しているマネージャーに通知を飛ばしたり、ロールの設定より動的に通知相手を設定することも可能です。