Service de webhook

Pour utiliser le fulfillment dans un système de production, vous devez implémenter et déployer un service de webhook. Pour gérer le traitement, votre service de webhook doit accepter les requêtes JSON et renvoyer les réponses JSON comme spécifié dans ce guide. Le flux de traitement détaillé pour le fulfillment et les webhooks est décrit dans le document Présentation du fulfillment.

Conditions requises pour le service de webhook

Votre service de webhook doit répondre aux exigences suivantes :

  • Gérer les requêtes HTTPS Le protocole HTTP n'est pas compatible. Si vous hébergez votre service de webhook sur Google Cloud à l'aide d'une solution de calcul ou d'informatique sans serveur, consultez la documentation du produit pour la diffusion avec HTTPS. Pour connaître les autres options d'hébergement, consultez Obtenir un certificat SSL pour votre domaine.
  • Assurez-vous que l'URL du service de webhook est accessible publiquement.
  • Gérer les requêtes POST avec un corps JSON WebhookRequest.
  • Répondez aux requêtes WebhookRequest avec un corps JSON WebhookResponse.

Authentification

X Élément
Nom d'utilisateur et mot de passe de connexion Pour les paramètres de webhook, vous pouvez spécifier des valeurs facultatives de nom d'utilisateur et de mot de passe de connexion. S'il est fourni, Dialogflow ajoute un en-tête HTTP d'autorisation aux requêtes de webhook. Cet en-tête se présente sous la forme suivante : "authorization: Basic <base 64 encoding of the string username:password>".
En-têtes d'authentification Pour les paramètres de webhook, vous pouvez spécifier des paires clé/valeur d'en-tête HTTP facultatives. S'ils sont fournis, Dialogflow ajoute ces en-têtes HTTP aux requêtes de webhook. Il est courant de fournir une seule paire avec une clé de authorization.
Authentification intégrée de Cloud Run Functions Vous pouvez utiliser l'authentification intégrée lorsque vous utilisez Cloud Run Functions. Pour utiliser ce type d'authentification, ne fournissez pas de nom d'utilisateur, de mot de passe ni d'en-têtes d'autorisation. Si vous fournissez l'un de ces champs, il ne sera pas utilisé pour l'authentification intégrée.
Jetons d'identité du service Vous pouvez utiliser des jetons d'identité de service pour l'authentification. Si vous ne fournissez pas de nom d'utilisateur, de mot de passe ou d'en-tête avec une clé authorization, Dialogflow suppose automatiquement que les jetons d'identité de service doivent être utilisés et ajoute un en-tête HTTP d'autorisation aux requêtes de webhook. Cet en-tête se présente sous la forme suivante : "authorization: Bearer <identity token>".
Authentification TLS mutuelle Consultez la documentation sur l'authentification TLS mutuelle.

Requête de webhook

Lorsqu'un intent configuré pour le fulfillment est mis en correspondance, Dialogflow envoie une requête de webhook HTTPS POST à votre service de webhook. Le corps de cette requête est un objet JSON contenant des informations sur l'intent correspondant.

En plus de la requête de l'utilisateur final, de nombreuses intégrations envoient également des informations sur l'utilisateur final. Par exemple, un ID qui identifie l'utilisateur de manière unique. Ces informations sont accessibles à l'aide du champ originalDetectIntentRequest de la requête de webhook, qui contient les informations envoyées par la plate-forme d'intégration.

Pour en savoir plus, consultez la documentation de référence sur WebhookRequest.

Voici un exemple de requête :

{
  "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": {}
}

Réponse de webhook

Une fois que votre webhook reçoit une requête, il doit envoyer une réponse. Le corps de cette réponse est un objet JSON contenant les informations suivantes :

Les limites suivantes s'appliquent à votre réponse :

  • Répondez dans un délai de 10 secondes pour les applications de l'Assistant Google ou de 5 secondes pour les autres applications. Sinon, la requête expire.
  • La taille de la réponse ne doit pas dépasser 64 Kio.

Pour en savoir plus, consultez la documentation de référence sur WebhookResponse.

Réponse textuelle

Voici un exemple de réponse textuelle :

{
  "fulfillmentMessages": [
    {
      "text": {
        "text": [
          "Text response from webhook"
        ]
      }
    }
  ]
}

Réponse sous forme de fiche

Voici un exemple de réponse de fiche :

{
  "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"
          }
        ]
      }
    }
  ]
}

Réponse de l'Assistant Google

Voici un exemple de réponse de l'Assistant Google :

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "this is a Google Assistant response"
            }
          }
        ]
      }
    }
  }
}

