はじめに
【Dify×Notion】ナレッジ検索+回答生成のチャットフローを作るで、Notion × Difyを使用したお問い合わせ用のチャットフローを作成したのですが、より実用的なものを作ってみたくなり、n8nとLINE Messaging APIを組み合わせて、お問い合わせ用のLINEチャットボットを作成しました。
ものすご〜くザックリしてますが、フローイメージは、以下のような感じ。
そして、UIイメージは、以下の通りとなります。
今回、覚書きも兼ねて、記事を書きました。
長くなるので、
- n8nパート: Notion × Dify × n8n × Messaging APIでお問い合せ用のLINEチャットボットを作成する ~ n8nでワークフローを作成する ~
- LINE Messaging APIパート: Notion × Dify × n8n × LINE Messaging APIでお問い合せ用のLINEチャットボットを作成する ~ LINE Messaging APIでLINE公式アカウントからの問い合わせを可能にする ~
に分割してまして、本記事は前者の方(n8nバート)になります。
利用環境
本記事における利用環境は、以下の通り。
- n8n: クラウド版
登録後、最初の2週間無料で使えるので、サクッと始めるために今回はクラウド版をチョイスしました。
補足事項
2週間経過すると、実行が不可になることはおろか、作成したワークフローを見ることすらできなくなってしまうようので、ゆっくり取り組みたい方、ゆくゆく実運用化を検討している方は、Docker環境を作成してngrokなどローカル環境を外部公開できるようにするツールを使うのもアリかな、と。
他環境での作業
1. DifyのAPIシークレットキーの取得
使用するDifyのチャットフローより、APIシークレットキーを取得し、控えておきます。
コチラに手順を記載しているので、よければ参考にしてください。
DifyのAPIシークレットキーは、HTTP Request1で使用します。
2. LINE Messaging APIのチャンネルアクセストークンの取得
HTTP RequestとHTTP Request2で使用します。
Notion × Dify × n8n × Messaging APIでお問い合せ用のLINEチャットボットを作成する ~ LINE Messaging APIでLINE公式アカウントからの問い合わせを可能にする ~の内容の実施がこれからかと思いますので、一旦はダミーで入力し、作業を実施した後に正規の値を入力してください。
n8nでの作業
それでは、n8n上で作業をしてきましょう!
今回は、以下のようなワークフローを作成します。
(1) サインアップ
まずは、サインアップします。
n8nのトップページにアクセスし、「Get Started」をクリック。
必要事項を入力し(①)、「Start free 14-day trial」をクリック(②)。
※この後も簡単な質問のようなものが続きます。
(2) ワークフローの作成
まずは、ワークフローを作成します。
画面左の「+」をクリックし(①)、「Workflow」をクリック(②)。

すると、以下のような画面に遷移するので、画面左上の赤枠の欄をクリックして、チャットフロー名を入力しておきましょう。

