LINEからA2019のボットを実行させてみた

RPAに対して「人間の作業を自動化する」というイメージを持たれている方が多いかと思いますが、私はノンコーディングなオーケストレーション・プラットフォームとしての使い方も多くなるだろうと思っています。これだけの技術を、楽するため”だけ”に使うのは**もったいない**ので。

・・ということで、Automation Anywhere A2019のAPI機能を使い、LINE、IBM Watson Assistant と連携させてみました。

#####想定ユースケース：
チャットボットとの会話に応じて関係するボットを実行させる・・ということで、
今回は「不正利用されてるっぽいんで、何はともあれカード止めて！」をイメージして作ります。

構成は、ざっとこんな感じです（厳密には LINE－Watson Assistant 間にも Node-RED が介在します）。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/d2192a2e-c753-2792-fe61-5bf95331a5fb.png width=70%>

今回のケースでは A2019 へは一方通行となりますが、A2019 には REST アクションや各種スクリプト言語（PythonやJavaなど）用アクションなど外部への連携アクションも豊富にそろっていますので、これらを使えばLINEへ返信するなども簡単に組み込むことができます。

#####前提：
A2019ではセキュリティ上の観点から、API実行時に必要なトークンに有効期限が設けられています（デフォルトでは20分）。そのため、定期的にトークンを更新しなければなりませんが、その**トークン生成もノンコーディングで自動化するためにNode-REDを間に挟んで簡単にサクッと実現**したいと思います。ただし、仕様上は有効期限が切れた際にトークンを更新すればよいのですが、今回は連携例の説明目的のためそこまで作り込まず、実行指示の都度、トークンを更新する簡単な仕様としています。

1．IBM Watson AssistantとLINEの連携は、他のドキュメントなどを参考に設定をお願いします。
  ちなみに私は下記を参考にさせていただきました。