Contexte

Voici un exemple qui définit le contexte de sortie :

{
  "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"
      }
    }
  ]
}

Événement

Voici un exemple qui appelle un événement personnalisé :

{
  "followupEventInput": {
    "name": "event-name",
    "languageCode": "en-US",
    "parameters": {
      "param-name": "param-value"
    }
  }
}

Entité de session

Voici un exemple qui définit une entité de session :

{
  "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"
    }
  ]
}

Charge utile personnalisée

Voici un exemple qui fournit une charge utile personnalisée :

{
  "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
      }
    }
  ]
}

Activer et gérer le fulfillment

Pour activer et gérer le fulfillment pour votre agent à l'aide de la console, procédez comme suit :

  1. Accédez à la console Dialogflow ES.
  2. Sélectionnez un agent.
  3. Sélectionnez Fulfillment dans le menu de la barre latérale.
  4. Définissez le champ Webhook sur Enabled (Activé).
  5. Fournissez les détails de votre service de webhook dans le formulaire. Si votre webhook ne nécessite pas d'authentification, laissez les champs d'authentification vides.
  6. Cliquez sur Enregistrer.

Capture d'écran de l'activation du fulfillment.

Pour activer et gérer le fulfillment pour votre agent avec l'API, consultez la documentation de référence sur les agents. Les méthodes getFulfillment et updateFulfillment vous permettent de gérer les paramètres de traitement.

Pour activer le fulfillment pour un intent avec la console, procédez comme suit :

  1. Cliquez sur Intents dans le menu de la barre latérale gauche.
  2. Sélectionnez un intent.
  3. Accédez à la section Fulfillment.
  4. Activez l'option Enable webhook call for this intent (Activer l'appel de webhook pour cet intent).
  5. Cliquez sur Enregistrer.

Pour activer le fulfillment pour un intent avec l'API, consultez la documentation de référence sur les intents et définissez le champ webhookState sur WEBHOOK_STATE_ENABLED.

Erreurs de webhook

Si votre service de webhook rencontre une erreur, il doit renvoyer l'un des codes d'état HTTP suivants :

  • 400 : requête incorrecte
  • 401 : non autorisé
  • 403 : Action interdite
  • 404 : introuvable
  • 500 : erreur interne du serveur
  • 503 : Service non disponible

Dans l'un des cas d'erreur suivants, Dialogflow répond à l'utilisateur final avec la réponse intégrée configurée pour l'intent correspondant :

  • Le délai avant expiration de la réponse a été dépassé.
  • Un code d'état d'erreur a été reçu.
  • La réponse n'est pas valide.
  • Le service de webhook n'est pas disponible.

De plus, si un appel d'API de détection d'intent déclenche la correspondance d'intent, le champ status de la réponse de détection d'intent contient les informations sur l'erreur de webhook. Exemple :

"status": {
    "code": 206,
    "message": "Webhook call failed. <details of the error...>"
}

Nouvelles tentatives automatiques

Dialogflow ES inclut des mécanismes internes qui relancent automatiquement certaines erreurs de webhook pour améliorer la robustesse. Seules les erreurs non terminales sont relancées, telles que les erreurs de délai avant expiration ou de connexion.

Pour réduire le risque d'appels en double :

  • Définissez des seuils de délai avant expiration plus longs pour les webhooks.
  • Prenez en charge l'idempotence dans votre logique de webhook ou dédupliquez les requêtes.

Utiliser Cloud Run Functions

Vous pouvez utiliser Cloud Run Functions pour le traitement de plusieurs manières. L'éditeur intégré de Dialogflow s'intègre à Cloud Run Functions. Lorsque vous utilisez l'éditeur intégré pour créer et modifier votre code de webhook, Dialogflow établit une connexion sécurisée à votre fonction Cloud.

Vous pouvez également utiliser une fonction Cloud qui n'a pas été créée par l'éditeur intégré. Si la fonction Cloud Functions réside dans le même projet que votre agent, celui-ci peut appeler votre webhook sans configuration particulière.

Toutefois, vous devez configurer manuellement cette intégration dans les deux situations suivantes :

  1. Le compte de service Agent de service Dialogflow avec l'adresse suivante doit exister pour votre projet d'agent :
    service-agent-project-number@gcp-sa-dialogflow.iam.gserviceaccount.com
    Ce compte de service spécial et la clé associée sont normalement créés automatiquement lorsque vous créez le premier agent d'un projet. Si votre agent a été créé avant le 10 mai 2021, vous devrez peut-être déclencher la création de ce compte de service spécial en procédant comme suit :
    1. Créez un agent pour le projet.
    2. Exécutez la commande suivante :
      gcloud beta services identity create --service=dialogflow.googleapis.com --project=agent-project-id
  2. Si votre fonction de webhook réside dans un projet différent de celui de l'agent, vous devez attribuer le rôle IAM Demandeur Cloud Functions au compte de service Agent de service Dialogflow dans le projet de votre fonction.

