如需在生产系统中使用 fulfillment,您必须实现并部署 webhook 服务。如需处理执行方式,您的 webhook 服务必须接受 JSON 请求并返回 JSON 响应,如本指南中所述。Fulfillment 概览文档中介绍了 fulfillment 和 webhook 的详细处理流程。
网络钩子服务要求
您的 webhook 服务必须满足以下要求:
- 处理 HTTPS 请求。不支持 HTTP。如果您使用计算或无服务器计算解决方案在 Google Cloud 上托管 webhook 服务,请参阅产品文档,了解如何使用 HTTPS 提供服务。如需了解其他托管选项,请参阅为网域获取 SSL 证书。
- 确保 webhook 服务网址可公开访问。
- 处理具有 JSON
WebhookRequest正文的 POST 请求。 - 使用 JSON
WebhookResponse正文响应WebhookRequest请求。
身份验证
| X | 项 |
|---|---|
| 登录用户名和密码 | 对于 webhook 设置,您可以指定可选的登录用户名和密码值。如果提供,Dialogflow 会向 webhook 请求添加授权 HTTP 标头。此标头的格式为:"authorization: Basic <base 64 encoding of the string username:password>"。 |
| 身份验证标头 | 对于 webhook 设置,您可以指定可选的 HTTP 标头键值对。如果提供,Dialogflow 会将这些 HTTP 标头添加到 webhook 请求中。通常会提供一个键为 authorization 的键值对。 |
| Cloud Run functions 内置身份验证 | 使用 Cloud Run functions 时,您可以使用内置身份验证。如需使用此类型的身份验证,请勿提供用户名、密码或授权标头。如果您提供其中任何字段,这些字段都不会用于内置身份验证。 |
| 服务身份令牌 | 您可以使用服务身份令牌进行身份验证。如果您未提供登录用户名、登录密码或键为 authorization 的标头,Dialogflow 会自动假定应使用服务身份令牌,并向网络钩子请求添加授权 HTTP 标头。此标头的格式为:"authorization: Bearer <identity token>"。 |
| 双向 TLS 身份验证 | 请参阅双向 TLS 身份验证文档。 |
网络钩子请求
当配置为执行方式的 intent 匹配时,Dialogflow 会向您的 webhook 服务发送 HTTPS POST webhook 请求。此请求的正文是一个 JSON 对象,其中包含有关匹配 intent 的信息。
除了最终用户查询之外,许多集成还会发送有关最终用户的信息。例如,唯一标识用户的 ID。您可以使用 webhook 请求中的 originalDetectIntentRequest 字段访问此信息,该字段包含从集成平台发送的信息。
如需了解详情,请参阅 WebhookRequest 参考文档。
以下是一个请求示例:
{
"responseId": "response-id",
"session": "projects/project-id/agent/sessions/session-id",
"queryResult": {
"queryText": "End-user expression",
"parameters": {
"param-name": "param-value"
},
"allRequiredParamsPresent": true,
"fulfillmentText": "Response configured for matched intent",
"fulfillmentMessages": [
{
"text": {
"text": [
"Response configured for matched intent"
]
}
}
],
"outputContexts": [
{
"name": "projects/project-id/agent/sessions/session-id/contexts/context-name",
"lifespanCount": 5,
"parameters": {
"param-name": "param-value"
}
}
],
"intent": {
"name": "projects/project-id/agent/intents/intent-id",
"displayName": "matched-intent-name"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": "en"
},
"originalDetectIntentRequest": {}
}
网络钩子响应
Webhook 收到请求后,必须发送响应。此响应的正文是一个 JSON 对象,其中包含以下信息:
您的响应会受到以下限制:
- 对于 Google 助理应用,请在 10 秒内响应;对于其他应用,请在 5 秒内响应;否则,请求会超时。
- 将响应大小控制在 64 KiB 或以下。
如需了解详情,请参阅 WebhookResponse 参考文档。
文本响应
以下是文本回答的示例:
{
"fulfillmentMessages": [
{
"text": {
"text": [
"Text response from webhook"
]
}
}
]
}
卡片响应
以下是卡片回答的示例:
{
"fulfillmentMessages": [
{
"card": {
"title": "card title",
"subtitle": "card text",
"imageUri": "https://example.com/images/example.png",
"buttons": [
{
"text": "button text",
"postback": "https://example.com/path/for/end-user/to/follow"
}
]
}
}
]
}
Google 助理响应
以下是 Google 助理回答的示例:
{
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "this is a Google Assistant response"
}
}
]
}
}
}
}
上下文
以下是设置输出上下文的示例:
{
"fulfillmentMessages": [
{
"text": {
"text": [
"Text response from webhook"
]
}
}
],
"outputContexts": [
{
"name": "projects/project-id/agent/sessions/session-id/contexts/context-name",
"lifespanCount": 5,
"parameters": {
"param-name": "param-value"
}
}
]
}
事件
以下是调用自定义事件的示例:
{
"followupEventInput": {
"name": "event-name",
"languageCode": "en-US",
"parameters": {
"param-name": "param-value"
}
}
}
会话实体
以下是设置会话实体的示例:
{
"fulfillmentMessages": [
{
"text": {
"text": [
"Choose apple or orange"
]
}
}
],
"sessionEntityTypes":[
{
"name":"projects/project-id/agent/sessions/session-id/entityTypes/fruit",
"entities":[
{
"value":"APPLE_KEY",
"synonyms":[
"apple",
"green apple",
"crabapple"
]
},
{
"value":"ORANGE_KEY",
"synonyms":[
"orange"
]
}
],
"entityOverrideMode":"ENTITY_OVERRIDE_MODE_OVERRIDE"
}
]
}
自定义负载
以下是提供自定义载荷的示例:
{
"fulfillmentMessages": [
{
"payload": {
"facebook": { // for Facebook Messenger integration
"attachment": {
"type": "",
"payload": {}
}
},
"slack": { // for Slack integration
"text": "",
"attachments": []
},
"richContent": [ // for Dialogflow Messenger integration
[
{
"type": "image",
"rawUrl": "https://example.com/images/logo.png",
"accessibilityText": "Example logo"
}
]
],
// custom integration payload here
}
}
]
}
启用和管理 fulfillment
如需通过控制台为您的代理启用和管理 fulfillment,请执行以下操作:
- 前往 Dialogflow ES 控制台。
- 选择一个代理。
- 在边栏菜单中选择配送。
- 将网路钩子字段切换为已启用。
- 在表单中提供 Webhook 服务的详细信息。如果您的 webhook 不需要身份验证,请将身份验证字段留空。
- 点击保存。

