Serviço de webhook

Para usar o processamento de pedidos num sistema de produção, deve implementar e implementar um serviço de webhook. Para processar o preenchimento, o seu serviço de webhook tem de aceitar pedidos JSON e devolver respostas JSON, conforme especificado neste guia. O fluxo de processamento detalhado para o processamento de pedidos e os webhooks é descrito no documento de vista geral do processamento de pedidos.

Requisitos do serviço de webhook

O seu serviço de webhook tem de cumprir os seguintes requisitos:

  • Tem de processar pedidos HTTPS. O HTTP não é suportado. Se alojar o seu serviço de webhook na Google Cloud Platform através de uma solução de computação ou computação sem servidor, consulte a documentação do produto para a publicação com HTTPS. Para outras opções de alojamento, consulte o artigo Obtenha um certificado SSL para o seu domínio.
  • O respetivo URL para pedidos tem de ser acessível publicamente.
  • Tem de processar pedidos POST com um corpo JSON WebhookRequest.
  • Tem de responder a pedidos WebhookRequest com um corpo JSON WebhookResponse.

Autenticação

É importante proteger o seu serviço de webhook, para que apenas o seu agente Dialogflow ou você tenha autorização para fazer pedidos. O Dialogflow suporta os seguintes mecanismos de autenticação:

Vigência Definição
Nome de utilizador e palavra-passe de início de sessão Para as definições de webhook, pode especificar valores de nome de utilizador e palavra-passe de início de sessão opcionais. Se fornecido, o Dialogflow adiciona um cabeçalho HTTP de autorização aos pedidos de webhook. Este cabeçalho tem o seguinte formato: "authorization: Basic <base 64 encoding of the string username:password>".
Cabeçalhos de autenticação Para as definições de webhook, pode especificar pares de chave-valor de cabeçalho HTTP opcionais. Se forem fornecidos, o Dialogflow adiciona estes cabeçalhos HTTP aos pedidos de webhook. É comum fornecer um único par com uma chave de authorization.
Autenticação incorporada do Cloud Functions Pode usar a autenticação incorporada quando usar as Cloud Functions. Para usar este tipo de autenticação, não forneça o nome de utilizador de início de sessão, a palavra-passe de início de sessão nem os cabeçalhos de autorização. Se fornecer algum destes campos, estes campos são usados para a autenticação em vez da autenticação incorporada.
Tokens de identidade de serviço Pode usar tokens de identidade de serviço para autenticação. Se não fornecer o nome de utilizador de início de sessão, a palavra-passe de início de sessão ou um cabeçalho com uma chave de authorization, o Dialogflow assume automaticamente que devem ser usados tokens de identidade do serviço e adiciona um cabeçalho HTTP de autorização aos pedidos de webhook. Este cabeçalho tem o seguinte formato: "authorization: Bearer <identity token>".
Autenticação TLS mútua Consulte a documentação sobre a autenticação TLS mútua.

Pedido de webhook

Quando uma intenção configurada para o preenchimento é correspondida, o Dialogflow envia um pedido de webhook HTTPS POST para o seu serviço de webhook. O corpo deste pedido é um objeto JSON com informações sobre a intenção correspondente.

Além da consulta do utilizador final, muitas integrações também enviam algumas informações sobre o utilizador final. Por exemplo, um ID para identificar exclusivamente o utilizador. Pode aceder a estas informações através do campo originalDetectIntentRequest no pedido de webhook, que contém as informações enviadas a partir da plataforma de integração.

Consulte a WebhookRequest documentação de referência para ver detalhes.

Segue-se um pedido de exemplo:

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

Resposta do webhook

Assim que o webhook receber um pedido de webhook, tem de enviar uma resposta de webhook. O corpo desta resposta é um objeto JSON com as seguintes informações:

As seguintes limitações aplicam-se à sua resposta:

  • A resposta tem de ocorrer no prazo de 10 segundos para aplicações do Assistente Google ou 5 segundos para todas as outras aplicações. Caso contrário, o pedido vai expirar.
  • A resposta tem de ter um tamanho inferior ou igual a 64 KiB.

Consulte a WebhookResponse documentação de referência para ver detalhes.

Resposta de texto

Exemplo de uma resposta de texto:

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

Resposta do cartão

Exemplo de uma resposta de cartão:

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

Resposta do Assistente Google

Exemplo de uma resposta do Assistente Google:

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

Contexto

Exemplo que define o contexto de saída:

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

Evento

Exemplo que invoca um evento personalizado:

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

Entidade de sessão

Exemplo que define uma entidade de sessão:

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

Payload personalizado

Exemplo que fornece um payload personalizado:

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

Ative e faça a gestão do processamento

