Dialogflow Fulfillment 與 API 整合完整教學

Dialogflow Fulfillment 與 API 整合完整教學
靜態回覆只能做簡單的 FAQ 機器人。要讓機器人真正有用,必須連接後端系統:查訂單、查庫存、處理預約。
Dialogflow 透過 Fulfillment(Webhook)讓你的機器人能呼叫外部 API,實現動態回覆。這篇文章從零開始,教你開發 Webhook、部署到 Cloud Functions、整合第三方 API。
如果你還不熟悉 Dialogflow 基礎,建議先閱讀 Dialogflow 完整指南 和 Intent 與 Context 教學。
Fulfillment 基礎概念
什麼時候需要 Fulfillment
不需要 Fulfillment 的場景:
- 回答固定問題(營業時間、地址)
- 純粹的閒聊對話
- 提供靜態資訊
需要 Fulfillment 的場景:
- 查詢即時資訊(訂單狀態、庫存數量)
- 執行動作(建立訂單、預約)
- 根據條件動態回覆
- 連接外部系統(CRM、ERP)
Webhook 運作原理
使用者 → Dialogflow → Webhook → 你的後端 → Webhook → Dialogflow → 使用者
│ │ │ │ │ │ │
「查訂單」 意圖理解 呼叫API 查資料庫 回傳結果 組合回覆 「您的訂單...」
流程說明:
- Dialogflow 偵測到需要 Fulfillment 的 Intent
- 發送 HTTP POST 請求到你設定的 Webhook URL
- 你的 Webhook 處理請求,呼叫資料庫或 API
- 回傳結構化的 JSON 給 Dialogflow
- Dialogflow 把內容發送給使用者
ES vs CX Fulfillment 差異
| 差異 | ES | CX |
|---|---|---|
| Request 格式 | v2 API 格式 | v3 API 格式 |
| Response 格式 | fulfillmentText / messages | fulfillmentResponse |
| Context 處理 | outputContexts | sessionInfo.parameters |
| 觸發方式 | Intent 級別啟用 | Page/Route 級別啟用 |
| 官方 SDK | dialogflow-fulfillment | 無官方 SDK |
本文主要以 ES 為例,CX 的 Webhook 開發請參考 Dialogflow CX 教學。
建立 Webhook 服務
使用 Cloud Functions(推薦)
Google Cloud Functions 是最簡單的 Webhook 部署方式,免管伺服器、自動擴展。
Step 1:建立 Cloud Function
- 前往 Google Cloud Console
- 選擇你的專案(與 Dialogflow Agent 相同)
- 搜尋「Cloud Functions」並進入
- 點擊「Create Function」
基本設定:
- Function name:dialogflow-webhook
- Region:asia-east1(台灣)
- Trigger type:HTTPS
- Authentication:Allow unauthenticated invocations
Step 2:撰寫程式碼
選擇 Runtime:Node.js 20
package.json:
{
"name": "dialogflow-webhook",
"version": "1.0.0",
"dependencies": {
"dialogflow-fulfillment": "^0.6.1"
}
}
index.js:
const { WebhookClient } = require('dialogflow-fulfillment');
exports.dialogflowWebhook = (request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Intent: ' + agent.intent);
console.log('Parameters: ' + JSON.stringify(agent.parameters));
function welcome(agent) {
agent.add('歡迎使用我們的服務!請問有什麼可以幫您?');
}
function fallback(agent) {
agent.add('抱歉,我不太理解您的意思。');
}
function checkOrder(agent) {
const orderId = agent.parameters.order_id;
// 這裡呼叫你的訂單系統
agent.add(`訂單 ${orderId} 的狀態是:處理中,預計明天出貨。`);
}
const intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('check_order', checkOrder);
agent.handleRequest(intentMap);
};
Step 3:部署
- 點擊「Deploy」
- 等待部署完成(約 1-2 分鐘)
- 複製觸發 URL
Step 4:在 Dialogflow 設定
- 進入 Dialogflow Console
- 點擊左側「Fulfillment」
- 啟用「Webhook」
- 貼上 Cloud Functions 的 URL
- 點擊「Save」
Step 5:啟用 Intent 的 Fulfillment
- 進入需要 Fulfillment 的 Intent
- 滾動到最下方
- 展開「Fulfillment」區塊
- 勾選「Enable webhook call for this intent」
- 儲存
使用 Node.js + Express
如果你想在自己的伺服器部署:
const express = require('express');
const { WebhookClient } = require('dialogflow-fulfillment');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
const agent = new WebhookClient({ request: req, response: res });
function handleIntent(agent) {
agent.add('這是自訂伺服器的回覆');
}
const intentMap = new Map();
intentMap.set('my_intent', handleIntent);
agent.handleRequest(intentMap);
});
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
注意:自建伺服器需要:
- HTTPS(可用 ngrok 測試)
- 公開可存取的 URL
- 處理擴展性問題
使用 Python Flask
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json()
intent_name = req['queryResult']['intent']['displayName']
parameters = req['queryResult']['parameters']
if intent_name == 'check_order':
order_id = parameters.get('order_id')
response_text = f'訂單 {order_id} 的狀態是:處理中'
else:
response_text = '收到您的訊息'
return jsonify({
'fulfillmentText': response_text
})
if __name__ == '__main__':
app.run(port=5000)
部署與 HTTPS 設定
本地測試用 ngrok:
# 安裝 ngrok
npm install -g ngrok
# 啟動本地伺服器
node server.js
# 另一個終端機
ngrok http 3000
# 複製 ngrok 給的 HTTPS URL,貼到 Dialogflow
正式部署選項:
- Google Cloud Functions(推薦)
- Google Cloud Run
- AWS Lambda
- Heroku
- 自建伺服器 + SSL 憑證
Dialogflow API 呼叫
除了被動接收 Webhook,你也可以主動呼叫 Dialogflow API。
DetectIntent API
DetectIntent API 讓你從自己的應用程式發送訊息給 Dialogflow。
使用場景:
- 自建聊天介面
- 整合到現有 App
- 批次測試對話
服務帳戶與驗證設定
Step 1:建立服務帳戶
- 前往 Google Cloud Console > IAM & Admin > Service Accounts
- 點擊「Create Service Account」
- 輸入名稱(如:dialogflow-client)
- 授予角色:「Dialogflow API Client」
- 建立金鑰(JSON 格式)
- 下載並安全保存金鑰檔案
Step 2:設定環境變數
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
範例程式碼
Node.js:
const dialogflow = require('@google-cloud/dialogflow');
const uuid = require('uuid');
async function detectIntent(projectId, text) {
const sessionId = uuid.v4();
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);
const request = {
session: sessionPath,
queryInput: {
text: {
text: text,
languageCode: 'zh-TW',
},
},
};
const [response] = await sessionClient.detectIntent(request);
const result = response.queryResult;
console.log('Intent:', result.intent.displayName);
console.log('Response:', result.fulfillmentText);
return result;
}
// 使用範例
detectIntent('your-project-id', '我要訂位');
Python:
from google.cloud import dialogflow_v2 as dialogflow
import uuid
def detect_intent(project_id, text):
session_client = dialogflow.SessionsClient()
session_id = str(uuid.uuid4())
session = session_client.session_path(project_id, session_id)
text_input = dialogflow.TextInput(text=text, language_code='zh-TW')
query_input = dialogflow.QueryInput(text=text_input)
response = session_client.detect_intent(
request={'session': session, 'query_input': query_input}
)
result = response.query_result
print(f'Intent: {result.intent.display_name}')
print(f'Response: {result.fulfillment_text}')
return result
# 使用範例
detect_intent('your-project-id', '我要訂位')
GitHub 範例專案
官方範例庫介紹
Google 提供官方範例程式碼:
Dialogflow ES:
Dialogflow CX:
社群推薦專案
| 專案 | 語言 | 功能 |
|---|---|---|
| dialogflow-fulfillment-nodejs | Node.js | 官方 Fulfillment 函式庫 |
| flask-dialogflow-webhook | Python | Flask Webhook 模板 |
| dialogflow-angular | TypeScript | Angular 整合範例 |
快速部署模板
一鍵部署到 Cloud Functions:
# 克隆範例專案
git clone https://github.com/your-repo/dialogflow-webhook-template.git
cd dialogflow-webhook-template
# 部署
gcloud functions deploy dialogflow-webhook \
--runtime nodejs20 \
--trigger-http \
--allow-unauthenticated \
--region asia-east1
進階整合
連接資料庫(Firestore / MySQL)
Firestore 範例:
const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();
async function checkOrder(agent) {
const orderId = agent.parameters.order_id;
const doc = await firestore.collection('orders').doc(orderId).get();
if (!doc.exists) {
agent.add('找不到這筆訂單,請確認訂單編號是否正確。');
return;
}
const order = doc.data();
agent.add(`訂單 ${orderId} 的狀態是:${order.status},預計 ${order.delivery_date} 送達。`);
}
MySQL 範例:
const mysql = require('mysql2/promise');
async function checkInventory(agent) {
const productName = agent.parameters.product;
const connection = await mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
const [rows] = await connection.execute(
'SELECT stock FROM products WHERE name = ?',
[productName]
);
if (rows.length > 0) {
agent.add(`${productName} 目前庫存 ${rows[0].stock} 件。`);
} else {
agent.add('找不到這個商品。');
}
await connection.end();
}
呼叫第三方 API
天氣 API 範例:
const axios = require('axios');
async function getWeather(agent) {
const city = agent.parameters['geo-city'];
try {
const response = await axios.get(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.WEATHER_API_KEY}&units=metric&lang=zh_tw`
);
const weather = response.data;
agent.add(`${city} 目前天氣:${weather.weather[0].description},氣溫 ${weather.main.temp}°C。`);
} catch (error) {
agent.add('抱歉,無法取得天氣資訊,請稍後再試。');
}
}
非同步處理與長時間任務
Dialogflow Webhook 有 5 秒的 timeout 限制。如果任務需要更久:
方法 1:快速回覆 + 後續通知
async function processLongTask(agent) {
const taskId = generateTaskId();
// 立即回覆
agent.add(`收到您的請求,處理中...我們會在完成後通知您(任務編號:${taskId})`);
// 非同步處理(不等待)
processTaskInBackground(taskId);
}
async function processTaskInBackground(taskId) {
// 執行長時間任務
const result = await someHeavyOperation();
// 完成後發送通知(透過 LINE Push、Email 等)
await sendNotification(taskId, result);
}
方法 2:使用 Cloud Tasks
把任務放入佇列,另一個服務處理:
const { CloudTasksClient } = require('@google-cloud/tasks');
async function queueTask(agent) {
const client = new CloudTasksClient();
const task = {
httpRequest: {
httpMethod: 'POST',
url: 'https://your-worker-service.com/process',
body: Buffer.from(JSON.stringify({ data: agent.parameters })).toString('base64'),
},
};
await client.createTask({ parent: queuePath, task });
agent.add('您的請求已加入處理佇列,稍後會通知您結果。');
}
錯誤處理與重試機制
async function robustApiCall(agent) {
const maxRetries = 3;
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
const result = await callExternalApi();
agent.add(`查詢結果:${result}`);
return;
} catch (error) {
lastError = error;
console.error(`Attempt ${i + 1} failed:`, error.message);
if (i < maxRetries - 1) {
await sleep(1000 * (i + 1)); // 指數退避
}
}
}
// 所有重試都失敗
console.error('All retries failed:', lastError);
agent.add('系統暫時忙碌,請稍後再試。如急需協助,請撥打客服專線。');
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
整合做不出來?後端整合是技術門檻最高的部分,牽涉到資安、效能、錯誤處理。預約技術諮詢,讓有經驗的人幫你解決整合難題。
部署與維運
監控與日誌
Cloud Functions 日誌:
- 前往 Google Cloud Console > Cloud Functions
- 選擇你的 Function
- 點擊「Logs」分頁
設定告警:
- 前往 Cloud Monitoring
- 建立告警政策
- 設定條件:錯誤率 > 5%、延遲 > 2 秒
- 設定通知管道(Email、Slack)
效能優化
1. 減少冷啟動
// 在 Function 外初始化連線,避免每次都重新連
const firestore = new Firestore();
exports.webhook = async (req, res) => {
// 使用已建立的連線
const doc = await firestore.collection('orders').doc('123').get();
// ...
};
2. 使用快取
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 300 }); // 5 分鐘快取
async function getData(key) {
let data = cache.get(key);
if (!data) {
data = await fetchFromDatabase(key);
cache.set(key, data);
}
return data;
}
3. 設定 minimum instances
避免冷啟動延遲:
gcloud functions deploy webhook \
--min-instances 1 \
--max-instances 10
安全性考量
1. 驗證請求來源
確認請求真的來自 Dialogflow:
// 檢查 User-Agent
if (!req.headers['user-agent'].includes('Google-Dialogflow')) {
return res.status(403).send('Forbidden');
}
2. 環境變數管理
敏感資訊不要寫在程式碼中:
// ❌ 不好
const apiKey = 'sk-xxxxx';
// ✓ 好
const apiKey = process.env.API_KEY;
3. 限制存取範圍
服務帳戶只給需要的權限,不要用 Owner 權限。
如果需要整合到行動 App,請參考 Dialogflow 行動開發整合教學。LINE Bot 整合請參考 Dialogflow LINE Bot 串接教學。
常見問題 FAQ
Q1: Dialogflow ES 和 Dialogflow CX 哪個比較好用?新專案該選哪個?
新專案首選 Dialogflow CX。(1) Dialogflow ES(Essentials,舊版)——免費額度較大、設定簡單、Intent-based 設計適合簡單問答。但限制:(A) 沒有 state machine 概念,複雜流程用 context 硬湊;(B) 每個 agent 只能 20 個 context/10,000 intents;(C) 不支援 flow-level 分組;(D) Google 開發投資已減少,新功能優先上 CX。(2) Dialogflow CX(舊稱 Conversational Agents)——付費(每次對話 $0.007 起)、visual flow builder、原生 state machine、Flow / Page / Route 概念清晰;適合複雜對話(預約、訂票、金融諮詢)。限制:(A) 學習曲線較陡;(B) 價格較高(每月可能 $500–5,000+);(C) 有些功能 overkill 簡單使用情境。選擇建議:(A) FAQ bot / 簡單客服 → Dialogflow ES(免費額度夠用);(B) 多步驟流程(註冊、預約、購買) → Dialogflow CX;(C) 企業 production 產品 → Dialogflow CX(免費方案長期維運風險);(D) 已用 ES 想遷移 → 可以共存,但重構 flow logic 大約需 2–4 週。2025 趨勢:Google 推出 Conversational Agents(整合 Gemini + CX + Dialogflow),未來可能是統一平台。
Q2: Fulfillment 一定要用 Webhook 嗎?Inline Editor 的 Cloud Functions 模式夠用嗎?
看規模和需求。(1) Inline Editor(Cloud Functions)——Dialogflow 內建的 Node.js 函數編輯器;優點:不用自己部署、免費額度夠小規模、設定簡單、適合原型。限制:(A) 只支援 Node.js(沒 Python);(B) 無法 import 大量套件;(C) 函數冷啟動 500ms–2 秒;(D) 難以整合複雜 middleware;(E) 不易做單元測試。(2) Webhook(自架伺服器 / Cloud Run / Lambda)——優點:(A) 任何語言(Python、Go、Java);(B) 任何 library;(C) 可 pre-warm 消除冷啟動;(D) 完整 CI/CD、監控、log;(E) 可與既有系統 tight integration。缺點:要自己維運、要有認證機制。選擇原則:(A) 原型 / FAQ bot / 小規模 → Inline Editor;(B) 中大型 production、需要查 DB、串第三方 API → Webhook;(C) 金融 / 醫療 / 敏感資料 → 一定 Webhook(資料不能放 Google);(D) 用 Python / Go 開發 → Webhook。實戰建議:Cloud Run 是 Webhook 的最佳選擇——serverless、按需付費、與 Dialogflow 在同一 GCP project 整合 IAM 簡單。
Q3: Webhook 驗證該怎麼做?Dialogflow 發來的 request 怎麼確認是真的?
三層驗證。(1) JWT Token 驗證(官方推薦)——Dialogflow 可以設定呼叫 webhook 時帶 Bearer token,你在 webhook 端驗證。(A) 在 Dialogflow Agent 設定裡設 webhook URL 和 auth header(如 Authorization: Bearer YOUR_SECRET);(B) webhook 端檢查:if request.headers['Authorization'] != 'Bearer YOUR_SECRET': return 403;(C) token 存在 Secret Manager 每 90 天輪替。(2) Request signature 驗證——Dialogflow CX 支援 webhook 簽章:你 webhook 用 shared secret 驗證 request 沒被竄改。(3) IP 白名單(較弱但常用)——Google 的 Dialogflow request 來自特定 IP range(查 Google 官方文件),webhook 只接受這些 IP。常見錯誤:(A) 不驗證 webhook 呼叫者——任何人知道你的 webhook URL 都能打,可能被濫用或洩密;(B) JWT secret hardcode 在 code 裡——要存 Secret Manager;(C) 沒做 payload schema validation——惡意 payload 可能讓 webhook 崩潰。production checklist:(1) HTTPS only(不接受 HTTP);(2) Authorization header 驗證;(3) rate limiting(同一 session 不超過 60 req/min);(4) request/response logging(debug 用);(5) Cloud Armor / WAF 在前擋 DDoS。
Q4: 對話機器人要存對話紀錄、跨 session 記憶,該怎麼設計?
Dialogflow 本身不保留對話紀錄(隱私設計),要自己做。架構模式:(1) Session state(短期記憶)——Dialogflow 的 Context / Session Parameters 本身已經夠用,session 期間自動維持;(2) Conversation history(長期儲存)——每次 webhook 呼叫時把 user input、bot response、timestamp、user_id、session_id 存到 DB(Firestore、PostgreSQL、MongoDB 都可),以 user_id 當 key 查詢歷史;(3) User profile(跨 session)——獨立 table 存使用者資料(偏好、過往購買、聯絡資訊),每次 webhook 時 user_id 查出來餵給邏輯。實作方式(Python + Firestore):webhook handler 裡呼叫 db.collection('conversations').document().set({user_id, session_id, user_input, bot_response, timestamp: firestore.SERVER_TIMESTAMP})。隱私與合規:(1) 儲存對話紀錄要告知使用者(privacy policy);(2) GDPR 要求提供「查看和刪除」功能;(3) 敏感資料(信用卡、密碼)不要存——要做 redaction;(4) 保留期限——一般 6–12 個月足夠,超過刪除。進階:用對話歷史增強 AI 回應——把最近 5–10 輪對話放進 prompt 餵給 LLM(Gemini、Claude),讓 AI 有 context 做更自然回答——這是 2025 年常見做法。
Q5: Dialogflow 的費用要怎麼算?500 個 DAU 的 Chatbot 月費大概多少?
Dialogflow ES 多數情境免費,CX 要仔細算。(1) Dialogflow ES 定價——(A) Text:$0.002 per request(每月前 15,000 requests 免費);(B) Voice input:$0.065/分鐘;(C) Voice output:$0.0065/字元。500 DAU × 10 rounds/day = 5,000 requests/day × 30 days = 150,000/month → 前 15,000 免費 + 付費 135,000 × $0.002 = $270/月。(2) Dialogflow CX 定價——(A) Text:$0.007 per request(無免費額度);(B) Voice input:$0.06/分鐘;(C) Voice output:同 ES。同樣 500 DAU × 10 rounds/day → 150,000 requests × $0.007 = $1,050/月。(3) 額外費用——(A) Vertex AI fulfillment(如果用了 generative features)—— 每次 LLM 呼叫 $0.001–0.005;(B) Webhook 運行費(Cloud Run)——可能 $20–200/月;(C) 資料儲存(Firestore)——$20–100/月;(D) Cloud Logging——$10–50/月。總 TCO:ES 500 DAU 約 $300–400/月,CX 500 DAU 約 $1,200–1,500/月。省錢技巧:(1) 分類 intents——免費方案的 quota 不要浪費在 low-value 閒聊上;(2) 用 entity 不要 regex——省 training 時間;(3) fulfillment 加 cache——常見查詢(如「營業時間」)的結果 cache,avoid 每次都打 DB;(4) 監控哪些 intent 被濫用——有人用 bot 玩就限制。
下一步
掌握 Fulfillment 開發後,你可以:
- 優化對話設計:Dialogflow Intent 與 Context 完整教學
- 學習 CX 版本:Dialogflow CX 教學:從入門到進階
- 整合 LINE Bot:Dialogflow LINE Bot 串接教學
- 行動 App 整合:Dialogflow 行動開發整合教學
後端整合需要協助?
好的後端架構能讓系統穩定、安全、易於擴展。不好的架構會在流量增加時出問題,或成為資安漏洞。
如果你需要:
- 設計可擴展的 Webhook 架構
- 整合複雜的企業系統
- 處理高流量場景
- 確保資安合規
預約架構諮詢,讓有經驗的工程師幫你設計穩健的後端架構。
諮詢完全免費,我們會在 24 小時內回覆。
相關文章
Dialogflow CX vs ES 完整比較:2026 版本選擇指南
Dialogflow CX 和 ES 到底差在哪?本文詳細比較功能、費用、適用場景,附決策流程圖,幫你選對版本不踩雷、不花冤枉錢。
DialogflowDialogflow 完整指南 2026:從入門到實戰的 AI 對話機器人開發
完整解析 Google Dialogflow CX 與 ES 版本差異、Generative AI Agents、Vertex AI 整合、費用計算、LINE Bot 整合教學。從零開始打造企業級 AI 客服機器人,含 2026 最新生成式 AI 功能與實戰範例。
DialogflowDialogflow Intent 與 Context 完整教學:打造聰明的多輪對話
深入解析 Dialogflow Intent 意圖設計、Context 上下文管理、Entity 實體擷取。學會設計多輪對話、條件式回應,打造真正聰明的 AI 機器人。