如需使用 API 为代理启用和管理 fulfillment,请参阅代理参考文档。您可以使用 getFulfillment 和 updateFulfillment 方法管理履单设置。
如需通过控制台为意图启用 fulfillment,请执行以下操作:
- 在左侧边栏菜单中选择意图 (Intents)。
- 选择一个意图。
- 前往履单部分。
- 将为此 intent 启用 webhook 调用切换为“开启”。
- 点击保存。
如需使用 API 为 intent 启用 fulfillment,请参阅 intent 参考文档并将 webhookState 字段设置为 WEBHOOK_STATE_ENABLED。
网络钩子错误
如果您的网络钩子服务遇到错误,则应返回以下 HTTP 状态代码之一:
400:请求有误401:未经授权403:禁止访问404:未找到500:内部服务器错误503:服务不可用
在以下任何错误情况下,Dialogflow 都会使用为匹配的 intent 配置的内置回答来回复最终用户:
- 已超过响应超时时间。
- 收到错误状态代码。
- 回答无效。
- Webhook 服务不可用。
此外,如果检测 intent API 调用触发了 intent 匹配,则检测 intent 响应中的 status 字段会包含网络钩子错误信息。例如:
"status": {
"code": 206,
"message": "Webhook call failed. <details of the error...>"
}
自动重试
Dialogflow ES 包含内部机制,可在发生某些网络钩子错误时自动重试,以提高稳健性。系统只会重试非终止错误,例如超时或连接错误。
为降低重复调用的可能性,请执行以下操作:
- 设置更长的 webhook 超时阈值。
- 在 webhook 逻辑中支持幂等性或对请求进行去重。
使用 Cloud Run functions
您可以通过多种方式使用 Cloud Run functions 进行执行。Dialogflow 内嵌编辑器与 Cloud Run functions 集成。当您使用内嵌编辑器创建和修改 webhook 代码时,Dialogflow 会建立与 Cloud Function 的安全连接。
您也可以使用并非由内嵌编辑器创建的 Cloud Function。如果 Cloud Function 与您的代理位于同一项目中,则您的代理无需任何特殊配置即可调用 webhook。
不过,在以下两种情况下,您必须手动设置此集成:
- 您的代理项目必须存在具有以下地址的 Dialogflow Service Agent 服务账号:
当您为项目创建第一个代理时,系统通常会自动创建此特殊服务账号和关联的密钥。如果您的代理是在 2021 年 5 月 10 日之前创建的,您可能需要通过以下方式触发此特殊服务账号的创建:service-agent-project-number@gcp-sa-dialogflow.iam.gserviceaccount.com
- 为项目创建新的代理。
- 执行以下命令:
gcloud beta services identity create --service=dialogflow.googleapis.com --project=agent-project-id
- 如果您的 webhook 函数与代理位于不同的项目中,则必须向函数项目中的 Dialogflow Service Agent 服务账号提供 Cloud Functions Invoker IAM 角色。
服务身份令牌
当 Dialogflow 调用网络钩子时,它会在请求中提供 Google Identity 令牌。任何 webhook 都可以选择使用 Google 客户端库或开源库(例如 github.com/googleapis/google-auth-library-nodejs)来验证令牌。例如,您可以按以下方式验证 ID 令牌的 email:
service-agent-project-number@gcp-sa-dialogflow.iam.gserviceaccount.com
示例
以下示例展示了如何接收 WebhookRequest 和发送 WebhookResponse。这些示例使用在快速入门中创建的 intent。
Go
如需向 Dialogflow CX 进行身份验证,请设置应用默认凭据。如需了解详情,请参阅为本地开发环境设置身份验证。
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
type intent struct {
DisplayName string `json:"displayName"`
}
type queryResult struct {
Intent intent `json:"intent"`
}
type text struct {
Text []string `json:"text"`
}
type message struct {
Text text `json:"text"`
}
// webhookRequest is used to unmarshal a WebhookRequest JSON object. Note that
// not all members need to be defined--just those that you need to process.
// As an alternative, you could use the types provided by
// the Dialogflow protocol buffers:
// https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookRequest
type webhookRequest struct {
Session string `json:"session"`
ResponseID string `json:"responseId"`
QueryResult queryResult `json:"queryResult"`
}
// webhookResponse is used to marshal a WebhookResponse JSON object. Note that
// not all members need to be defined--just those that you need to process.
// As an alternative, you could use the types provided by
// the Dialogflow protocol buffers:
// https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookResponse
type webhookResponse struct {
FulfillmentMessages []message `json:"fulfillmentMessages"`
}
// welcome creates a response for the welcome intent.
func welcome(request webhookRequest) (webhookResponse, error) {
response := webhookResponse{
FulfillmentMessages: []message{
{
Text: text{
Text: []string{"Welcome from Dialogflow Go Webhook"},
},
},
},
}
return response, nil
}
// getAgentName creates a response for the get-agent-name intent.
func getAgentName(request webhookRequest) (webhookResponse, error) {
response := webhookResponse{
FulfillmentMessages: []message{
{
Text: text{
Text: []string{"My name is Dialogflow Go Webhook"},
},
},
},
}
return response, nil
}
// handleError handles internal errors.
func handleError(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "ERROR: %v", err)
}
// HandleWebhookRequest handles WebhookRequest and sends the WebhookResponse.
func HandleWebhookRequest(w http.ResponseWriter, r *http.Request) {
var request webhookRequest
var response webhookResponse
var err error
// Read input JSON
if err = json.NewDecoder(r.Body).Decode(&request); err != nil {
handleError(w, err)
return
}
log.Printf("Request: %+v", request)
// Call intent handler
switch intent := request.QueryResult.Intent.DisplayName; intent {
case "Default Welcome Intent":
response, err = welcome(request)
case "get-agent-name":
response, err = getAgentName(request)
default:
err = fmt.Errorf("Unknown intent: %s", intent)
}
if err != nil {
handleError(w, err)
return
}
log.Printf("Response: %+v", response)
// Send response
if err = json.NewEncoder(w).Encode(&response); err != nil {
handleError(w, err)
return
}
}
Java
如需向 Dialogflow CX 进行身份验证,请设置应用默认凭据。如需了解详情,请参阅为本地开发环境设置身份验证。
Node.js
如需向 Dialogflow CX 进行身份验证,请设置应用默认凭据。如需了解详情,请参阅为本地开发环境设置身份验证。
Python
如需向 Dialogflow CX 进行身份验证,请设置应用默认凭据。如需了解详情,请参阅为本地开发环境设置身份验证。