TwilioのTaskRouterでオペレータに通話を割り振る


はじめに

Twilioで開発していて、「ブラウザで着信なんかはできたけど、複数人のオペレータに割り振る時はどうするの?」てな時のためのTaskRouterです。

大まかに以下のような流れになります。

  1. 電話がかかってくる(発信者はオペレータに繋がるまで待つ)
  2. (TwiMLを返すAPIが)タスクを作って「WorkFlow」に入れる
  3. 「WorkFlow」はタスクを順番に「Activities(オペレータの状態)」に割り振っていく
  4. 割り振られたアクティビティの状態にあるオペレータが電話をとる(例えば、オンラインアクティビティにふられたら、オンラインの状態のオペレータが電話をとる)
  5. 通話が完了したらタスクの状態をCompleteにする

今回は最低限動かすために、「タスクを作ってWorkFlowに入れる処理」、「タスクを取り出してアクティビティに割り振る処理」だけ書きます。

Twilio Consoleで準備

ひとまずWorkflow、Activities、Workerなどはあらかじめ作ってしまいます。

  • 公式サイトのTaskRouterからWorkspacesを作成。SIDを控える
    • Workspaces > Workflows からWorkflowを作り、SIDを控える
    • Workspaces > Workers から適当な従業員を作る。ひとまずACTIVITYはAvailableにする
    • Workspaces > Activities からAvailableのSIDを控える

APIを用意する

Node.js + Expressの例

import express = require("express");
import { Twilio, twiml } from "twilio";

const app = express();

// ここでキューにタスクをつっこむ
app.route("/enqueue").post((_, res) => {
  const voice = new twiml.VoiceResponse();
  voice.say("enqueue! enqueue!"); // エンキュー! エンキュー! と叫ぶ
  // voice.say({ voice: "Polly.Mizuki", language: "ja-JP" }, "日本語でおk");
  const enqueue = voice.enqueue({ workflowSid: "" });
  enqueue.task({}, JSON.stringify({ hi: "test" })); // 追加で送りたい内容とか指定できる
  res.type("text/xml");
  res.send(voice.toString()); // タスク割り当ての命令の入ったTwiMLを返します
});

// タスクを取り出してアクティビティに割り振る
app.route("/assignment").post((_, res) => {
  res.send({
    instruction: "dequeue", // キューを取り出す
    post_work_activity_sid: "", // 割り振り先のアクティビティ
  });
});

// タスクを完了させる
// app.route("/complete").post(async (req, res) => {
//   const taskId = req.body.taskId; // タスクIDをリクエストボディから受けどります
// 
//   const twilio = new Twilio("アカウントのSID", "アカウントのAuthToken");
//   const workspace = twilio.taskrouter.workspaces("WorkspaceのSIDを入れる");
//   await workspace.tasks(taskId).update({ assignmentStatus: "completed" }); // TODO: エラーハンドリング
//   res.send("終了");
// });

workflowSidpost_work_activity_sidには、控えておいたSIDを入れてください。
(実際に運用するなら.envなどで設定。認証やバリデータなどもつけます)

詳しくは公式ドキュメント公式Gitにあります。

できたらngrokなどを使って、どこかに公開します。

作ったAPIをTwilioに設定する

  • Twilioの電話番号の設定で、VoiceのWEB HOOKに/enqueueのURLを設定
  • TaskRouterのWorkflowsの設定で、AssignmentCallbackに/assignmentのURLを設定
  • TaskRouterのWorkersの設定で、ATTRIBUTESに{"contact_uri":"client:オペレータ名"}を入れる

オペレータ名は、クライアントが着信を受け取るためのトークン生成時に設定したやつです。

こんな感じの
import { jwt } from "twilio";

const capability = new jwt.ClientCapability({
  accountSid: "accountSid",
  authToken: "authToken",
});
capability.addScope(
  new jwt.ClientCapability.IncomingClientScope("オペレータ名")
);

「そんなもの書いた覚えはない」という方いたらごめんなさい。。。
オペレータ名でなくても、コールバックには特定の番号やSIPが設定できます

ひとまず動かす

電話をかけると、「エンキュー! エンキュー!」と言われたあと音楽が流れ、オペレータ宛に着信がくると思います

ただ、タスクをまだ完了させていないので、同じアカウントで2回目の着信を受けられません
TaskRouter.jsを使うか、APIを作ってからEnqueueのAction属性で指定してあげるなどがいいかもですね(taskIdが取りにくいので、task一覧からwrapping状態のtaskを探して、complete状態にするなど)

できたら次はWorkspaces、Workers、TaskQueue、Workflowをプログラムから構成できるようにするといいかもですね