API.AIのAgentはそれ単体でChatBotのように振舞うこともできますが、 ChatBotの前段に置いてユーザの入力を解析し適切な処理を呼び出す役割として利用します。
Agentにwebhookの設定を行いバックエンドのAPIを呼び出す場合の流れは以下のようになります。
1. (Slackなどから)ユーザの入力をAgentに送信
2. Agentが入力を分析しIntentを選択
3. 分析したデータをwebhookでバックエンドのAPIへ送信
4. バックエンドのAPIは受信したら処理を行いAgentへ応答を返す
5. Agentが応答のないようをユーザに配信する
Agentの作成
まず、チュートリアルを参考にエージェントを作成します。 言語は「日本語」を選択。ひとつのエージェントに対して複数指定や作成後の変更もできないみたいです。

Intentの作成
エージェントを作成したら
Intent を新規に作成します。
適当な名前でIntentを作成したら、まず
User Says を定義します。

「東京の今日の天気は?」に対して
@sys.geo-citycode>@sys.geo-city</code に 東京 @sys.datecode>@sys.date</code に 今日の をマッピングします。
(
@sys.geo-citycode>@sys.geo-city</code で 渋谷 は認識されなかったので 東京 にしました)
画面右側にデバッグ用のパネルがあるのでそちらで話しかけてみると以下のようになります。 まだ応答が定義されていないので「Not available」となります。

応答するために
Response を定義します。

今回は外部のデータを使用せずに応答するため「わかりません」という応答にします。

SHOW JSON からリクエストの内容を見てみると入力のテキストに対してパラメータが正しくマッピングされていることがわかります。
最初に「東京の今日の天気は?」という例文を学習させましたが「今日の東京の天気は?」と逆にしても正しくマッピングされたので驚きました。
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": "2017-08-28T00:05:38.31Z",
"lang": "ja",
"result": {
"source": "agent",
"resolvedQuery": "東京の今日の天気は?",
"action": "",
"actionIncomplete": false,
"parameters": {
"date": "2017-08-28",
"geo-city": "東京"
},
"contexts": [],
"metadata": {
"intentId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"webhookUsed": "false",
"webhookForSlotFillingUsed": "false",
"intentName": "weather"
},
"fulfillment": {
"speech": "2017-08-28 の 東京の天気はわかりません。",
"messages": [
{
"type": 0,
"speech": "2017-08-28 の 東京の天気はわかりません。"
},
{
"type": 0,
"speech": ""
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
入力テキストをwebhookを受信して応答する(Fulfillment)
Google Cloudの
Cloud Functions を作成し Fulfillment に設定します。
詳しいやり方はこちらを参考にしてください。
以下のソースのように関数の
request に先ほどのJSONが渡されるので処理して response に応答を返します。
本当なら天気APIを呼んだりするのですが今回は常に晴れを返すようにします。
exports.helloHttp = function helloHttp (req, res) {
let city = req.body.result.parameters['geo-city'];
let response = "今日の" + city + 'の天気は晴れです。';
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({
"speech": response,
"displayText": response
}));
};
この関数をデプロイしてFulfillmentに設定したのちにAgentの設定でwebhookをONにすると テキストを入力した際にこちらの関数にJSONがPOSTされるようになります。
このインタフェースを満たしていればCloud Functionsを使用しなくても通常のAPIや API Gateway + Lambdaでも実装可能と思います。(ApiKeyやBasic認証の設定もできました)
SlackからAgentを呼び出す(Integrations)
最後に作成したAgentをSlackに連携します。
Integrations からSlackの設定を選択します。
Google Assistant, Amazon Alexa, Microsoft Cortana, LINE Botなどの連携も追加できました。

テスト用のbotを選択するとSlackのチーム認証後、選択したチームに @apiai_botcode>@apiai_bot</code が参加します。

公開するにはSlack appの作成が必要みたいですが動作確認用にはテスト用のbotで十分かなと思います。
Entityで辞書を作成する
東京 はデフォルトの辞書(@geo-city)に登録されていましたが 渋谷 は登録されていませんでした。
このような場合は
Entity を使用して辞書を作ることでAgentに覚えさせることができます。
EntityはJSONまたはCSV形式でImport/Exportできるので簡単に扱えそうです。
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "cities",
"isOverridable": true,
"entries": [
{
"value": "渋谷区",
"synonyms": [
"渋谷区",
"渋谷",
"Shibuya",
"Shibuya-Ku"
]
}
],
"isEnum": false,
"automatedExpansion": false
}

松木佑徒