Para ativar e gerir o processamento para o seu agente com a consola:

  1. Aceda à consola do Dialogflow ES.
  2. Selecione um agente.
  3. Selecione Preenchimento no menu da barra lateral do lado esquerdo.
  4. Ative o campo Webhook.
  5. Faculte os detalhes do seu serviço de webhook no formulário. Se o seu webhook não exigir autenticação, deixe os campos de autenticação em branco.
  6. Clique em Guardar na parte inferior da página.

Captura de ecrã da ativação do processamento.

Para ativar e gerir o processamento do seu agente com a API, consulte a referência do agente. Os métodos getFulfillment e updateFulfillment podem ser usados para gerir as definições de processamento.

Para ativar o processamento de um objetivo com a consola:

  1. Selecione Intenções no menu da barra lateral esquerda.
  2. Selecione uma intenção.
  3. Desloque a página para baixo até à secção Cumprimento.
  4. Ative a opção Ativar chamada de webhook para este objetivo.
  5. Clique em Guardar.

Para ativar o processamento de um objetivo com a API, consulte a referência de objetivos. Defina o campo webhookState como WEBHOOK_STATE_ENABLED.

Erros de webhook

Se o seu serviço de webhook encontrar um erro, deve devolver um dos seguintes códigos de estado HTTP:

  • 400 Pedido incorreto
  • 401 Não autorizado
  • 403 Proibido
  • 404 Não encontrado
  • 500 Falha do servidor
  • 503 Serviço indisponível

Em qualquer uma das seguintes situações de erro, o Dialogflow responde ao utilizador final com a resposta incorporada configurada para a intenção atualmente correspondente:

  • Tempo limite de resposta excedido.
  • Código de estado de erro recebido.
  • A resposta é inválida.
  • O serviço de webhook está indisponível.

Além disso, se a correspondência de intenção tiver sido acionada por uma chamada da API detect intent, o campo status na resposta da API detect intent contém as informações de erro do webhook. Por exemplo:

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

Novas tentativas automáticas

O Dialogflow ES inclui mecanismos internos que repetem automaticamente em determinados erros de webhook para melhorar a robustez. Só são repetidos os erros não terminais (por exemplo, erros de limite de tempo ou de ligação).

Para reduzir a probabilidade de chamadas duplicadas:

  • Defina limites de tempo limite de webhook mais longos.
  • Suporte a idempotência na lógica do webhook ou remova duplicados.

Usar o Cloud Functions

Existem algumas formas de usar as Cloud Functions para o processamento de pedidos. O editor inline do Dialogflow integra-se com as funções do Google Cloud. Quando usa o editor inline para criar e editar o código do webhook, o Dialogflow estabelece uma ligação segura à sua função do Google Cloud.

Também tem a opção de usar uma função do Cloud não criada pelo editor inline (talvez porque quer usar um idioma que não seja o Node.js). Se a função do Google Cloud residir no mesmo projeto que o seu agente, o agente pode chamar o webhook sem precisar de nenhuma configuração especial.

No entanto, existem duas situações em que tem de configurar manualmente esta integração:

  1. A conta de serviço do agente de serviço do Dialogflow com o seguinte endereço tem de existir para o projeto do seu agente:
    service-agent-project-number@gcp-sa-dialogflow.
    Esta conta de serviço especial e a chave associada são normalmente criadas automaticamente quando cria o primeiro agente para um projeto. Se o seu agente foi criado antes de 10 de maio de 2021, pode ter de acionar a criação desta conta de serviço especial com o seguinte:
    1. Crie um novo agente para o projeto.
    2. Execute o seguinte comando:
      gcloud beta services identity create --service=dialogflow.googleapis.com --project=agent-project-id
  2. Se a função de webhook residir num projeto diferente do agente, tem de fornecer a função do IAM do invocador das Cloud Functions à conta de serviço do agente de serviço do Dialogflow no projeto da sua função.

Tokens de identidade de serviço

Quando o Dialogflow chama um webhook, fornece um token de identidade Google com o pedido. Qualquer webhook pode, opcionalmente, validar o token através de bibliotecas de cliente Google ou bibliotecas de código aberto, como github.com/googleapis/google-auth-library-nodejs. Por exemplo, pode validar o email do token de ID da seguinte forma:

service-agent-project-number@gcp-sa-dialogflow.

Amostras

Os exemplos seguintes mostram como receber um WebhookRequest e enviar um WebhookResponse. Estes exemplos fazem referência a intenções criadas no início rápido.

Go

Para se autenticar no Dialogflow, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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

Para se autenticar no Dialogflow, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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

Para se autenticar no Dialogflow, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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

Para se autenticar no Dialogflow, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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