TaskRouterとConferenceの組み合わせる

こんにちは、@24guchiaです。

以前の記事で、日本国内でTaskRouterを使う場合、
Conferenceを使いましょうとの結論を付け、
実際に
運用をはじめたので、TaskRouterとConferenceを組み合わせる方法について書きます。

この記事を読むとTaskRouterを使わない場合でも、Conferenceを使って、
通話のモニタリング機能を拡張できるようにしておくか、
それとも通常のDialで済ませるかの判断基準になると思います。

日本国内でTaskRouterを使う場合、Conferenceを使う理由って?

端的に言うと、TaskRouterで割り振った受電の通話音声が
必ず遅れやすい環境での通話を強いられます。
詳細は過去記事を参照してください。
http://harinoma.info/?p=73

TaskRouterのみの影響ということは受電だけ直せばよいか?

これはケースバイケースですが、基本的には架電もConferenceに置き換えたほうが良いです。
理由はConferenceとDialが混合するため、コードが読みづらくなり、
拡張性や保守性が下がります。
また、保留を提供している場合、受電と架電で処理を分ける必要があります。
日本国内でTaskRouterを使う場合、
Conferenceでの受電架電の機能提供は
セットで必須になると思います。

TaskRouterは使いたいけど、Conferenceは使いたくない場合は?

下記選択肢から選んでください。

  1. 受電は通話が遅れるものとして受け入れる

  2. 一旦受けて、必ず即時折り返す

  3. TaskRouterの日本サーバができるのを待つ

3以外はあんまり現実的な選択肢はないですね。ただ、3はいつになるか不明です。今日時点(2018年5月27日)では、諦めてConferenceを使いましょう。

そもそもConferenceとは

250人まで同時通話できる機能です。Dialは1対1の通話に対し、250人まで同時に話せますグループ通話機能を作ったりするのが一般的なユースケースです。

AgentConferenceとは

Conferenceの拡張機能です。Conferenceとの決定的な違いは、
coachプロパティにより、
話した音声を特定の相手に届けられる点です。

この機能は何に使うかというと、新人営業と顧客の通話を先輩営業が聞きながら、話し相手には聞かれずに、先輩が新人に口頭で直接指示を出すといった場合に使います。
リアルタイムで指示が出せ、さらにソフトフォンを使えるため、
場所を問わず、コーチングが出来ます。
声が荒ぶっても、話し相手には音声が聞こえないので、
近くの新人をコーチングする場合でも、この機能を使うと安全です。

一般的なビジネスフォンでもウィスパリングやら、
モニタリングやら
といった名称で提供されていることもあります。

Conferenceのハマりどころ

概念が違う

先にも書いた通り、Dialは1対1の通話に対し、Conferenceは1人以上250人までの通話という点が違います。
二人以上ではなく、1人以上のため、
普通の通話では考えなくても良いことを考える必要があります。

誰かが通話を終了した時、Conferenceを終了させるかどうか考える必要がある

Conferenceは1人以上でも、通話が可能です
そのため、二人で話していて、相手が電話を切っても、
残された方は自動で電話が切れません。

例えば、endConferenceOnExitというプロパティがあり、
このプロパティをtrueにすることで、
このプロパティがtrueの人が通話を終了したら、
自動でConferenceを終わらせる機能があります。

じゃあ、これを一律でtrueにすればよいかというと、基本的にはダメです。
その理由は保留があるからです。
保留する場合、その人はConference上の通話を終了するため、
このプロパティがtrueだとConferenceが終了してしまいます。

一律ではなく、顧客の通話のみ、このプロパティをtrueにします。
また、このプロパティがfalseの側が通話を終了した場合、
API経由で必ずConferenceを終了させましょう。
終了させないと、通話相手は自動で電話が切れないので、
気付かずずっと通話状態になっているとクレームにつながります。

Twilio ClientでConferenceSidが取れない

ConferenceSidは通話を終了させたり、
参加者に対して更新処理をかけるのに必要な情報です。

先に挙げたように、必ずAPI経由でConferenceを終了させる必要がありますが、ClientにはなぜかConferenceSidを受け渡されません。
じゃあ、CallSidから参照しようという手も無理です。
CallSidからConferenceに関する情報は取れません。

解決方法としては、架電と受電で異なる方法を用いました。

架電の場合

ConferenceにStatusCallbackイベントが設定できるので、
イベント時にSyncでClientに通知しました。

かなりトリッキーな方法で一刻も早く別の方法で直したいのですが、
現時点ではこういう方法以外は見つけられませんでした。

受電の場合

TaskRouterを使う場合、TaskSidがConferenceのFriendlyNameに設定されるため、
Taskを受領する際、FriendlyNameで検索することで
ConferenceSidが取得できます。
TaskSidはTwilioが付与する一意なIDなので、1件のみ取れます。

一個余計なAPIを投げる必要があり、余計なコストだと考えています。
まあ、架電に比べたらかなりマシです。

この解決方法の問題点

Syncにしても、API経由にしても、時差があります。
Webページなら気にならない誤差ですが、電話ではけっこう致命的な時差です。

一番の問題として、ConferenceSid取得前に電話を切ろうとすると
Conferenceを終了させるAPIに失敗します。
そのため、この方法で解決する場合、ConferenceSidが取得できているか、
できていない場合、再度時間を置いてAPIを呼び出すよう待つ必要があります。

架電時、架電先がビジー応答返却すると、Conferenceが重複した

なんだそれ、という感じですが架電時の処理を下記の通りに組むと重複します。

  1. Twilioの番号と架電先の番号の通話をConferenceに参加させるAPIを実行する

  2. 1で作られたConferenceにdialするTwimlを返却する

これは普通に待受状態の電話機に通話する場合は問題ありません。
問題が発生するのは、ビジー応答を返却する電話機の場合のみです。
ちなみにビジー応答は、通話中かつ留守電設定がない電話機の場合、
ビジー応答が返却されるようです(観測範囲内)。

なぜ重複するかというと、1でConferenceに入る前に、
ビジー応答が返却され、通話中の参加者がConferenceからいなくなり
1のAPIで作成されたConferenceが即時終了します。
そして、2ではすでに終了したConferenceに架電しようとしますが、
存在していないため、同名の別のConferenceが作成され、そこに1人で参加します。

これにはけっこうハマりました。
Conferenceは1人以上で成立するという仕様のため、
電話を切る必要があるが、上でも挙げている通り、
ConfereceSidがClientに渡されない。
さらに重複したConferenceにはStatusCalllbackのイベントを設定できず、ConfereceSidをSyncで渡すという実装をしていたので、
電話を切るために行った対策がすべて通用しませんでした。

これの対策は1と2の間で少し待ち、
1で生成されたConferenceが生きているか確認したり、
StatusCallbackで対策したりと方法があります。
私は1秒待ち、Conferenceのstatusを確認する方法で対応するつもりです。

StatusCallbackの数が普通の通話より増える

イベントの数が増えます。https://www.twilio.com/docs/voice/twiml/conference#attributes-statusCallbackEvent

サーバへのアクセスが増えるので、注意してください。
うちのサーバはちょいちょい限界を迎えてます。

ConferenceSidが渡されないために、必要以上にStatusCallback設定しています。

まとめ

ちょっとこれは理不尽では?

理不尽だと感じる理由は下記の通り。

  1. TaskRouterはGAなのに、日本国内では通話に遅延が発生しやすいまま放置されている

  2. 1のアナウンスが私のブログにしか情報がない(観測範囲内)

  3. ConferenceSidをClientに受け渡す方法がなく、かなりトリッキーな実装を強いられる

これからTaskRouterを受電で使う場合はよく考えて採用してください。TaskRouterと同様の仕組みは時間かかりますが、作れると思います。
受電はTaskRouterを使うとTwilioで完結し、良いと思うのですが、
いかんせん日本国内での使用には問題が多いです。