+ [LINEチャットボットとWatsonを連携する](https://medium.com/@taiponrock/line%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%9C%E3%83%83%E3%83%88%E3%81%A8watson%E3%82%92%E9%80%A3%E6%90%BA%E3%81%99%E3%82%8B-8a7d89a49e57)
+ [無料で作る LINE & Watsonチャットボット開発](https://hituji-ws.com/ai/line-watson-chatbot/)
+ [LINE x Watson AIボット入門](https://qiita.com/bird_tomita/items/4c307f05b6de384b0170)

参考までに下記は私の環境で使用したNode-RED用フローです（様々な方の情報を~~参考に~~かなり流用させていただきました）。Node-RED の右上メニューからインポートしてお使いいただけます。

<details><summary>サンプルフロー</summary><div>
**（注意）使用に際しては下記2か所を修正してください**

- create reply message ノードのコード内 (LINE Channel access tokenを貼り付け) 箇所
- watson-assistant-v2” ノードの assistant_id

```JSON
[
    {
        "id": "6909d0ea.fd4a5",
        "type": "tab",
        "label": "LineBot",
        "disabled": false,
        "info": ""
    },
    {
        "id": "8c8ae145.b9b2b",
        "type": "http in",
        "z": "6909d0ea.fd4a5",
        "name": "webhooks",
        "url": "/LineBot",
        "method": "post",
        "upload": false,
        "swaggerDoc": "",
        "x": 120,
        "y": 120,
        "wires": [
            [
                "8fafc93c.46d0a8"
            ]
        ]
    },
    {
        "id": "8fafc93c.46d0a8",
        "type": "function",
        "z": "6909d0ea.fd4a5",
        "name": "get text",
        "func": "flow.set(\"replyToken\",msg.payload.events[0].replyToken);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 340,
        "y": 120,
        "wires": [
            [
                "89c425dd.f85f08",
                "2cad866c.860b9a"
            ]
        ]
    },
    {
        "id": "6f537222.1c1e9c",
        "type": "http request",
        "z": "6909d0ea.fd4a5",
        "name": "reply message",
        "method": "POST",
        "ret": "obj",
        "paytoqs": false,
        "url": "https://api.line.me/v2/bot/message/reply",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 660,
        "y": 360,
        "wires": [
            []
        ]
    },
    {
        "id": "345bd957.2f5696",
        "type": "function",
        "z": "6909d0ea.fd4a5",
        "name": "create reply message",
        "func": "//var output_text = flow.get(\"text\");\nvar post_request = {\n    \"headers\": {\n        \"content-type\": \"application/json; charset=UTF-8\",\n        \"Authorization\": \" Bearer \" + \"{(LINE Channel access tokenを貼り付け)}\"\n    },\n    \"payload\": {\n        \"replyToken\": flow.get(\"replyToken\"),\n        \"messages\": [\n            {\n                \"type\": \"text\",\n                \"text\": flow.get(\"optext\") + \" \"\n            }\n        ]\n    }\n};\nreturn post_request;",
        "outputs": 1,
        "noerr": 0,
        "x": 380,
        "y": 360,
        "wires": [
            [
                "6f537222.1c1e9c"
            ]
        ]
    },
    {
        "id": "cef17837.63acc8",
        "type": "change",
        "z": "6909d0ea.fd4a5",
        "name": "watson return value stored variable",
        "rules": [
            {
                "t": "set",
                "p": "optext",
                "pt": "flow",
                "to": "payload.output.generic.0.text",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 900,
        "y": 260,
        "wires": [
            [
                "345bd957.2f5696"
            ]
        ]
    },
    {
        "id": "89c425dd.f85f08",
        "type": "change",
        "z": "6909d0ea.fd4a5",
        "name": "watson parameter switching",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.events.0.message.text",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 400,
        "y": 260,
        "wires": [
            [
                "22f470cc.5f28c"
            ]
        ]
    },
    {
        "id": "22f470cc.5f28c",
        "type": "watson-assistant-v2",
        "z": "6909d0ea.fd4a5",
        "name": "",
        "service-endpoint": "",
        "assistant_id": "(Watson AssistantのAssistant IDを貼り付け)",
        "debug": false,
        "restart": false,
        "return_context": true,
        "alternate_intents": false,
        "multisession": false,
        "timeout": "",
        "optout-learning": false,
        "x": 650,
        "y": 260,
        "wires": [
            [
                "cef17837.63acc8"
            ]
        ]
    },
    {
        "id": "2cad866c.860b9a",
        "type": "http response",
        "z": "6909d0ea.fd4a5",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 630,
        "y": 80,
        "wires": []
    }
]
```
</div></details>

2．IBM Watson AssistantとNode-REDの連携についても、他のドキュメントなどを参考に設定をお願いします（前述の参考サイトの中でも触れているものがあります）。
  ちなみに私は下記を参考にさせていただきました。

+ [IBM CloudでNode-REDを使う方法](https://inoccu.net/blog/2020/03/08/160126.html)

※いずれも、バージョンアップや仕様変更等により手順や設定箇所等が変更されているケースがありますが、大きく流れは変わらないため参考になるかとは思います（手抜きですみません）。

#####手順：

手順としては大きく以下となります。

**LINE**
1. LINE developers へ登録
2. プロバイダー／チャンネルの作成
**IBM Cloud**
3. IBM Cloud へ登録
5. Watson assitant サービスを作成
4. Node-RED Apps を作成
6. Watson Assistant で Skill や Dialog を作成
7. Node-RED で LINEと Watson Assistant をつなぐフローを作成（前述のサンプルコード）
**A2019**
8. A2019 にて呼び出される Bot を作成
9. API 実行に必要な情報を取得（参考：[A2019でAPI＜基本の4選＞](https://qiita.com/stig/items/55aec0ffb81cb1bac2d7)）
**IBM Cloud**
**10. Watson Assistant で Bot 実行用の Dialog を作成**
**11. Node-RED で Bot 実行用のフローを作成**

本稿での記載としては**10以降**となります。

##10. Watson Assistant で Bot 実行用の Dialog を作成

まずは、Watson Assitant から Node-RED を呼び出すための Webhooks を設定します。
呼び出すURLには、Node-RED Apps 作成時に生成されたURLに ”/BotDeploy” を付加した URL としています。

Node-RED Apps 作成時に生成されたURLは、下記のアプリの詳細画面左上の「アプリ URL」に記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/5c9317ce-82a4-093e-9bc8-f66f6ac3dc43.png)

URLの設定先は、下記の Watson Assistant 画面の Daialog 画面内にある Options 配下の Webhooks となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/ef2123a5-79d5-b9f6-01ce-f5a8aa9ee581.png)
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/0d9c6c0a-e88b-5073-3ebd-e108ff22f63d.png width=50%>

次に、Botを実行させるためのDialogを作成します。
私は、デフォルトで用意されている「#Customer_Care_Report_Fraudulent_Use」を使い、それだけではチョット芸が無いので、チャットボットらしく応答によってBotの実行要否を確認してからBotを実行させるDialogとしました。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/1ca6cb29-db9b-93c1-8135-8aceab7f6e5c.png width=50%>

Bot を実行させたい node を開き、右上の ”Customize”をクリックし、Customize 画面を開きます。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/a4b7f57c-a83f-512a-a9b0-8659e375a70a.png)

Customize 画面にて、Webhooks スイッチを ON にします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/3a7e2c71-4815-0a5b-c85e-c7879af7e708.png width=50%>

ここでの設定のポイントは、”Then callout to my webhook” の ”Parameters” へ以下を設定することになります。ここで設定された値が、呼び出される Node-RED のフローへ引き渡されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/862852c5-055a-01d8-0971-861e3b5ba9f9.png)

|Parameters   |入力する値|
|:------------|:--------------------------------------|
|botId        |実行させたい Bot の ID をセット|
|apiKey       |API を実行するユーザーの apiKey を入力|
|userName     |API を実行するユーザーの userName を入力|
|runAsUserId  |Bot を実行するユーザーの userId を入力|

※Parameters の名前は任意です。Watson Assistant と Node-RED 内で使用する一時的な名前になります。

会話の中でメニュー（リスト）から実行させたい Bot を指定させて引き渡す、会話の内容に応じて実行させる Bot を変える・・なんてことも簡単にできるので、活用の幅が広がりますね。

これで、Watson Assitant 側の設定は完了です。

こちらは上記設定のサンプルコードとなります。
Watson Assistant の右上メニューからインポートしてお使いいただけます。

<details><summary>サンプル Skill</summary><div>

```JSON
{
    "intents": [
      {
        "intent": "General_Jokes",
        "examples": [
          {
            "text": "私を驚かせて"
          },
          {
            "text": "面白い事言って"
          },
          {
            "text": "面白い事言ってください"
          },
          {
            "text": "あそぼー"
          },
          {
            "text": "あそびましょ"
          },
          {
            "text": "ついてこられるか"
          },
          {
            "text": "なんかニュースある？"
          },
          {
            "text": "俺についてこい"
          },
          {
            "text": "冗談わかる"
          },
          {
            "text": "冗談言ってみて"
          },
          {
            "text": "寒くない？"
          },
          {
            "text": "楽しませて"
          },
          {
            "text": "楽しませてくれるね"
          },
          {
            "text": "ご機嫌だね"
          },
          {
            "text": "ご機嫌にさせて"
          },
          {
            "text": "歌える？"
          },
          {
            "text": "歌ってくれる？"
          },
          {
            "text": "気分はどう？"
          },
          {
            "text": "ジョークは理解しますか"
          }
        ],
        "description": "ジョークを要求します"
      },
      {
        "intent": "General_Human_or_Bot",
        "examples": [
          {
            "text": "誰と話しているのかわかりません"
          },
          {
            "text": "AIですか？"
          },
          {
            "text": "AIと話すのですか？"
          },
          {
            "text": "だれ？"
          },
          {
            "text": "ロボットですか？"
          },
          {
            "text": "あなたはロボットですか？"
          },
          {
            "text": "あなたはコンピュータですか？"
          },
          {
            "text": "あなたは人ですか"
          },
          {
            "text": "人ですか？"
          },
          {
            "text": "今。誰と話しているのでしょうか？"
          },
          {
            "text": "私は今誰と話しているのでしょうか？"
          },
          {
            "text": "私はコンピュータと話しているの？"
          },
          {
            "text": "私は誰と話していますか？"
          },
          {
            "text": "コンビュータと話していますか？"
          },
          {
            "text": "ワトソンと話してますか？"
          },
          {
            "text": "あなたは誰ですか？"
          },
          {
            "text": "誰と話しているのかわからない"
          }
        ],
        "description": "人間やボットに話すかどうか尋ねます"
      },
      {
        "intent": "Customer_Care_Report_Fraudulent_Use",
        "examples": [
          {
            "text": "アカウントのログイン記録を確認できますか？"
          },
          {
            "text": "不正使用"
          },
          {
            "text": "アカウントが不正使用された場合、どうすればいいですか？"
          },
          {
            "text": "不正使用防止機能について教えてください"
          },
          {
            "text": "不正ログインを調べる方法はありますか？"
          },
          {
            "text": "アカウント乗っ取りされたけどどうすればいいですか"
          },
          {
            "text": "アカウント乗っ取り確認"
          },
          {
            "text": "乗っ取り確認できる方法はありますか"
          },
          {
            "text": "今週他の地理位置からログインした記録はありますか？"
          },
          {
            "text": "このパソコン以外のログイン記録はありますか？"
          },
          {
            "text": "会員カードが盗まれたため停止してください"
          },
          {
            "text": "会員証をなくしてしまったため停止してください"
          },
          {
            "text": "アカウントの使用履歴を調べたい。"
          },
          {
            "text": "アカウントの使用履歴を調べてくれる？"
          },
          {
            "text": "アカウントハックされたので凍結して欲しい"
          },
          {
            "text": "盗用や不正利用など悪用された場合はどうすればいいですか？"
          },
          {
            "text": "カードが盗難されてしまいました、どうすればいいですか？"
          },
          {
            "text": "クレジットカードを紛失してしまいました"
          },
          {
            "text": "クレジットカードが不正使用されました。"
          },
          {
            "text": "誰か私のアカウントにログインした気がする。"
          }
        ],
        "description": "アカウントの不正使用を報告します"
      },
      {
        "intent": "General_Greetings",
        "examples": [
          {
            "text": "やぁ"
          },
          {
            "text": "ちわっ"
          },
          {
            "text": "ヤッホー"
          },
          {
            "text": "こんにちは。"
          },
          {
            "text": "おはようございます"
          },
          {
            "text": "ちょっといいですか？"
          },
          {
            "text": "あけましておめでとうございます"
          },
          {
            "text": "もしもし、サービスセンターですか？"
          },
          {
            "text": "今よろしいですか"
          },
          {
            "text": "今大丈夫？"
          },
          {
            "text": "何かお困りでしょうか"
          },
          {
            "text": "お忙しいところすみません。"
          },
          {
            "text": "挨拶"
          },
          {
            "text": "教えてください"
          },
          {
            "text": "すみませんが、ちょっとお時間宜しいですか。"
          },
          {
            "text": "もしもし。林です。"
          },
          {
            "text": "すみませんが、ちょっと聞きたいことがありますが。"
          },
          {
            "text": "ちょっと質問したいんですけど。"
          },
          {
            "text": "質問してもいいですか"
          },
          {
            "text": "連絡してくれてありがとうございます、これからよろしくお願いします"
          }
        ],
        "description": "ボットに挨拶します"
      }
    ],
    "entities": [
      {
        "entity": "yesno",
        "values": [
          {
            "type": "synonyms",
            "value": "大丈夫",
            "synonyms": []
          },
          {
            "type": "synonyms",
            "value": "結構",
            "synonyms": []
          },
          {
            "type": "synonyms",
            "value": "はい",
            "synonyms": []
          },
          {
            "type": "synonyms",
            "value": "お願い",
            "synonyms": []
          },
          {
            "type": "synonyms",
            "value": "いいえ",
            "synonyms": []
          }
        ],
        "fuzzy_match": true
      }
    ],
    "metadata": {
      "api_version": {
        "major_version": "v2",
        "minor_version": "2018-11-08"
      },
      "from-sample": true
    },
    "webhooks": [
      {
        "url": "（Node-RED 呼び出し先URLを入力）",
        "name": "main_webhook",
        "headers": []
      }
    ],
    "dialog_nodes": [
      {
        "type": "response_condition",
        "output": {
          "text": {
            "values": [
              "アカウント停止処理を開始します。アカウントの停止処理が完了するとメールにてご連絡します。"
            ],
            "selection_policy": "sequential"
          }
        },
        "parent": "node_2_1587634140981",
        "conditions": "anything_else",
        "dialog_node": "response_8_1587634486698",
        "previous_sibling": "response_1_1587634485160"
      },
      {
        "type": "response_condition",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "アカウント停止処理を開始しました。アカウントの停止処理が完了するとメールにてご連絡します。"
                }
              ],
              "response_type": "text",
              "selection_policy": "multiline"
            }
          ]
        },
        "parent": "node_2_1587634140981",
        "conditions": "$webhook_result_1",
        "dialog_node": "response_1_1587634485160"
      },
      {
        "type": "standard",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "オペレータにお繋ぎします。少々お待ちください。"
                }
              ],
              "response_type": "text",
              "selection_policy": "sequential"
            }
          ]
        },
        "parent": "node_1_1587633901303",
        "conditions": "@yesno:いいえ || @yesno:大丈夫 || @yesno:結構",
        "dialog_node": "node_8_1587634509443",
        "previous_sibling": "node_2_1587634140981"
      },
      {
        "type": "standard",
        "parent": "node_1_1587633901303",
        "actions": [
          {
            "name": "main_webhook",
            "type": "webhook",
            "parameters": {
              "botId": "（実行させるBotのbotIdを入力）",
              "apiKey": "（APIを実行するユーザーのapiKeyを入力）",
              "userName": "（APIを実行するユーザーのuserNameを入力）",
              "runAsUserId": "（Botを実行するユーザーのuserIdを入力）"
            },
            "result_variable": "webhook_result_1"
          }
        ],
        "metadata": {
          "_customization": {
            "mcr": true
          }
        },
        "conditions": "@yesno:はい || @yesno:お願い",
        "dialog_node": "node_2_1587634140981"
      },
      {
        "type": "standard",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "何かご用件はありますか？"
                }
              ],
              "response_type": "text",
              "selection_policy": "sequential"
            }
          ]
        },
        "conditions": "#General_Greetings",
        "dialog_node": "node_5_1587626570248",
        "previous_sibling": "node_1_1587633901303"
      },
      {
        "type": "standard",
        "title": "その他",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "解釈できませんでした。申し訳ありませんが違う表現を試していただけますか。"
                },
                {
                  "text": "恐れ入りますが表現を変えていただけますか。解釈できませんでした。"
                }
              ],
              "response_type": "text",
              "selection_policy": "sequential"
            }
          ]
        },
        "conditions": "anything_else",
        "dialog_node": "その他",
        "previous_sibling": "node_1_1587626054731",
        "disambiguation_opt_out": true
      },
      {
        "type": "standard",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "ムリ💦"
                }
              ],
              "response_type": "text",
              "selection_policy": "sequential"
            }
          ]
        },
        "conditions": "#General_Jokes",
        "dialog_node": "node_6_1587626518038",
        "previous_sibling": "node_5_1587626570248"
      },
      {
        "type": "standard",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "すぐにアカウントを凍結することをお勧めします。"
                },
                {
                  "text": "このまま、一時的なアカウントの停止処理を行いますか？"
                }
              ],
              "response_type": "text",
              "selection_policy": "multiline"
            }
          ]
        },
        "context": {
          "yesno": ""
        },
        "conditions": "#Customer_Care_Report_Fraudulent_Use",
        "dialog_node": "node_1_1587633901303",
        "previous_sibling": "ようこそ"
      },
      {
        "type": "standard",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "信じるか信じないかはあなた次第です。"
                }
              ],
              "response_type": "text",
              "selection_policy": "sequential"
            }
          ]
        },
        "conditions": "#General_Human_or_Bot",
        "dialog_node": "node_1_1587626054731",
        "previous_sibling": "node_6_1587626518038"
      },
      {
        "type": "standard",
        "title": "ようこそ",
        "output": {
          "generic": [
            {
              "values": [
                {
                  "text": "はい、何かご用ですか？"
                },
                {
                  "text": "ご用件をどうぞ"
                }
              ],
              "response_type": "text",
              "selection_policy": "multiline"
            }
          ]
        },
        "conditions": "welcome",
        "dialog_node": "ようこそ"
      }
    ],
    "counterexamples": [],
    "system_settings": {
      "disambiguation": {
        "prompt": "もしかして",
        "enabled": true,
        "randomize": true,
        "max_suggestions": 5,
        "suggestion_text_policy": "title",
        "none_of_the_above_prompt": "上記のいずれにも該当し"
      },
      "human_agent_assist": {
        "prompt": "もしかして"
      }
    },
    "learning_opt_out": false,
    "name": "DEMO Skill",
    "language": "ja",
    "description": ""
  }
```
</div></details>

##11. Node-RED で Bot 実行用のフローを作成

この工程では、下記のフローを作っていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/6524a1fd-9723-6ff0-5f2a-97771a40d007.png)

