Amazon ConnectとLambdaで電話問い合わせの転送先を動的に変更する

はじめに
こんにちはyuuchanです。
現在業務を行っているPJに参画して1年以上が経ちました。
最初はNW担当チームのひとりとして設計や構築等を行っていましたが、最近では運用保守に関連する様々なタスクを担当しています。
今回は、Amazon Connectを用いての顧客からの電話問い合わせに応答する仕組みを変更・修正した経験から、日時等の条件によって問い合わせ電話の転送先を切り替える方法について紹介したいと思います。
本記事について
・Amazon Connectの「オペレーション時間の確認」機能を使用しても同様の事ができますが、PJの都合でLambdaを用いて実装したためそちらの手法を紹介します。
・問い合わせ電話を転送するところまで触れ、転送後の顧客体験については触れません。
・あくまでも問い合わせ電話の転送先を日時等によって切り替えることを目的とし、フローブロックの詳細な機能についての紹介等は行いません。
最終的にやりたいこと

顧客からの問い合わせ電話について、曜日や時間帯、他特別な条件をもとにその転送先を切り替えるような仕組みをAmazon ConnectおよびLambdaを用いて実現することを目的とします。
Amazon Connectのコンタクトフローについて
顧客からAmazon Connectに対して電話があった場合、通話が終了して切断されるまで基本的には以下のような流れを辿ります。

※AWS Black Belt Online Seminarの資料を参考にしています。詳細については、そちらを参照ください。

コンタクトフローにはいくつか種類があり、上図のそれぞれのタイミングで対応したフローが動作するような仕組みになっています。
今回は、電話を転送するところまでを目的としているため、上図の内「アナウンス」「キューへ転送」に対応した「コンタクトフロー(インバウンド)」に着目します。
※本記事ではいくつかの種類のフローをまとめて指す場合「コンタクトフロー」と記述し、「アナウンス」「キューへ転送」に対応するコンタクトフローを「コンタクトフロー(インバウンド)」と記述します。

ここで一旦、Amazon Connectの管理画面において、コンタクトフローをどのように確認できるかを見ておきたいと思います。
Amazon Connectの管理画面にアクセスし、「チャネル」->「電話番号」を見てみます。
以下のように、取得済みの電話番号の情報を見ることができます。

「コンタクトフロー/IVR」の列を見ると「Call Inbound Flow」と記載されています。
これは、この電話番号に着信があった場合「Call Inbound Flow」というフローが呼ばれることを表しており、それが今回着目する「コンタクトフロー(インバウンド)」に相当します。
では、フローを見ていきたいと思います。
同じく管理画面で「ルーティング」->「フロー」を選択すると、作成したフローや各デフォルトフロー、サンプルフローの一覧を見ることができます。

一覧を見ると、先程電話番号を確認した際に「コンタクトフロー/IVR」の列に記載されていた「Call Inbound Flow」は一番上にありました。
タイプが「コンタクトフロー」となっているフローのみ、電話番号と直接関連付けることができ、「コンタクトフロー(インバウンド)」として扱うことができます。
コンタクトフローの作成
前節では、「コンタクトフロー(インバウンド)」である「Call Inbound Flow」は既に作成済みで実際に電話番号と関連付いていましたが、本節では新しい「コンタクトフロー(インバウンド)」を作成したいと思います。
前節で説明した「ルーティング」->「フロー」の画面から「フローを作成」を選択し、以下のような「コンタクトフロー(インバウンド)」を作成しました。
※簡略化のため、エラー処理やリトライ処理等を省いています。

顧客から問い合わせ電話があると、上図の「エントリ」から「切断」までの各フローブロックの処理を辿ることになります。
本記事でポイントになるのは「AWS Lambda関数を呼び出す」「コンタクト属性の設定」「電話番号への転送」の3つのフローブロックです。
AWS Lambda関数を呼び出す
フローブロックの名称通りですが、Lambda関数を呼び出すことができます。
本記事では、以下のように後述する「転送先電話番号選択Lambda」を呼び出すように設定します。