AgentConferenceも実装しづらいなぁという感じなので、
急いで導入する必要はあまりないかもしれません。
下記記事によると、通常のコールからシームレスにConferenceに変更できる機能が実装予定らしいので、モニタリング・ウィスパリングしたい場合でも、
それまで待ったほうが無難かと思います。
https://www.twilio.com/blog/2017/12/agent-conference-generally-available.html

モニタリングの下地ができたのはよしとよう

1ヶ月の実装とテスト2週間ほど(バグがめっちゃ出た)かけ、
とりあえずConferenceが導入できました。

モニタリング・ウィスパリングは元から要望が合ったのですが、
どうにもリリースに間に合わず、置いておいた要望です。
ウィスパリングのアドバイス機能はバグが発生すると、
即クレームに繋がるので、まずはモニタリングで聞くだけの機能を提供し、
その後、ウィスパリングを導入する予定です。
また、リアルタイムでの通話一覧機能を実装し、
どの通話を聞くか、アドバイスするかを選択できるようにする予定です。

これらの機能が実装でき次第、
記事を上げていく予定ですので
それまで乞うご期待。

Twilioでのテレフォニーリニューアルについて

こんにちは、@24guchiaです。

弊社では内製していた顧客管理システムの全面刷新を年始に行いました。
私はその中でもTwilioを用いたテレフォニーに関するリニューアルを担当しました。

リニューアルにあたりTwilioをなぜ採用したのかや、
どういう技術構成を組んだか、
リニューアルから3ヶ月経ち、成功と失敗、
これからの未来について考えをまとめていきます。

リニューアルに関して

そもそもなぜリニューアルに踏み切ったか

  • データ最適化を進め、機械学習の導入などエンジニアの進化速度の向上
  • エンジニアリング組織として、強くしていく
  • レガシーシステムで改修に時間がかかり、改善のスピードを上げることが出来ない
  • データが見えづらいため、勘に頼った判断が増えていた
  • 顧客管理システムのUIUXが悪く、実際に使う営業からのハレーション

他にもいろいろありますが、大きな理由はこの辺ですね。

これ書いてる人は何やったの

先にも書きましたが、Twilioを使用し、
社内の電話システム改修とCRMつなぎ込みを行いました。

インハウスのコンタクトセンターを1人で作りました(ドヤ)

・・・

すいません、実装は1人でやりましたが色んな人の協力あってです。
わざわざこれ書くのも、協力してくれた人への自分なりの感謝の表れです。

Twilioを用いたコンタクトセンターのリニューアルに関して、
知りたい方は読み進めていってください。

なんでTwilioを採用したの

電話機にとらわれない、コミュニケーション手段として利用できる

電話機を使う必要がなくなります。
PCとインターネット回線さえあれば、どこでも働くことができます。
将来的にはWebサイトやアプリからの通話を格安(通信料金のみ負担)で提供もでき、
今まででは考えられないコミュニケーション手段として、使えるためです。

すべての通話ログが残り、検索ができる

ログが残ることで、1人のお客様に対してどれくらいの時間とコストを掛けているか、
放棄呼、到達率といったすべてのログを集めることができます。

ログが残るサービスは多いですが、
それを開かれたAPIで検索できることが強みだと思います。
APIがあるため、必要な情報を集めることができ、
データを基にした判断が可能になります。

架電者・受電者が分かれた形式で録音できる

先の通話ログが残ると似た理由ですが、
話者の音声が左右に分かれることで、営業がどのような内容を話しているか、
音声からテキスト化し、分析するための基盤を作ることが出来ます。

これは他のサービスでは提供されているのは見たことがないです。
メールやメッセージは元々テキストなので、分析しやすいですが、
この特長により音声までも分析の対象にできるため、
よりデータドリブンな判断が可能になります。

オープンなAPIが公開されている

存在しているAPIはすべて下記ドキュメントで公開されています。
https://www.twilio.com/docs/
一部、知ってる人は知っているみたいな隠し情報とかも
あったりしますが、普通に使う分には困らないです。

これは技術選定フェーズではかなり有利で、
他のテレフォニーだとAPIはあるらしいくらいまでしか分からず、
弊社で必要なことがすべて実現できるか不明でした。
その点、Twilioはドキュメントが用意されているので、
要件を洗い出し、このAPIを呼び出すという一覧を作成できたので、
先の特長とあわせて、Twilioで問題ないだろうという判断ができました。

どうやって提供しているの

クライアントはChromeExtensionを採用

社内の顧客管理システムでブラウザをGoogleChromeに限定している、
という前提条件ありきですが、ChromeExtensionを自作し、
社内限定で公開しています。

Extensionにした理由は、顧客管理システムを使う以上、
Chromeは常に開いているだろうという想定と、
別のソフトウェアだと起動し忘れて、
受電できないということを懸念し、
ブラウザ一体型のExtensionにしました。

在席管理はSyncを採用

Twilio.Syncを使用し、Extensionにログインしたら、
在席にし、Syncのdisconnectedイベントで離席、
通話が始まったら通話中と切り替えました。

受電割り振りはTaskRouterを採用

Twilio.TaskRouterを採用し、受電の割り振りをしています。
受電した番号で、顧客管理DBに検索、
担当者が決まっていれば、担当者を優先的に呼び出し、
担当者が離席中であれば、同じチーム、
同じチームも全員離席していれば在席の誰かを呼び出します。

成功と失敗

成功していること

  • ちゃんとログは残る
  • 録音もできている
  • データ分析の基盤作りができた
  • 物理の電話機を一掃できた
  • 見えていなかった問題が見えるようになった

だいたい、採用した時に狙っていた通り、
通話ログが着々と溜まっていき、電話機は減らせました。
また、今まで放棄されていた通話などに気づくことが出来、
転送することで放棄が減っているようです。

失敗したこと

一つの失敗だけで一記事できそうです(涙)。
他にもいろいろありますが、とりあえず5つだけ。

Syncの事前の負荷テスト不足で全然動かない【対応済み】

SyncはAPI制限があります。下記URL参照です。
https://www.twilio.com/docs/sync/limits

200人くらいいる営業を同じマップに配置し、
それが更新をしまくるので、SyncがAPI制限に引っかかり、
まったく在席管理が見れないという不具合が起きました。
現在、修正済みですが、在席管理と電話機を
同じExtension上においていたため、電話が動かないということが
頻発し、かなり迷惑をかけました。

API制限に引っかからない形にし、
また、在席管理をExtensionとは別ページに置くことで対応済み。

StackOverflowに質問して、SyncのPMから
返信いただいているので、参照してください。
https://stackoverflow.com/questions/48207330/twilio-sync-map-frequently-cannot-get-300-over-items

データ分析するための分析基盤が必要【未対応】

Twilioはログが残りますが、通話の考え方がユーザから見たときと異なります。

AliceがBobに電話をかけたというケースは、
一般的な電話利用者から見ると、1つの通話ですが、
Twilioの通話ログは下記の通り2つに分かれます。

  • AliceからTwilioへの通話
  • TwilioからBobへの通話

TaskRouterを使うと通話ログは更に分かれ、
AliceからTwilioへの通話、Twilioから各Workerへの通話が
生成された分だけ通話が分かれます。

どういうことかというと、下記の通りの通話ログが生成されます。

  • AliceからTwilioへの通話
  • TwilioからWorkerAへの呼び出し(タイムアウトするまで取られない)
    • 通話が切られるか、誰かが対応するまで無限にこの通話ログが生成されます
  • TwilioからWorkerXへの呼び出し(対応されて、通話が開始)

TaskRouterで生成された通話ログは通常の管理画面で
追うのはかなり困難なため、データはあるが、分析するための準備が必要な状態です。

現在、未対応。

TaskRouterで受電すると通話が遅れる【対応中】

こちらかなり危険で、日本国内のTwilio開発者では対応手段が限られる、
致命的な問題です。詳しくは以前記事を書いているのでそちら参照。
http://harinoma.info/?p=73

詳細は記事を読んでもらうとして、問題の概要として、
TaskRouterで生成されたタスクを通常の通話で処理すると、
アメリカのサーバを経由した通話になり、通話が遅れる可能性があります。