大きな流れとしては、
1. Change ノードでトークン更新リクエストのボディ部を作成
2. http request ノードでトークン更新のリクエスト
3. Change ノードでBot 実行リクエストのボディ部を作成
4. http request ノードで Bot 実行のリクエスト
となります。

具体的な内容は下記のコードをご覧いただくか、Node-RED へインポートしてください。
**修正箇所は、2つの http request ノード にそれぞれある (A2019のURLを入力) となります。**修正タイミングはインポート前と後のどちらでも構いません。

※もし、Watson Assistant の Dialog にて Parameters の名称を変更や追加された際は、各 Change ノードの変更も必要になります。

<details><summary>Node-RED フロー</summary><div>

```JSON
[
    {
        "id": "bc817430.562118",
        "type": "tab",
        "label": "BotDeploy",
        "disabled": false,
        "info": ""
    },
    {
        "id": "89ae558a.8cb288",
        "type": "http request",
        "z": "bc817430.562118",
        "name": "",
        "method": "POST",
        "ret": "obj",
        "paytoqs": false,
        "url": "(A2019のURLを入力)/v1/authentication",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 910,
        "y": 220,
        "wires": [
            [
                "46d76b49.1f1414",
                "a629f324.92c37"
            ]
        ]
    },
    {
        "id": "72e34cbd.e86db4",
        "type": "http request",
        "z": "bc817430.562118",
        "name": "",
        "method": "POST",
        "ret": "obj",
        "paytoqs": false,
        "url": "(A2019のURLを入力)/v3/automations/deploy",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 910,
        "y": 320,
        "wires": [
            [
                "efff7424.ddf758"
            ]
        ]
    },
    {
        "id": "6ab4151f.8aebac",
        "type": "http in",
        "z": "bc817430.562118",
        "name": "",
        "url": "/BotDeploy",
        "method": "post",
        "upload": false,
        "swaggerDoc": "",
        "x": 140,
        "y": 100,
        "wires": [
            [
                "b74d5e3c.ed9c6",
                "982db960.090f08"
            ]
        ]
    },
    {
        "id": "efff7424.ddf758",
        "type": "debug",
        "z": "bc817430.562118",
        "d": true,
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 1090,
        "y": 320,
        "wires": []
    },
    {
        "id": "b74d5e3c.ed9c6",
        "type": "change",
        "z": "bc817430.562118",
        "name": "set variable",
        "rules": [
            {
                "t": "set",
                "p": "botId",
                "pt": "flow",
                "to": "payload.botId",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "apiKey",
                "pt": "flow",
                "to": "payload.apiKey",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "userName",
                "pt": "flow",
                "to": "payload.userName",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "runAsUserId",
                "pt": "flow",
                "to": "payload.runAsUserId",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 210,
        "y": 220,
        "wires": [
            [
                "149f9a69.895be6"
            ]
        ]
    },
    {
        "id": "46d76b49.1f1414",
        "type": "change",
        "z": "bc817430.562118",
        "name": "set token",
        "rules": [
            {
                "t": "set",
                "p": "token",
                "pt": "flow",
                "to": "payload.token",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 200,
        "y": 320,
        "wires": [
            [
                "b1830eeb.047d6"
            ]
        ]
    },
    {
        "id": "eb6c5d4b.a09a3",
        "type": "debug",
        "z": "bc817430.562118",
        "d": true,
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 890,
        "y": 160,
        "wires": []
    },
    {
        "id": "f69188e3.cc4148",
        "type": "change",
        "z": "bc817430.562118",
        "name": "set token request message",
        "rules": [
            {
                "t": "set",
                "p": "headers.content-type",
                "pt": "msg",
                "to": "application/json",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.username",
                "pt": "msg",
                "to": "userName",
                "tot": "flow"
            },
            {
                "t": "set",
                "p": "payload.apiKey",
                "pt": "msg",
                "to": "apiKey",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 660,
        "y": 220,
        "wires": [
            [
                "89ae558a.8cb288",
                "eb6c5d4b.a09a3"
            ]
        ]
    },
    {
        "id": "a629f324.92c37",
        "type": "debug",
        "z": "bc817430.562118",
        "d": true,
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 1090,
        "y": 220,
        "wires": []
    },
    {
        "id": "149f9a69.895be6",
        "type": "change",
        "z": "bc817430.562118",
        "name": "delete msg.payload",
        "rules": [
            {
                "t": "delete",
                "p": "payload",
                "pt": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 410,
        "y": 220,
        "wires": [
            [
                "f69188e3.cc4148"
            ]
        ]
    },
    {
        "id": "b1830eeb.047d6",
        "type": "change",
        "z": "bc817430.562118",
        "name": "delete msg.payload",
        "rules": [
            {
                "t": "delete",
                "p": "payload",
                "pt": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 410,
        "y": 320,
        "wires": [
            [
                "4037c9a0.6929f8"
            ]
        ]
    },
    {
        "id": "4037c9a0.6929f8",
        "type": "change",
        "z": "bc817430.562118",
        "name": "set botdeploy request message",
        "rules": [
            {
                "t": "set",
                "p": "headers.content-type",
                "pt": "msg",
                "to": "application/json",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "headers.x-authorization",
                "pt": "msg",
                "to": "token",
                "tot": "flow"
            },
            {
                "t": "set",
                "p": "payload.fileId",
                "pt": "msg",
                "to": "botId",
                "tot": "flow"
            },
            {
                "t": "set",
                "p": "payload.botInput.sInputString1.type",
                "pt": "msg",
                "to": "STRING",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.botInput.sInputString1.string",
                "pt": "msg",
                "to": "rgdfg",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.botInput.bBooleanInput.type",
                "pt": "msg",
                "to": "BOOLEAN",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.botInput.bBooleanInput.boolean",
                "pt": "msg",
                "to": "true",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "payload.botInput.dInputDict1.type",
                "pt": "msg",
                "to": "DICTIONARY",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.botInput.dInputDict1.dictionary[0].key",
                "pt": "msg",
                "to": "Key 1",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.botInput.dInputDict1.dictionary[0].value.type",
                "pt": "msg",
                "to": "STRING",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.botInput.dInputDict1.dictionary[0].value.string",
                "pt": "msg",
                "to": "cvbdfgdfg",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.status",
                "pt": "msg",
                "to": "ACTIVE",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.rdpEnabled",
                "pt": "msg",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "payload.setAsDefaultDevice",
                "pt": "msg",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "payload.workspaceName",
                "pt": "msg",
                "to": "public",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.runAsUserIds[0]",
                "pt": "msg",
                "to": "runAsUserId",
                "tot": "flow"
            },
            {
                "t": "set",
                "p": "payload.scheduleType",
                "pt": "msg",
                "to": "INSTANT",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload.poolIds",
                "pt": "msg",
                "to": "[]",
                "tot": "json"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 670,
        "y": 320,
        "wires": [
            [
                "72e34cbd.e86db4",
                "cbd276ae.1fbbc8"
            ]
        ]
    },
    {
        "id": "cbd276ae.1fbbc8",
        "type": "debug",
        "z": "bc817430.562118",
        "d": true,
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 890,
        "y": 380,
        "wires": []
    },
    {
        "id": "982db960.090f08",
        "type": "http response",
        "z": "bc817430.562118",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 370,
        "y": 100,
        "wires": []
    }
]
```
</div></details>