事前にAWS管理コンソールのAmazon Connectの画面にて、Amazon Connect管理画面側で使用するLambda関数を設定しておく必要がありますが、上記のように一覧から選択してこのフローブロックで呼び出すLambda関数を指定します。
作成するLambda関数はJSONを返却する仕様であるため、「レスポンスの検証」項目でJSONを指定しておきます。
コンタクト属性の設定
Amazon Connectではひとつの問い合わせは「コンタクト」として扱われますが、「コンタクト」内のフローブロック間で共有できるデータを入れておく箱のようなものがあります。
そのデータはコンタクト属性としてアクセスできます。
本記事では、Lambda関数からアウトプットされた電話番号を「コンタクト属性の設定」フローブロックで格納し、後述の「電話番号への転送」フローブロックで取り出して電話を転送する、のような使い方をします。
「コンタクト属性の設定」フローブロックには、ユーザー定義したphone
というキーの値に、「AWS Lambda関数を呼び出す」フローブロックから渡されたphone
というキーの値を設定するため、以下のような設定を行います。

電話番号への転送
こちらもフローブロックの名称通り、指定した電話番号へ顧客からの電話を転送することができます。
「コンタクト属性の設定」でphone
キーに転送先電話番号が格納されているため、「電話番号への転送」フローブロックでは、そのキーにアクセスすることにより転送先電話番号を取得します。
フローブロックの設定は以下のとおりです。

転送先電話番号選択Lambdaの実装および上記のコンタクトフローの作成後、Amazon Connectで取得した電話番号にコンタクトフローを関連付ければ作業完了です。
実際に様々な曜日や時間帯に電話してみると、転送先電話番号選択Lambdaで記述したとおり、AさんBさんにそれぞれ電話が転送されるかと思います。
転送先電話番号選択Lambda
前節の「AWS Lambda関数を呼び出す」フローブロックでは、以下のようなLambda関数を呼び出します。
曜日、時刻、他特別な日であるかどうかをもとに営業時間内外を判定し、時間内の場合はAさん、時間外の場合はBさんの電話番号を返却しています。
import random
import datetime
from zoneinfo import ZoneInfo
def lambda_handler(event, context):
# 2025年度 特別に営業日扱いになる日
HOLIDAY_OPEN_DAYS = [
datetime.date(2025, 6, 1),
datetime.date(2025, 7, 6),
# 他多数の月日
]
# 2025年度 祝日
PUBLIC_HOLIDAY = [
datetime.date(2025, 4, 29),
datetime.date(2025, 5, 3),
datetime.date(2025, 5, 4),
datetime.date(2025, 5, 5),
datetime.date(2025, 5, 6),
datetime.date(2025, 7, 21),
# 他多数の月日
]
# 電話転送先
INSIDE_BUSINESS_HOURS_OPERATORS = [
{"phone": "+81XXXXXXXXXX"}, # Aさんの電話番号
]
OUTSIDE_BUSINESS_HOURS_OPERATORS = [
{"phone": "+81YYYYYYYYYY"}, # Bさんの電話番号
]
# 現在日時(JST)の取得
now = datetime.datetime.now(ZoneInfo("Asia/Tokyo"))
date = now.date()
time = now.time()
weekday = now.weekday()
# 定時時間内外判定
if date in HOLIDAY_OPEN_DAYS: # 特別に営業日扱いになる日
if (time < datetime.time(9, 0)) or (datetime.time(13, 00) <= time):
insideBusinessHours = False
else:
insideBusinessHours = True
elif date in PUBLIC_HOLIDAY: # 祝日判定
insideBusinessHours = False
elif weekday in [5, 6]: # 土日判定
insideBusinessHours = False
elif weekday in [0, 1, 2, 3, 4]: # 平日判定
if (time < datetime.time(9, 00)) or (datetime.time(18, 00) <= time):
insideBusinessHours = False
else:
insideBusinessHours = True
else:
insideBusinessHours = False
# 転送先選択
if insideBusinessHours:
return random.choice(INSIDE_BUSINESS_HOURS_OPERATORS)
else:
return random.choice(OUTSIDE_BUSINESS_HOURS_OPERATORS)
おわりに
いかがでしたでしょうか。
Amazon Connectは、個人的な学習ではしっかり触れる機会が中々得にくいサービスのひとつかと思いますが、業務で触れる機会を得ることができまたひとつAWSの知見が増えたと感じました。
今回紹介した「コンタクトフロー(インバウンド)」は、あくまでも小規模なヘルプデスク向けの作りであり、大規模なコールセンターを構築する上では、本記事では触れていない他の種別の「コンタクトフロー」や「フローブロック」を柔軟に組み合わせ、顧客体験を向上させていく必要があります。
今後PJでそのような機会があった際には、本記事の続編としてぜひ紹介できればと思います。