日本国内での対応方法はDequeueなどは使わずに、
Conferenceで使用し、regionをjp1にすると
国内での通話が実現できます。
ただし、Conference使用量分、料金が増えます。

こちらConferenceに置き換え作業を現在対応中。
対応のめどが付いたら、別記事作ります。

24時間動く電話にエンジニア(僕)の対応が追いつかない【対応済み】

Twilioを扱えるエンジニアが1人(僕)しかおらず、
それに対して利用者は300人程度で想定していないバグや
使用方法の質問、早朝深夜・土日祝関係なく問題を抱えたまま
動き続けるシステムに僕が心身ともに参ってしまいました。
体重が一時的にけっこう落ちました。

対策として、どう対応するのが正解かケースによりますが、
下記のようなことが言えます。

  • 1人でやらない
  • テスト(負荷テストや状態遷移テストなど)を複数の観点から事前にしっかりやる
  • 利用者への周知のコミュニケーションパスを作っておく

今は部長や間接部門の方に周知をしてもらい、一部運用でカバーをしているため、
安定稼働しつつあり、たくさんの人に協力してもらえているので
ほとんど回復しています。

Extensionが思いの外使いにくい【対応中】

Chromeは開いているけど、Excelなど他のソフトウェアを使ったりすることもあるので、
Chrome上にしか表示できないExtensionでは、解決ができないことが多くあります。

  • 自分の在席状態をExtensionのバッジで表示しているが、文字が小さすぎる
  • 通知(Notification)の表示領域不足し、修正もできない
  • 配布方法が独特

まあ、表示系はもっとちゃんとテストしとけよっていう話ですが、
配布方法が一番の困りどころです。

配布は下記順番で行います。

  • Extension更新パッケージを管理画面でアップロード
  • 最大1時間以内に更新パッケージがStore上に公開される
  • 公開されたパッケージを各利用者が手動アップロードか自動アップロード

これの何が問題かというと、クライアントとサーバの両方を修正する時、
サーバの更新は一瞬ですが、クライアントの更新タイミングは不明です。
そのため、サーバ上のみ最新で、クライアントが古いままなどが発生し、
サバクラでバージョン不一致が発生してしまうことがあげられます。

また、最新のクライアントで不具合が発生した場合でも、
すぐにバージョンダウンして再公開などできないため、
同手順を踏み、アップロードする必要があり、
最大1時間程度は電話が使えないということが起こり得ます。

対応として、夜中に1人でアップロードして、翌朝更新するよう依頼する
という方法で現在はしのぎ、できるだけサバクラ同時に修正が必要なことは
実施しないようにしています。

これらの理由につき、Extensionを捨てて、Electronでアプリ化を進めています。
これの作業にはなんと、僕以外の優秀なフリーランスの方が着手してくれています

Electronでは上記問題は解決できそうですが、
また別の問題も起きると思います。
同じ失敗をしないよう事前テストとして、
ExtensionとElectronを併用する期間を設ける予定です。

これからの展望

通話音声に関するデータ基盤を作り、データドリブンな組織、
とかっこよく今どきな言葉を並べていますが、
この3ヶ月は書いた通り、泥臭く地道な修正を続けていました。
また、更に3ヶ月かもっと長い期間、同様な地道な作業が続くと思います。

短期的には影が薄くなりたい

この泥臭い作業が終わったあと、声大きめに
あれやこれやの指示出していた僕はひっそりと仕事をしたいです。
最近あの電話おじさん見ないね?と言われるようになりたい。

これは僕がコミュ障とか人が嫌いとかそういうことではなく、
電話機が持っている機能を安定して提供できている状態で、
利用者がわざわざエンジニアに話す必要がない状態だからです。

世にある安定しているインフラは、インフラを支える技術者が当然いますが、
僕らは普段意識することはあまりないです。

普通に使える。
まずは、そういう状態を目指します。

中期的にはコンタクトセンターとして最適な組織に変えたい

顧客からの問い合わせに最適最速な経路で、担当者に繋がる組織。
放棄呼や待ち時間を圧倒的に少なくしたい。

最適な担当者につなげるというのは、システムだけではできず、
どういった電話がどの時間帯に誰宛にかかってくるのかといった分析と
組織としてどう対応するのかの方針を定める必要があると思ってます。

その部分の分析をした上で、システムに組み込み測定を繰り返す事ができる、
SMARTなコンタクトセンターにしていきたい。
数値として洗い出せば、効率的な働き方の提案につながり、
長時間労働のうち、本当は必要のない勤務時間を減らせるようになると思います。

長期的にはコミュニケーション全般を最適化していきたい

はい、Twilioのミッションですね。
プロダクトとしては、Twilio.Channlesが近いです。
https://twilio.kddi-web.com/blog/developer/entry000316.html

また、TaskRouterは実は通話以外のタスク生成と割り振りが可能です。
そのため、受電を最優先タスクとして割り振りし、
それ以外のチャットツールやメールなどは優先度を少し下げて、
割り振るといった器用なことが出来ます。

この辺、まとめた概念がTwilio.Flexだと思っています。
以前の記事参照。
http://harinoma.info/?p=80

すべてTwilioで完結するべきか微妙なので、
最適な部分に最適な技術で対応していきたいです。

最後に、通話ログがあり、テキスト化ができるため、
テキストマイニングに従った最適な通話シナリオの作成、
リアルタイム文字起こしやリアルタイム感情分析など
技術的におもしろそうなことも待ち構えています。

まとめ

Twilioに携わるようになり、はや一年が経ちました。
最初はホコリまみれのボロい電話機を渡され、
これをなんとかしてくれと言われた時、
弊社でのキャリアが終わったとも思ったものです。

かなり尖ったスキルセットにはなりましたが、
調べても分からないことを解決していくのは
エンジニアとして自信が付きました。
なんでも出来る、でも必要なことだけやるように
これから精進していきます。

Twilio Flexは何がすばらしいのか

こんにちは、@24guchiaです。

つい先日、Enterprise ConnectTwilio Flexというサービスの
ローンチが発表されました。
Flexは何がすばらしいのか、私の考えを記事にします。

CCaaSという概念の提唱

Flex自体はTwilioが今まで持っていた機能の集合体でしかないと、
私は思っています。

しかし、Twilioを知らない人にとっては、何をどこまでできるかが分かりません。コンタクトセンターが持っている機能を全てクラウドに置き換えられますが、
ひとつひとつコンタクトセンターが持っている機能を概念として理解し、
Twilioの持っている機能に落としこむには、それなりの習熟が必要です。

これらひとかたまりの機能をFlexという名前を付けたこと自体で、
人に話すことが出来、理解することができます。
このこと自体が、私はすばらしいと考えています。

Twilioが目指している未来を表している

先に上げているCCaaSはContactCenter as a Serviceの略です。
CallCenterではなく、ContactCenterです。
コールセンターとコンタクトセンター、似ているようですが、異なります。

コールセンターは電話だけをコミュニケーションの手段と考えています。
対して、コンタクトセンターは電話以外も含めた、
すべてのコミュニケーションを対象としています。

この考え方自体はChannelsという機能でも、最初から提示していました。
Twilioが目指しているのは、
コミュニケーションすべてのプラットフォーム化
であると私は考えています。

Twilioが電話だけを対象にずっとサービスを続けるようであれば、
見限られることも考えられますが、
全てのコミュニケーションをプラットフォーム化する
という考え方は他のどのサービスでも体現していません。

この企業哲学こそが、Twilioを使っていきたいと考えられる理由の一つです。

UI の提供

開発者向けの機能の一つとして、
共通で使えるようなUIが提供されることで
開発者はTwilioの機能開発に集中できます。

Twilio開発者は日本国内では少ないため、
やらなくてもいい作業が減り、本来やるべき仕事に集中できることは
非常に大きなメリットです。

すぐにFlexを導入するか

私の考えですが、すぐに導入は難しいと思います。
最初に述べておりますが、FlexはTwilioが持っている機能の集合体です。
そのため、 一つ一つの機能はちゃんと習熟する必要があります。