####これで設定作業は完了です。作成したフローをデプロイし試してみましょう。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/7c1b3623-c678-aa9a-7137-70474a6df9df.png width=70%>
「はい」の回答にて Bot 実行リクエストが投げられUnattended Bot がサブミットされ、リクエスト結果を受け取り「アカウント停止処理～」が返信されます。

**（お詫び）実は今回、サブミット結果が何であれ「アカウント停止処理～」返信となります(^-^;。結果を受けて返信内容を変えるなどは、Watson Assistant 側で定義可能ですが、~~ちょっと手抜き~~読まれる方々へのエンハンスの余地を残した次第です(;'∀')モノは言いよう...**

-----
**（参考）Change ノードについて：**
今回のケースではChange ノードを使い、http リクエスト用のヘッダーやボディ部をノンコーディングで作っています。JSONの構造どおり Change ノードを設定すればよいので、簡単に作成することが可能です。

**ボディー部の例：**
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/1ec6ea67-bf4b-b0e0-3d35-648a961e459f.png width=50%> 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/a06b1de6-be5e-3746-6027-675ecfc04974.png)

より詳しく知りたい方は、下記が参考になるかと思います。
[Node-RED User Group Japan メッセージを利用する](https://nodered.jp/docs/user-guide/messages)
[Changeノードを制すものがNode-REDを制す](https://qiita.com/joeartsea/items/1be1b7f8d08fab04ca73)
[Changeノードを知り反省しWio Nodeの例でhttp requestノードまでの流れを書き直す](https://qiita.com/tseigo/items/544e62eac6a9b9353523)