Jetons d'identité du service

Lorsque Dialogflow appelle un webhook, il fournit un jeton d'identité Google avec la requête. Tout webhook peut éventuellement valider le jeton à l'aide des bibliothèques clientes Google ou de bibliothèques Open Source telles que github.com/googleapis/google-auth-library-nodejs. Par exemple, vous pouvez valider le email du jeton d'ID comme suit :

service-agent-project-number@gcp-sa-dialogflow.iam.gserviceaccount.com

Exemples

Les exemples suivants montrent comment recevoir un WebhookRequest et envoyer un WebhookResponse. Ces exemples utilisent des intents créés dans le guide de démarrage rapide.

Go

Pour vous authentifier auprès de Dialogflow CX, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

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

Pour vous authentifier auprès de Dialogflow CX, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.


// TODO: add GSON dependency to Pom file
// (https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5)
// TODO: Uncomment the line bellow before running cloud function
// package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedWriter;

public class Example implements HttpFunction {

  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonParser parser = new JsonParser();
    Gson gson = new GsonBuilder().create();

    JsonObject job = gson.fromJson(request.getReader(), JsonObject.class);
    String str =
        job.getAsJsonObject("queryResult")
            .getAsJsonObject("intent")
            .getAsJsonPrimitive("displayName")
            .toString();
    JsonObject o = null;
    String a = '"' + "Default Welcome Intent" + '"';
    String b = '"' + "get-agent-name" + '"';
    String responseText = "";

    if (str.equals(a)) {
      responseText = '"' + "Hello from a Java GCF Webhook" + '"';
    } else if (str.equals(b)) {
      responseText = '"' + "My name is Flowhook" + '"';
    } else {
      responseText = '"' + "Sorry I didn't get that" + '"';
    }

    o =
        parser
            .parse(
                "{\"fulfillmentMessages\": [ { \"text\": { \"text\": [ "
                    + responseText
                    + " ] } } ] }")
            .getAsJsonObject();

    BufferedWriter writer = response.getWriter();
    writer.write(o.toString());
  }
}

Node.js

Pour vous authentifier auprès de Dialogflow CX, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

const functions = require('@google-cloud/functions-framework');

// TODO: Add handleWebhook to 'Entry point' in the Google Cloud Function
functions.http('handleWebhook', (request, response) => {
  const tag = request.body.queryResult.intent.displayName;

  let jsonResponse = {};
  if (tag === 'Default Welcome Intent') {
    //fulfillment response to be sent to the agent if the request tag is equal to "welcome tag"
    jsonResponse = {
      fulfillment_messages: [
        {
          text: {
            //fulfillment text response to be sent to the agent
            text: ['Hello from a GCF Webhook'],
          },
        },
      ],
    };
  } else if (tag === 'get-name') {
    //fulfillment response to be sent to the agent if the request tag is equal to "welcome tag"
    jsonResponse = {
      fulfillment_messages: [
        {
          text: {
            //fulfillment text response to be sent to the agent
            text: ['My name is Flowhook'],
          },
        },
      ],
    };
  } else {
    jsonResponse = {
      //fulfillment text response to be sent to the agent if there are no defined responses for the specified tag
      fulfillment_messages: [
        {
          text: {
            ////fulfillment text response to be sent to the agent
            text: [
              `There are no fulfillment responses defined for "${tag}"" tag`,
            ],
          },
        },
      ],
    };
  }
  response.send(jsonResponse);
});

Python

Pour vous authentifier auprès de Dialogflow CX, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

# TODO: change the default Entry Point text to handleWebhook
import functions_framework


@functions_framework.http
def handleWebhook(request):
    req = request.get_json()

    responseText = ""
    intent = req["queryResult"]["intent"]["displayName"]

    if intent == "Default Welcome Intent":
        responseText = "Hello from a GCF Webhook"
    elif intent == "get-agent-name":
        responseText = "My name is Flowhook"
    else:
        responseText = f"There are no fulfillment responses defined for Intent {intent}"

    # You can also use the google.cloud.dialogflowcx_v3.types.WebhookRequest protos instead of manually writing the json object
    res = {"fulfillmentMessages": [{"text": {"text": [responseText]}}]}

    return res