(3) 各ノードの作成
続いて、ノードを作成していきましょう。
以下の手順では、
- 原則、上のスクショの左から、同じ位置に複数のノードがある場合は、上から
- デフォルト値から変更が必要な部分のみ
記載しています。
Webhookノード
まずはいちばん左端のWebhookノードから作成します。
初期状態では、画面の中央部に「Add first step...」と下に書かれた「+」のみがありますので、それをクリック。
すると、以下のような画面右端にノード検索用のウィンドウが出てきます。
検索ボックスに「Webhook」と入力すると(①)、候補が出ますので、「Webhook」を選択しましょう(②)。
「Webhook」ノードの編集画面が出ますので、以下の通り入力。
入力が完了したら、右上の「×」をクリックしましょう(⑤)。
| 項目 | 入力値 |
|---|---|
| ①HTTP Method | POST |
| ②Path | inquery |
| ③Respond | When Last Node Finishes |
| ④Response Data | First Entry JSON |
そうすると、Webhookノードが出来上がっています。
次のノード追加のために、右方に突き出た「+」をクリックすると(①)、画面右にノード検索ウィンドウが起動するので、検索ボックスに次のノード名を入力して(②)、検索、追加します。
以後は基本的にはこの作業の繰り返しとなります。
なお、作成したWebhookのProduction URLは、で使用します。
編集画面にて、「Production URL」をクリックするとその下に表示されるURL控えておきましょう。
Edit Fieldsノード
先ほど作成したWebhookノードの次に、Edit Fieldsノードを追加します。
編集画面の「Add Field」を2回クリックし、
Fields to Set に2つの欄ができたら、以下の通り入力しましょう。
Fields to Set・その0
| 項目 | 入力値 |
|---|---|
| name | data |
| T | String |
| = | 以下に記載 |
- 入力値
{{ $json.body.events[0].postback?.data || $json.body.events[0].message.text }}
Fields to Set・その1
| 項目 | 入力値 |
|---|---|
| name | replyToken |
| T | String |
| = | 以下に記載 |
- 入力値
{{$json.body.events[0].replyToken}}
Switchノード
続いて、Switchノードを追加します。
今回は、6つの条件分岐を作成します。
先ほど作成hした、Edit Fieldsノードの右にSwitchノードを検索・追加したら、編集画面にて、「Add Routing Rule」を5回クリックして、
合計6つのRouting Rules欄を作成し、以下のように入力しましょう。
Routing Rules・その0
問い合わせ開始用です。
| 項目 | 入力値 |
|---|---|
| value1 | {{ $node['Edit Fields'].json['data'] }} |
| T | is equal to |
| value2 | start-inquiry |
Routing Rules・その1
| 項目 | 入力値 |
|---|---|
| value1 | {{ $node['Edit Fields'].json['data'] }} |
| T | is equal to |
| value2 | register-info |
Routing Rules・その2
| 項目 | 入力値 |
|---|---|
| value1 | {{ $node['Edit Fields'].json['data'] }} |
| T | is equal to |
| value2 | order-info |
Routing Rules・その3
| 項目 | 入力値 |
|---|---|
| value1 | {{ $node['Edit Fields'].json['data'] }} |
| T | is equal to |
| value2 | not-found |
Routing Rules・その4
| 項目 | 入力値 |
|---|---|
| value1 | {{ $node['Edit Fields'].json['data'] }} |
| T | is equal to |
| value2 | finish-inquiry |
Routing Rules・その5
| 項目 | 入力値 |
|---|---|
| value1 | true |
| T | is equal to |
| value2 | true |
Code in JavaScript
Switchノードの1番上(Routing Rules・その0)に、Code in JavaScriptを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Mode | Run Once for All Items |
| ②Language | JavaScript |
| ③JavaScript | 以下に記載 |
const options = [
{ label: "登録情報について", data: "register-info" },
{ label: "注文について", data: "order-info" }
];
const actions = options.map(opt => ({
type: "postback",
label: opt.label,
data: opt.data,
displayText: opt.label
}));
return [
{
json: {
messages: [
{
type: "template",
altText: "サポート内容を選択してください",
template: {
type: "buttons",
text: "サポートセンターです。\nご用件を選択いただくか、ページ下部より入力・送信してください。",
actions
}
}
]
}
}
];
Code in JavaScript1
Switchノードの上から2番目(Routing Rules・その1)に、Code in JavaScriptを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Mode | Run Once for All Items |
| ②Language | JavaScript |
| ③JavaScript | 以下に記載 |
const options = [
{ "label": "ID・パスワードを忘れた", "data": "ID・パスワードを忘れた" },
{ "label": "登録情報を変更したい", "data": "登録情報を変更したい" },
{ "label": "問い合わせたい内容が見つからない", "data": "not-found" },
];
const actions = options.map(opt => ({
type: "postback",
label: opt.label,
data: opt.data,
displayText: opt.label
}));
return [
{
json: {
messages: [
{
type: "template",
altText: "サポート内容を選択してください",
template: {
type: "buttons",
text: "ご質問内容を選択してください。",
actions
}
}
]
}
}
];
Code in JavaScript2
Switchノードの上から3番目(Routing Rules・その2)に、Code in JavaScriptを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Mode | Run Once for All Items |
| ②Language | JavaScript |
| ③JavaScript | 以下に記載 |
const options = [
{ "label": "注文をキャンセルしたい", "data": "注文をキャンセルしたい" },
{ "label": "商品の配送状況を確認したい", "data": "商品の配送状況を確認したい" },
{ "label": "返品・返金について知りたい", "data": "返品・返金について知りたい" },
{ "label": "問い合わせたい内容が見つからない", "data": "not-found" },
];
const actions = options.map(opt => ({
type: "postback",
label: opt.label,
data: opt.data,
displayText: opt.label,
}));
return [
{
json: {
messages: [
{
type: "template",
altText: "サポート内容を選択してください",
template: {
type: "buttons",
text: "ご質問内容を選択してください。",
actions
}
}
]
}
}
];
Code in JavaScript3
Switchノードの上から4番目(Routing Rules・その3)に、Code in JavaScriptを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Mode | Run Once for All Items |
| ②Language | JavaScript |
| ③JavaScript | 以下に記載 |
const options = [
{ label: "問い合わせを終了する", data: "finish-inquiry" },
];
const actions = options.map(opt => ({
type: "postback",
label: opt.label,
data: opt.data,
displayText: opt.label
}));
return {
json: {
messages: [
{
type: "template",
altText: "メニューを選択してください",
template: {
type: "buttons",
text: "お手数ですが、以下のお問合せ先までご連絡ください。\n\n総合フリーダイヤル: 0120-xx-xxxx\n平日: 9:30-20:00\n土日祝日: 9:30-17:30\n",
actions
}
}
]
}
};
HTTP Request
Switchノードの上から5番目(Routing Rules・その4)に、HTTP Requestを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Method | POST |
| ②URL | https://api.line.me/v2/bot/message/reply |
| ③Send Headers | トグルON |
| ④Specify Headers | Using Fields Below |
| ⑤Header Parameters1: Name | Authorization |
| ⑥Header Parameters1: Value | Bearer {LINE Messaging APIのチャンネルアクセストークン} |
| ⑦Header Parameters2: Name | Content-Type |
| ⑧Header Parameters2: Value | application/json |
| ⑨Send Body | トグルON |
| ⑩Body Content Type | JSON |
| ⑪Specify Body | Using JSON |
| ⑫JSON | 以下に記載 |
{
"replyToken": "{{ $node['Edit Fields'].json['replyToken'] }}",
"messages": [
{
"type": "text",
"text": "お問い合わせを終了します。\nありがとうございました。"
}
]
}
HTTP Request1
Switchノードの一番下(Routing Rules・その5)に、HTTP Requestを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Method | POST |
| ②URL | https://api.dify.ai/v1/chat-messages |
| ③Send Headers | トグルON |
| ④Specify Headers | Using Fields Below |
| ⑤Header Parameters1: Name | Authorization |
| ⑥Header Parameters1: Value | Bearer {DifyのAPIシークレットキー} |
| ⑦Header Parameters2: Name | Content-Type |
| ⑧Header Parameters2: Value | application/json |
| ⑨Send Body | トグルON |
| ⑩Body Content Type | JSON |
| ⑪Specify Body | Using JSON |
| ⑫JSON | 以下に記載 |
{
"inputs": {},
"query": "{{ $node['Edit Fields'].json['data'] }}",
"response_mode": "blocking",
"conversation_id": "",
"user": "user-001"
}
Code in JavaScript4
HTTP Request1に、Code in JavaScriptを繋げ、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Mode | Run Once for Each Items |
| ②Language | JavaScript |
| ③JavaScript | 以下に記載 |
Modeは、他箇所と異なり、Run Once for Each Itemsとなります。
const answer = $json.answer;
const options = [
{ label: "問い合わせを終了する", data: "finish-inquiry" },
];
const actions = options.map(opt => ({
type: "postback",
label: opt.label,
data: opt.data,
displayText: opt.label
}));
return {
json: {
messages: [
{
type: "template",
altText: "メニューを選択してください",
template: {
type: "buttons",
text: `${answer}\n\n終了する場合は、「問い合わせを終了する」をタップしてください`,
actions
}
}
]
}
};
HTTP Request2
一番右端に、Http Requestノードを作成し、以下のように入力します。
| 項目 | 入力値 |
|---|---|
| ①Method | POST |
| ②URL | https://api.line.me/v2/bot/message/reply |
| ③Send Headers | トグルON |
| ④Specify Headers | Using Fields Below |
| ⑤Header Parameters1: Name | Authorization |
| ⑥Header Parameters1: Value | Bearer {LINE Messaging APIのチャンネルアクセストークン} |
| ⑦Header Parameters2: Name | Content-Type |
| ⑧Header Parameters2: Value | application/json |
| ⑨Send Body | トグルON |
| ⑩Body Content Type | JSON |
| ⑪Specify Body | Using JSON |
| ⑫JSON | 以下に記載 |
{
"replyToken": "{{ $node['Edit Fields'].json['replyToken'] }}",
"messages": [
{
"type": "template",
"altText": "{{ $json.messages[0].altText }}",
"template": {{ JSON.stringify($json.messages[0].template) }}
}
]
}
"template": {{ JSON.stringify($json.messages[0].template) }}のvalueは、""で囲わないでください。
入力が完了したら、
- Code in JavaScript
- Code in JavaScript1
- Code in JavaScript2
- Code in JavaScript3
- Code in JavaScript4
と繋げましょう。
(4) 公開
「Save」ボタンをクリックして(①)編集内容を保存したら、「Activate」のトグルをONにすると公開状態になります(②)。
エンドポイントのURLを知っていれば誰でも使用できてしまうので、使わない時はトグルをOFFにしておきましょう。
終わりに
今回n8nで作成したワークフローについて、Difyでも頑張れば作れなくはなさそうでしたが、
- switchによる条件分岐を使いたかったのと、
- 役割分担
の観点から、LINEからの問い合わせの受付と返答はn8nに持たせました。
実際やってみた感想としては、変数入りのJSONの扱い方が特に難しかったです。
冒頭でも書いた通り続きの作業は、
にて。


