特にTaskRouterは難易度が高いです。
ACDの考え方を理解し、
導入を考えてる組織のコンタクトセンターの文化を理解し、
TaskRouter自体の機能を理解する必要があります。

また、ドラスティックな変更になるため、
いきなり全ての機能を導入し、コンタクトセンターを一新するというのは、
上司や現場などから、反発を受ける可能性があります。
やれることからひとつずつやって行くのが良いかと思います。
そもそも現時点では、プレビュー版の為いつ導入できるか不明です。

Twilio自体の導入について

Flexが現時点でプレビューのため、
逆に今は少しずつ導入するチャンスであるとも言えます。
Flex、及びTwilioが目指す哲学に同意できるのであれば、
今のうちから準備を進めて導入を進めるのはどうでしょうか。

まとめ

以前、弊社にAPACのマネージャーが訪問してきたことあります。
その際質問された、コミュニケーションの未来はどうなると思いますか?
という質問が記憶に残っています。

その時の私は、開発者としての視点しか持っておらず、
明確な答えが出すことが出来ませんでした。
この質問を受けた時から、
コミュニケーションの未来について考えるようにしています。
あとで私も同じ質問を返すべきだと公開しました。

しかし、その質問はする必要がなかったです。
Flex自体がTwilioの考えるコミュニケーションの未来で、
先の質問に対する答えだと思うからです。

TaskRouterを日本国内で使う場合の注意点

こんにちは、@24guchiaです。

日本国内でTaskRouterを受電で使う場合、通話音声が遅れる可能性があります。今まで、TaskRouterを使いましょうみたいなことを書いていたので、
その反省と皆様への注意を兼ねて記事にします。

原因

受電が遅れるということですが、原因はTaskRouter自体の仕組みにあります。TaskRouterはTask割り振りをして、米国サーバーでキューが作成されます。
そのままdequeueをすると、
米国サーバーで作成されたキューを介して通話が始まります。
そのため、日本国内のピア同士の通話であっても
米国サーバーを経由することになるため、
音声の遅れが発生します。

対応方法

dequeueを使うのではなくConferenceを使いましょう
Conferenceの作成方法はドキュメント見てもらおうとして、
Conference作成時、リージョンの指定ができます。
このリージョンをjp1に設定することによって、日本国内での通話が実現できます。

まとめ

1月にリニューアルしてから、通話が遅れることがあるとよく言われていました。
アルファー版で発生していなかったので、なんでだろうと悩んでいましたが、
原因がわかればなんということはないです(遠い目)。

現在、 通常のCallからConferenceに置き換える作業しています。
これはなかなかに骨が折れますので、
これから日本国内で導入を考えているTwilioデベロッパーの皆様、
予めConferenceでの実装をお勧めします。

Conferenceへの置き換え苦労話は今度、まとめます。
とりあえず言えることは、単純な置換では絶対に動かないし、
1対1が前提の通話に対し、複数人が通話する前提のConferenceでは
そもそも考え方が異なります。
この辺はかなり苦労しています。

Twilioのアカウント周りで失敗したのを懺悔

あけましたおめでとうございます、@24guchiaです。

年始から縁起悪い記事ですが、今日失敗したことまとめます。

ほうほうの人に質問してしまっていて、申し訳ない気持ちでこの記事書きました。

この記事を読むと分かること

Twilio.Clientを用いて、何故か架電ができず、

下記ログが出力される時の原因と解決方法が分かる

[Connection] Received HANGUP from gateway

書いた理由

  • ググっても出てこなかった
  • 同じミスを自分がしないようにメモ
  • 後から始めたTwilio開発者が同じミスでハマらないようにしたい

今日の僕のハマってた時間と、ほうほうの人に質問で時間取らせた分、

他の人がこの記事ですぐ解決できれば開発者全体でプラスにしたいため。

事象

なぜか架電できない

同じ実行環境で架電すると、なぜか架電ができる番号とできない番号がある。

※実行環境は原因に関係ないので、特にあげません。

正確には架電すると架電の呼び出し音は一瞬鳴るが、

架電先の電話機が鳴動する前に架電が終了する。

切り分けてみた

  • 架電先の電話機固有の問題

携帯電話にかけても、固定電話にかけても架電ができなかったので、

架電先電話機は関係ない。

  • 実行環境の問題

同じ環境で別の番号を用いた場合、架電が出来たので実行環境は関係ない。

  • ネットワークの問題

無線LANと有線LANを切り替えても、かからなかったのでネットワークは関係ない。

  • ソースコードの問題

プロダクション版とアルファ版で同じ番号でかけたところ、

アルファ版ではかかるのでソースコードに問題ありそう。

コンソールのログ読んだ

ICEコネクション周りは正常に終了していた。

※ICEってなんだ?って人はこの記事参照してください

架電先に届く前に先に上げたログが出力されていた。

[Connection] Received HANGUP from gateway

 

このログはIP網とPSTNをつなぐゲートウェイから、

電話切られたっていう信号を受信したというログです。

なので、通常に通話し、相手側に切電ボタン押されたり、

受話器を置いた時に送られる信号です。

ゲートウェイについて参考:https://www.3cx.jp/voip-sip/voip-gateway/

考えた

相手先に届く前にゲートウェイから、通話終了の信号が来るのは

ネットワークとかに問題があると思ったがぜんぜん違っていた。

原因

Twilioにはマスターアカウントとサブアカウントがあって、

画面に表示している電話番号と生成する認証トークンが不一致だったのが原因。

マスターアカウントの認証トークンを基に生成されたDeviceで、

サブアカウントの番号を使用して架電しようとしていたので、

架電ができませんでした。

ハマった理由

ICEは正常終了しているのに関わらず、

即時でゲートウェイからハングアップの信号受信したログが出たから。

IPとPSTNの間にあるゲートウェイ周りの情報も

逆に存在を知らなければ、変にハマらなかったかもしれない。

まとめ

認証トークンはドキュメント通りに作れば、正常に返ってきます。

電話番号はTwilioで買えば、買ったアカウントに紐付きます。

認証トークンと電話番号、本当に紐付いているか再度確認しましょう。

プロダクションで使うTaskrouter構成について

この記事を読むと分かること

  • プロダクションで使うTaskrouterガチ構成が見れる
  • WorkflowのルーティングのJSONファイルを公開するので、ドキュメントとは違うユースケースのルーティングを見れる

こんにちは、@24guchiaです。

Twilio Advent Calendar 2017 の13日目です。

Taskrouterと1ヶ月ほど格闘し、得られた情報を社外秘のみ取り除いて、全部公開します。

Twilioドキュメント以外で、Taskrouterの記事が少なくいろいろと苦戦したので、

今後Taskrouter使う人の参考になれば良いなーと思います。

弊社の受電の仕様

受電の仕様は下記です。

  • 受電した番号でDB検索し、担当者が存在するか確認する
  • 担当者が存在する場合、担当者の電話機を鳴らす
  • 担当者が電話を取らないか不在の場合、担当者と同じ部署の人の電話機をランダムで鳴らす
  • 誰も受電出来ない場合、機械音声で担当できるものがいない旨を通知

企業側としては受電担当部門が不要になり、

お客様としては余計な取次による待ち時間が減らせることができます。

CTIの効果を感じられる仕組みだと思います。

Taskrouterに落とし込むとどうなるか

Workerの設定

Workerは電話機を使う人、一人に対して1Workerを必ず発行します。

独自で持たせている属性はメールアドレスと部署IDだけです。

FriendlyNameはemailからピリオドをアンダースコアにしただけのものを使用しています。

例:

{"email":"hiroshi.abe@example.com,"contact_uri":"client:hiroshi_abe","department_id":1}

Activityの設定

デフォルトで生成されるものをそのまま使っています。

Taskqueueの設定

TARGET WORKER EXPRESSIONに1==1を入れているだけの

キューをひとつだけ使用しています。Workflowだけでなんとかしています。

Workflowの設定

設定しているJSONファイルは下記。

これだけだと、何も出来ないので好きに使ってください。

{
  "task_routing": {
    "filters": [
      {
        "targets": [
          {
            "queue": "WQxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "expression": "task.email==worker.email",
            "priority": "1",
            "timeout": "10"
          },
          {
            "queue": "WQxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "expression": "task.department_id==worker.department_id",
            "priority": "2"
          }
        ],
        "filter_friendly_name": "email",
        "expression": "filter=='email'"
      },
      {
        "targets": [
          {
            "queue": "WQxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "expression": "worker.department_id IN task.department_id",
            "priority": "3"
          }
        ],
        "filter_friendly_name": "department_id",
        "expression": "filter=='department_id'"
      }
    ],
    "default_filter": {
      "queue": "WQxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
  }
}

WorkflowのJSONの解説

パッと見、filterって何してるんだろうと感じると思います。

これを説明するためにまず、Taskqueueの仕様について理解が必要です。

Taskqueueの仕様

Taskqueueはキュー内に存在する、WorkerのAvailabilityはチェックしません。

そのため、割り振りしたけど、そのWorkerが離席してて受電できなかったというようなことが発生しました。

こうやって回避した

離席している人の電話機を鳴らすということを回避するために、

Task発行前に担当するWorkerのAvailabilityをチェックするように変更しました。

Availabilityがtrueの場合、taskにキーがfilter、値がemailの属性を設定します。

falseの場合、taskにキーがfilter、値がdepartment_idの属性を設定します。

この属性はfilter_friendly_nameがemaildepartment_idの下にあるexpressionで評価される際に使用します。

filterがemailの場合

targetsの中に2つのキューだけあります。

taskにemailの属性が設定されてあり、担当者のメールアドレスが情報として持たせてあります。

この属性を設定することにより、Taskqueueの中からWorkerのemailの属性が合致するものが選択されるため、

まず担当者の電話機が直通で鳴るようになります。

timeoutを10秒にしてあり、在席しているが取ることができなかった場合でも、

自動で次のQueueにエスカレートされ、次の判定であるdepartment_idが一致するWorkerの電話機を鳴らすようにしてあります。

担当者に直通で電話機を鳴らす場合の具体例:{"person_name":"Alice","email":"hiroshi.abe@example.com","department_id":1,"filter":"email"}

filterがdepartment_idの場合

targetsの中に1つだけキューがあります。

先の例と同様ですが、email情報は持っていません。

そのため、Taskqueueの中からWorkerのdepartmnet_idの属性が合致するWorkerが選択され、

担当者と同じ部署の誰かの電話機が鳴らすようにしています。

こちらはtimeoutを設定していないため、電話を切られるまでか、

同じ部署内の誰かが電話を取るまで鳴り続けます。

担当者と同じ事業部の誰かの電話機を鳴らす具体例:{"person_name":"Bob","department_id":1,"filter":"department_id"}

回避した結果

この仕組で不在の担当者に一度着信させて、お客様を待たせるということをなくすことができました。

まとめ

Twilioを利用するメリットはいくつもありますが、

受電から担当者への取次時間を減らせるということは

Twilioを導入する企業、架電するお客様の双方に大きなメリットがあります。

  • 直通で担当者につながることにより
    • お客様への安心感の提供
    • 取次が減らせるため、オペレーターが電話業務に取り掛かる時間が減る
    • 通話時間が減るので金銭的に通話料を節約できる

このようなメリットを感じられたら、ぜひTaskrouterの導入をおすすめします。

受電の難しさとどう解決したかについて

この記事の主張

  • Twilioを用いたWebCTI構築で一番難しいのは受電である
  • 保留も難しいと言われるが、保留の実装はドキュメントだけで解決する
  • 手を動かす前に、仕様洗い出しと実装のイメージ作りをしましょう

 

こんにちは、@24guchiaです。

Twilio Advent Calendar 2017 の9日目です。

弊社では営業管理ツールリニューアルに伴い、

電話システムも某IP電話会社から、Twilioへの置き換えを行い、新たにCTIの仕組みを導入しています。

導入にあたり、仕様の洗い出しや提案、実装から各社間の調整まで仕事させてもらっています。

僕はTwilioに触る前まで、IP電話のサービスを使ってなかったし、Twilioは名前も知りませんでした。

1年ほどで得た経験を基に受電の難しさをまとめますので、参考にしてください。

この記事に書いてある内容はTwilioに詳しい人に質問できる環境にありながらも、

基本的には1人で得た知識と経験のため、これがベストプラクティスではないです。

むしろそんなのあったら教えて欲しい。

なぜ受電が難しいのか

IP電話やTwilioについて詳しくない人が、

そもそもネットワークを用いた電話の仕組みを理解できていないからです。

携帯電話はほとんどの人が持っていますが、仕組みが異なります。

電話番号1つに対して、通話を発信・着信できる端末が複数ある

普通の電話は番号1つに対して、発信・着信できる端末は1つだけです。

ですが、Twilioでは1つの電話番号で、複数人が同時に発信・着信できます。

一般的に思い込んでいる、電話番号と端末が1対1なのに対し、Twilioは一対多の関係にあります。

もちろん、1対1の作りでも構築できますが、月額108円が最低でも1人ずつにかかり、

管理コストも膨大なことになります。

これはTwilioが提供しているJavaScriptライブラリや、iOS/AndroidのSDKを使用し、

ブラウザなりアプリなりで仮想電話端末を実装することで解決します。

言われれば当然ですが、いざやってみないと身にしみて分からないこともあります。

同じ電話番号にかかってきた通話を誰に割り振るかを考えないといけない

先のことを理解した時に、この問題にぶつかります。

Twilioへ指示を出すことで誰に割り振るかの指示は出せますが、

誰に割り振るか自体は自分たちで考える必要があります。

この時点で、システムだけでは解決できず、現場で仕事している

営業やオペレーターなどと連携が必要です。

また、先の事実はエンジニアであればすぐに理解できるかもしれませんが、

必ずしもITリテラシーの高くない人へ納得性のある説明をした上で、

現場でどう割り振るのがベストなのかコミュニケーションを取る必要があります。

新しい技術に触れながら、現場の知識も取り込んでいかないといけない。

リアルタイムとの戦い

仕様も無事に決まりました。次に襲いかかる問題がこれです。

一般的なWebエンジニアであれば、実戦経験の少ない

リアルタイムとの戦いが待っています。

受電した通話を誰に割り振るかは決まっても、

その人が在席していないとその通話は空振りになりお客様を待たせることになります。

そこでかかってきた時点のオペレーターの状態を取得する必要があります。

リアルタイムで状態を取得する方法

下記3つが簡単に思いつきます。

  1. DBなどに管理し、逐一問い合わせてみる
  2. Twilio.Syncを使ってみる
  3. Twilio.Taskrouterを使ってみる
DBで管理する場合

在席状態を管理するために、逐一ajaxなどでその人の状態をupdateし続ける必要があります

これはサバクラ両方を1人でスクラッチしつつ、

保守フェーズですべて管理する必要があります。

人数が少なければ可能かもしれないですが、あまり現実的ではなさそうです。

Twilio.Syncを使う場合

SyncとはTwilioが提供しているWebsocketを用いた、リアルタイム通信ができる機能です。

最初に僕がやってみたのがこれでした。

Syncを使うとサーバ側実装がなく、インフラの設定や保守が不要で、

使用した分だけの料金で使うことが出来ます。

ただこの機能は検索性が高くなく、500件のデータを入れたSyncを検索した所、

10秒ほどかかってしまい、受電で使うには難しかったです。

人数次第では選択肢に入ってくるかもしれませんが、実装した上で弊社では採用しませんでした。

Syncを使おうとした時の記事は下記を参照。

http://harinoma.info/?p=32

Twilio.Taskrouterを使う場合

TaskrouterとはTwilioが提供しているACDです。

ACDとは通話を誰に割り振るか分配する機能です。

ロードバランサーというとイメージが付きやすいと思います。

Taskrouterは受電に特化した機能です。最終的に弊社で採用したのはTaskrouterです。

Taskrouterについては、下記記事参照。

http://harinoma.info/?p=45

Taskrouter実装との戦い

ライブラリは提供されているだけなので、当然実装する必要があります。

実装するにあたり、一番苦戦した点はドキュメントではもっとも単純なケースの例しかなく、

弊社の仕様ではどうTaskrouterを構築し、実装すべきなのかわからなかったことです。

自分のベストを尽くしたつもりだけど、

構築した環境が良いのかどうかは運用フェーズまで明らかにならないと思われます。

デバッグの大変さ

最終的にはPC4台+サブディスプレイ2枚+電話機1台+私用携帯電話1台を用いた

デバッグ構成で実機デバッグをしました。

一般的なTwilioエンジニアの開発風景

受電した通話の情報を元にどのようなタスクが作成され、誰に割り振られるかまでは

実機がなくてもデバッグ可能です。(これもまあまあ大変ですが)

ですが、在席離席の挙動は想定通りか、リアルタイムで在席状態が正しく取得できるか、

クライアントの通話に問題はないか、タイムアウトとエスカレートの挙動の確認など、

実機で試さないとわからないことが多いです。

物理的にデバッグ環境構築が大変なのは初めてでした。

構築した後もなかなか大変なデバッグ作業になります。

すべてを乗り越えて

晴れて受電の機能が完成です。

受電1つ取ってもこれだけの大ボリュームが待っています。

特に失敗したなと感じたのは、Syncの速度感をもっと早く調べておくべきだと思いました。

弊社では、SyncもTaskrouterもどっちも使うよくばりプランなので、

Syncの実装自体は有用でしたが、最速の実装かと言われるとそうではなかったです。

弊社の場合、ACDを導入していなかったため、

とりあえず導入するだけでも改善効果が見込めます。

具体的には担当営業へ直接つながることによるお客様への安心感の提供、

取次時間を減らせることへの業務改善です。

タイムアウトやエスカレートの仕組みは今回あまり活用できていませんが、

今後の改善へ手が打ちやすくなる布石として考えています。

やっぱり難しそうだな〜と思うあなたへのメッセージ

https://twiliomeetup.doorkeeper.jp/events/68355

このイベントに参加しますので、ぜひ話しましょう!

僕だけでなく、Twilio開発に携わるエンジニアがたくさん参加しますので、

得られることもたくさんありますよ。

次回予告

12/13のアドベントカレンダーで具体的なTaskrouterの設定例を載せますのでお楽しみに。

WebRTCについて調べた

WebRTCについて調べた

こんにちは、@24guchiaです。

Webの記事何本かと本2冊買って読んでみたので、一度、現状の理解を書いてみます。

ちなみに買った本は下の本と、

 

わか(った気にな)るWebRTCの電子版です。

https://booth.pm/ja/items/504677

読む順番としては、わか(った気にな)るWebRTCを読んで、

ざっくり概要を頭に入れてわかった気になってから、リックテレコムのWebRTCの本を読むと良いと思います。

いきなりリックテレコムから入ると心が折れること間違い無し。

最近、リックテレコムから販売されている本を買うことが増えてきた。

この記事で分かること

WebRTCってそもそも何か、どういうところで使われてて、

どんなプロトコルが用意されているかが分か(った気にな)るようになります。

なんで調べたの?

Twilioを使うにあたって、Twilioがそのあたり難しい部分を吸収したライブラリやSDKを用意してくれてるけど、

デバッグするにあたってあまりにも分からないことが多すぎたため。

Twilio使わないから知らなくても良いや〜って思わず、ネットワークについての勉強になるし、

最近ではiOS11からWebRTC対応されスマホ全般で使える技術となったので、

Web系の開発をしている人は押さえておくべき技術になっていくでしょう。

WebRTCってそもそも何?

Web Real Time Communicationの略。名前の通り、

ブラウザでのリアルタイム性を持つコミュニケーション全般を取り扱います。

コミュニケーションは具体的に、音声通話や動画(ビデオチャット)などを指します。

特長はインターネット回線につながっているブラウザさえあれば、

上記コミュニケーションを行える点です。

もう電話機や専用のソフトウェアは必要なくなります。

WebRTCを使っているサービスは何がある?

Twilio

appear.in

Slack音声通話

などがあります。使ったことがあるサービスがあると思います。

リアルタイムコミュニケーションってどうやってるの?

  1. 音声などの情報入出力の許可をユーザによって行わせる
    • 不正にユーザの情報を収集しづらくするために、ユーザに許可・拒否を選択させる
  2. ピア同士の接続の確立
    • 次に詳細な説明を書きます
  3. ピア同士のデータ交換
    • データ交換によって、音声通話やビデオチャットが可能になります
  4. 接続の終了

ピア同士の接続の確立って難しそうだね?

はい、難しいですね

接続の確立について、オファーアンサーネゴシエーションという

ローカルとリモートの設定を交換する手法があります。

  1. 接続を試みる側がどのメディアどのデコードで送るかをオファーとして送る
  2. 受け手側は、送られたオファーに対して、対応可能かと他に使いたいものリストをアンサーとしてオファー側に送る
  3. アンサーを受取、各ピア同士で受け取った情報を設定することでデータ交換が行えるようになる

ネットワークの制限

セキュリティを高めるためのファイアウォールや

NATの存在が接続の確立にあたっては障害となる。

その回避を行うため、特別なプロトコルが用意されています。

NAT is 何?

Network Address Translatorの略。

IPアドレスは有限の資源であり、資源の有効活用のために使われる。

グローバルIPをNAT機能持ちルータで、ルータ内のプライベートIPとの変換を行う技術。

NAPTであることがほとんどで、ポートの変換も行うことが多い。

正確にはNAPTだけど、一旦NATで統一します。

ピア同士が接続されるWebRTCだが、

NATの存在のため、接続先ピアがどのプライベートIPを持っているかが

外側からは分からないため、下記NAT越えが行われる。

NAT越え is 何?

上記問題への対応のため、ピアに直接パケットを送るために行われる手法・技術。

具体的には、ホールパンチという手法でNATを透過したテストパケットを送れるかどうかを試す。

ホールパンチ is 何?

NATの外から、プライベートIPアドレスとポート番号のペアを知るために行われる手法。

具体的には下記手法を試していく。

ICE is 何?

Interactive Connectivity Establishmentの略。プロトコルのひとつ。

NAT越えを行うための手法の一つ。ICEでは下記を行う。

  • IPアドレスとポート番号のペアを集める
  • ピア同士がペアを交換する
  • ホールパンチを試す
  • 繋がるペアでデータ交換を行う

上記が純粋な手法で、よくあるICEではSTUNプロトコルとTURNプロトコルを使い、

ピア同士の接続の確立を試みます。

また、VanillaとTrickleという拡張がある。

Vanilla ICE is 何?

標準のICEを指す。拡張であるTrickleが出来たため、標準がVanillaと呼ばれる。

VanillaはすべてのIPアドレスとポート番号のペアを収集してから

すべて接続を試し、接続確立されたものから使用するペアを選択する。

バニラという単語自体には標準という意味がある。

ICEという名前のためのシャレみたいなもんでしょうね。

Trickle ICE is 何?

標準のICEに対し、拡張されたICEを指す。

Vanillaに対し、Trickleではペアを順次交換し、接続成功した時点で処理が終了されるので、

接続確立までがVanillaよりも速くできる可能性がある。

現時点ではChrome/Firefoxと一部ブラウザでしか対応していないため、

使用する際には最新の情報を調べてください。

Trickleは滴り落ちるという意味なので、ペアを少しずつ試すという点が

アイスが滴り落ちるのと様子に似ているからこの名前なんだと思います。

STUN is 何?

Session Traversal Utilities for NAT の略。プロトコルのひとつ。

これもNAT越えのための手法のひとつ。

STUNで対象のピアのネットワーク上にNATが存在するかどうかを確認するプロトコル。

テストパケットをSTUNサーバに送り、自分のIPが外部のネットワーク上からどういうIPで見えるかを確認します。

自分のIPと一致していれば、NATは存在しません。

NATが存在しなければ、NAT越えの必要なくパケットを送ることが出来ます。

存在する場合は、NATが一つ以上存在し、一番外側のNATの情報が取得できます。

STUNでアドレスとポートのマッピングを取得します。

このマッピング情報をもとにピア同士で接続するのがSTUNです。

TURN is 何?

Traversal Using Relays around NAT の略。プロトコルのひとつ。

TURNはSTUNの拡張プロトコル。ICEがホールパンチに失敗した場合、メディアリレーを行う。

ブラウザに実装されているTURNクライアントと、NATの外にあるTURNサーバと

接続先のピアがTURNサーバを経由し、メディア情報を交換している。

STUNとの違いはSTUNはピア同士で接続するのに対し、

TURNはピアとピアの間にTURNサーバが存在し、

TURNサーバ経由で接続する点が異なります。

ICEとSTUNとTURNの関係

同じNAT超えをしているし最初どういう関係かわかりませんでしたが、

iwashiさんからTwitterでリプライいただけたので書いておきます。

各プロトコルは独立している。TURNはSTUNの拡張プロトコル。

ICEはICE自身でのアドレスとポートのマッピングを行い、

さらにTURNとSTUNも利用するプロトコルです。

まとまれ

これらのプロトコルを用いて、ピア同士で接続できれば晴れてリアルタイムコミュニケーションが楽しめます。

Twilioではこの辺り難しいところを何も考えずに使える点が良いですね。

音声通話はもちろん、最近ではビデオチャット機能も充実してきているとのことなので、

手っ取り早くWebRTCに触れてみたい方はTwilioをさわってみてはどうでしょう。

https://twilio.kddi-web.com/

どういう構成だとSTUNでつなぐことが出来て、

TURNが必要になるのはどういう構成なのかなど今度調べてみます。

Twilio.Taskrouterを調べて使ってみた【長文】

こんにちは、@24guchia です。

掲題通り、便利そうだけどなんか難しそうだな・・・

と思って避けていたTwilio.Taskrouter導入しました。

 

最初にお伝えします。

理解が難しいですが、とても便利な機能です。

顧客を待たせることになる受電、手を抜かずにやりきりましょう。

 

2017/11/04 追記

なんと、Twilio.TaskrouterのプロマネからTwitterでコメントありました。

後ほど、まとめますが、気になる方は僕のTwitterアカウント参照してください。

@24guchia

2017/11/06 追記

一部、不明点やアドバイス頂いた点を追記しました。

Twilio.Syncで受電割り振りすると言ったな

http://harinoma.info/?p=32

あれは嘘だ。

すいません、Syncの使い方間違えてました。

Sync自体は在席管理で使い続けます。Syncも便利です。

Sync → Taskrouter変更の経緯

そもそもSyncでデータの中身に対して、クエリを発行する方法がない。

そのため、全件取得して中身を取り出して、該当する人だったら

その人に通話を割り振るとしていたが、500件mapに入れたら検索だけで10秒位かかった。

遅すぎて流石に厳しいので、ACDに特化したTaskrouterについて調べることにしました。

Taskrouter概要

理解が必要な概念は下記の通り。

  • Workspace
    • 以下概念を入れるための入れ物
  • Workflow
    • ACDとして、どの呼をどのTaskqueue(後述)に入れるかのルール設定ができる
    • 挙動としては、一般的なSwitch文に似ている。JSON形式で記述方法はSQLライクな文法で設定することが出来る
  • Taskqueue
    • 呼を入れて、待たせる。保留と同等なので、架電側には保留音が流れる(電話の場合)
    • FIFOとLIFOが選べる
    • このTaskqueueに入っているTask(後述)をどの属性を持ったWorker(後述)が対応可能かフィルタできる
    • 一般的な使い方はTaskqueueにセールス部門、サポート部門、全社員というような使い分けを行う
  • Task
    • 受電した呼に属性をJSONで持たせたもの
    • Taskが持っている属性でWorkflowの評価が行われ、Taskqueueへキューされる
    • 受電以外に問い合わせメールとかにも使えるらしいので、Taskという名前らしい
  • Worker
    • Taskを対応する人。オペレーターや営業など
    • Task同様、JSONで属性を持つ。Taskqueueのフィルタの際に評価される
    • 例えば、Aさんにセールス部門という属性をもたせ、Bさんにサポート部門という属性をもたせて、得意なTaskをこなせるように設定する
    • Task対応できるかどうかの属性(Available)やどういう状況(Activity)を持たせる
  • その他
    • Workflowによって、タスクキューという通話一覧にキューされる。
    • 優先度と時間によってエスカレートする仕組みがある。
    • タイムアウトの時間設定ができるので何秒か対応できなかったら、自動でエスカレートし、次の評価されたQueueに入る。

概念はこのようになっています。

振り分け処理について

先述の通り、Workflowsに設定しているJSONで振り分けを行っている。

task_routingに設定されているfiltersはSwitch文のように動作する。

filtersのexpressionに合致するタスクは、そのfilter内のtargetsに沿って通話振り分けが行われる。

いずれにも一致しない場合、default_filterのキューに入れられる。

switch caseとdefaultと同じです。

expressionの文法

SQLライク。JSONのキーバリューを走査してくれる。

ANDとORで接続する。一般的な比較ができる、==,!=,>,<,HAS,CONTAINS,IN,NOT INが使える。

型はString,Numbers(int and float),Booleanがある。配列も使える。

タスクにJSONで属性つけるとexpressionでの評価対象になる。

ここらへんはドキュメント読んでください。

Taskrouterってどうやって作るの

いつも通り、管理コンソールかREST APIで作る。

https://jp.twilio.com/console/taskrouter/workspaces/create

で、Twimlでどうやって使うの

Enqueueでworkflowに入れる。

そのときにTask名詞でexpressionの評価対象になる属性をJSON形式で設定できる。

で、クライアントではどう使うの

Taskrouter.jsというJavaScriptSDKが用意されているのでそれを使う。

トークン生成が必要なので、サーバ必須。

ここのところ激プッシュしてるFunctionsでもOKらしい。動画参照

https://www.youtube.com/watch?v=XMg5ytgyn1E

FunctionsだとCRM連携ってどうやるんだろう?

Taskrouterを使う場合の受電の流れ

  1. 受電するとTwilioの受電時Webhookが呼ばれる
    1. この画面で管理してるやつ → https://jp.twilio.com/console/phone-numbers/incoming
  2. 1で呼び出されたWebhook内でTaskをあるWorkflowにenqueueするtwimlを生成する
  3. Workflowの処理が呼び出だされTaskの属性とWorkerの属性によってタスク割り振りが決定し、予約が作成する
  4. 割り振りされたら、コールバックが呼ばれる
    1. この画面で管理してるやつ → https://jp.twilio.com/console/taskrouter/workspaces/WSxxx/workflows/WWxxx
  5. 4で呼び出されたコールバック内で、タスクをどうするかを決める処理を行う
    1. 今のところ使っているのはVoiceのみのため、基本的に全部callでWorkerのcontact_uriに電話かける
    2. Voice以外のタスクを取り扱うようになったら、適切なチャネルに流れるように設計する必要がある
  6. クライアントに電話がかかる
    1. 具体的にはTwilio.Device.incomingとworkerのイベントでresevation.createdが並行して呼ばれる。
    2. 並行に呼ばれるのはかなり厄介なので、他はどうしてるか知りたい

受電のフローはこうです。

Taskrouterの勘所

Taskとあるが、Queue(保留)の仕組みを組み合わせているだけ

これが理解できておらず、苦労しました。

Taskrouterで割り振られた通話の親通話がなぜか取れない

callAPIの受電では親通話に紐付いて、

クライアント側は子通話が生成されるが、Queueと同じ仕組みのため、

割り振られた受電でも、Queueに入っている通話に対して架電しているので、

親子関係が生成されない。

追記:親子関係が生成されない件について

下記ドキュメントにあるようにinstruction:conferenceを使用することで親子関係が生成されるようです。

https://www.twilio.com/docs/api/taskrouter/reservations#conference

現在はdequeueでクライアントにかけているため、

conferenceに変更し、どう挙動するか後ほどまとめます。

 

ACDって要するにロードバランサーだよね

Automatic Call Distributor/着信呼自動分配装置って、名前いかついし

そんなのWebで似た概念ないよな・・・って思ってたけど、

ロードバランサーと同じってのに気づくと、よく分からないものから

なんとなくイメージが付けやすくなると思います。

良いところ

  • 振り分け、タイムアウト、エスカレートできる
    • 振り分けはともかく、タイムアウトとエスカレートの処理を書くのはなかなかしんどいと思う
  • ソースを修正せずに、管理コンソールだけで受電振り分け設定を変更できる
    • 注意として、管理コンソールだけでは使用できない設定があり、更にAPIで設定しても管理コンソールに表示されないようなので、この事情を知らない人が勝手に変えると壊れる可能性があります
  • 受電したとき、clientだとcurrentの親callを取らないどこからの受電分からないが、taskrouterだとreservation.task.attributesに入ってる
    • 2017/11/06追記: conferenceでTaskを割り振りすることで親受電を取れるようです。現在、確認中
  • taskの生成を行う際、JSONになんでも情報を持たせることができ、クライアントでtask.attributesで参照できる
    • task.attibutesはめちゃくちゃ便利です!DBで取得した値を設定することで、クライアント側に受電と同時に取得した値の参照が出来るようになります。
    • API呼び出しとAPI保守費用が下がるので、めちゃくちゃ単純な割り振りしかないからいいやって思わずに、使うと良いです

困りどころ

  • dequeue/callを使うと、クライアントの受電とアサインされたtaskの受電で2つとも同じ処理(Twilio.Device.incoming)を通るので、処理の切り分けが必要
    • dequeueだと、connection.parameters.ApiVersionがなぜかないが判断基準にするには微妙(そもそもない事自体がバグなのでは?)
  • dequeue/callを使うと、Twilio.Device.incomingがreservation.createdより先に発火する事が多い
    • 電話は鳴るが、アサインされたtaskが参照できないので若干無駄な瞬間がある
    • たまにreservationの方が速かったりするので、reservation.createdを必ず待つことができない
  • ワーカーのavailabilityを見て、割り振りするかの設定であるskip_ifが管理コンソールで変更できない
    • API呼び出しで解決しました
    • APIでskip_if付けても、管理コンソールに表示されないっぽい?
    • 挙動確認したところ、ドキュメント通りなので反映はされているらしい
    • StackOverflowで聞いてるけど、回答が来なくて悲しかったのはちょっと前の話
    • https://stackoverflow.com/questions/46884250/how-do-i-configure-skip-if-on-twilio-taskrouter-workflow
    • 2017/11/06追記:↑先日、回答がありました。現在はAPIで更新/参照の必要があります
    • なんとドキュメントに見れない件がNoteとして記載されていました。嬉しい:)
    • https://www.twilio.com/docs/api/taskrouter/worker-presence
  • TaskQueueに対応可能Workerがいなくても、一旦キューに入ってタイムアウトまで待つ
    • 対応可能Workerがいない場合、次のキュー判定に入るかどうかの設定がほしい
  • TaskAttributesがマルチバイト文字が未サポート
    • 下記、気合のエンコードとデコードで解決
    • サーバ側(Php)でurlencode()でエンコードして、クライアント側(Taskrouter.js)でdecodeURIComponent(reservation.task.attributes.name)でデコードする
    • Syncではマルチバイト文字対応してるのになんでだろう
    • 2017/11/06追記:Taskの割り振りに関係ないため、対応していないらしい。現在、対応を希望していますが、同上の理由により優先度を上げて対応は難しいとのこと。

REST APIではまったとこ(Php)

https://www.twilio.com/docs/api/taskrouter/workers

  • Workerを作るAPIのオプショナルパラメータでドキュメントのFIELDがプログラムで使う連想配列のキーと一致しない
    • ActivitySidはactivitySid、Attributesはattributesをキーにする必要がある。ドキュメント仕事してくれ
    • パラメータ変換するだけのクラス作りました
  • Attributesに設定するのは単純な配列じゃなくて、JSON化する必要がある
    • JSON化はTwilioのライブラリ側でやるでも良いような気がする
    • json_encode,json_decodeしないで文字列でゴリゴリJSONを扱うってあんまりしないし
  • Worker削除しようとする時に、そのWorkerのavailableがtrueだと削除できない。
    • 対応として、削除する関数にforce引数を付けて、force=trueだったら削除前にavailableがfalseのactivityに変えている。
  • QuickStartのドキュメントは更新されてないので、APIは別でドキュメントを読む必要あり

Taskrouter.jsではまったとこ(クライアント側)

  • Workerのトークン生成でreservation更新を許可しておらず、403が出た
    • エラーメッセージがちょっと分かりづらかった
    • 403 Policies defined such that we cannot access the given resource
    • dequeueでかかってきた通話をconnectするとreservationが更新されたのでより混乱してしまった
  • Worker生成のオプションでdisconnectActivitySid設定しても、アクティビティが変わらない?

まとめ

困りどころ多いですね!

ただそれを差し引いても便利機能なので、がんばって実装しましょう。

後で使いそうなドキュメント

Twilio Developer Meetup 2017に参加しました

こんにちは、@24guchiaです。
先日、タイトルのイベントに参加したのでそのレポートです。

全体的に

サーバレスについて語られていました。
TwilioのFunctionsはAWSで言うところのLambdaに似た機能です。

サーバレスの良いところ

何と言ってもサーバを管理する必要がない点です。
通常のサーバ運用だと、サーバセットアップしたり後、
継続的にセキュリティ対策するなどの継続的なコストがかかります。
それらをプロ中のプロがセットアップ済みメンテナンス込みで用意してくれるところが、
サーバレスの良いところです。

デメリット

デメリットになりうるのはサービスで用意してある設定で対応できない場合だと思います。
それは事前調査である程度は回避できるのではないでしょうか。
今回のミートアップでは上記のことを話されていましたが、
現状だとFunctionsでできることの少なさや、改善してほしいことが多く、
プロダクト採用には遠いかなというのが正直な感想です。

Functionsへの要望としては、バージョン管理、デプロイの機構、
外部パッケージの利用をかんたんにしてほしいというのがパッと思い浮かぶところです。

まだまだ課題は多いですが、サーバ管理もやる身としては、サーバ管理をする必要がなくなるなんて夢のある話です。
また、Functionsを利用することで、サービスが全てTwilio内で収まるため、
パケットロスが減らせるとのことです。
PDCAが回せるよう、Functionsで賄えることは少しずつ使えるようにしていきたいです。

初めてのLT

今回のイベントで初めてLTしました。
反省点はこんな感じ↓

  1. 文字が全般的に小さかった
  2. みんな座って聞いてるわけじゃなかった
  3. Wifiがなかったので、みんなにデモしてもらうことができなかった
  4. 色味が黒すぎた
  5. もう少しキャッチーな画像があったほうが良さそう
  6. プライマリディスプレイにもスライド出す必要あった

見た目的なことは次のLTで改善したい。
あと、どういう状況でLTするかの事前確認しないと行けないのと、
Twilioのミートアップだったから、電話番号出せたら面白い。
今回、ミラーリングしなかったのは普通に見づらくてしくったなって感じ。

ググってもググっても出てこないことばっかりやってるので
大変でもあり、前例がないことをやっていてやりがいがあるとも感じてます。
最近読んだ本で、どんなことでも積極的にシェアすることが重要とあったので、
引き続き懲りずにシェアしていきます。

最近読んだ本↓

スライドシェアにデモ部分削除して、アップしました。
こちらです

以上、ありがとうございました。