Servicio de webhooks

Para usar entregas en un sistema de producción, debes implementar y aplicar un servicio de webhook. Para administrar la entrega, el servicio webhook debe aceptar solicitudes JSON y mostrar respuestas JSON como se especifica en esta guía. El flujo de procesamiento detallado para las entregas y los webhooks se describe en el documento de descripción general de las entregas.

Requisitos del servicio de webhook

El servicio de webhook debe cumplir con los siguientes requisitos:

  • Debe administrar solicitudes HTTPS. HTTP no es compatible. Si alojas tu servicio de webhook en Google Cloud Platform mediante una solución de Compute o de procesamiento sin servidores, consulta la documentación del producto para la entrega con HTTPS. A fin de conocer otras opciones de hosting, consulta Obtén un certificado SSL para el dominio.
  • La URL para las solicitudes debe ser de acceso público.
  • Debe administrar las solicitudes POST con un cuerpo JSON WebhookRequest.
  • Debe responder a las solicitudes WebhookRequest con un cuerpo JSON WebhookResponse.

Autenticación

Es importante proteger el servicio de webhook para que solo tú o tu agente de Dialogflow estén autorizados a realizar solicitudes. Dialogflow admite los siguientes mecanismos de autenticación:

  • La autenticación básica con acceso y contraseña. Esto se configura cuando se habilita la entrega.
  • La autenticación con encabezados de autenticación. Esto se configura cuando se habilita la entrega.
  • Autenticación mutua de TLS.

Solicitud de webhook

Cuando hay una coincidencia con un intent configurado para la entrega, Dialogflow envía una solicitud POST HTTPS del webhook al servicio de webhook. El cuerpo de esta solicitud es un objeto JSON con información sobre el intent que coincide.

Consulta la documentación de referencia de WebhookRequest para obtener más información.

A continuación, se muestra una solicitud de ejemplo:

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

Respuesta de webhook

Una vez que tu webhook reciba una solicitud, deberá enviar una respuesta de webhook. El cuerpo de esta respuesta es un objeto JSON con la siguiente información:

Se aplican las siguientes limitaciones a tu respuesta:

  • La respuesta debe ocurrir en un plazo de 10 segundos para las aplicaciones del Asistente de Google o de 5 segundos para todas las otras aplicaciones; de lo contrario, se agotará el tiempo de espera de la solicitud.
  • La respuesta debe tener un tamaño menor o igual que 64 KiB.

Consulta la documentación de referencia de WebhookResponse para obtener más información.

Respuesta de texto

Ejemplo de una respuesta de texto:

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

Respuesta de tarjeta

Ejemplo de una respuesta de tarjeta:

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

Respuesta del Asistente de Google

Ejemplo de una respuesta del Asistente de Google:

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

Contexto

Ejemplo que establece el contexto de salida:

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

Ejemplo que invoca un evento personalizado:

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

Entidad de sesión

Ejemplo que establece una entidad de sesión:

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

Habilita y administra la entrega

Si deseas habilitar y administrar la entrega para el agente con la consola, sigue estos pasos:

  1. Ve a la consola de Dialogflow.
  2. Selecciona un agente.
  3. Selecciona Entrega en el menú de la barra lateral izquierda.
  4. Con el botón para activar o desactivar, selecciona Enabled (Habilitado) en el campo Webhook.
  5. Proporciona los detalles del servicio de webhook en el formulario. Si el webhook no requiere autenticación, deja los campos de autenticación en blanco.
  6. Haz clic en Guardar en la parte inferior de la página.

Captura de pantalla de la habilitación de la entrega.

Para habilitar y administrar la entrega del agente con la API, consulta la referencia del agente. Se pueden usar los métodos getFulfillment y updateFulfillment para administrar la configuración de las entregas.

Si deseas habilitar la entrega para un intent con la consola, haz lo siguiente:

  1. En el menú de la barra lateral izquierda, selecciona Intents.
  2. Selecciona un intent.
  3. Desplázate hacia abajo hasta la sección Entrega.
  4. Activa la opción Enable webhook call for this intent.
  5. Haz clic en Guardar.

Si deseas habilitar la entrega para un intent con la API, consulta la referencia de los intents. Configura el campo webhookState como WEBHOOK_STATE_ENABLED.

Errores de webhook

Si el servicio webhook experimenta un error, debería mostrar uno de los siguientes códigos de estado HTTP:

  • 400 Solicitud incorrecta
  • 401 Sin autorización
  • 403 Prohibido
  • 404 No encontrado
  • 500 Falla del servidor
  • 503 Servicio no disponible

En cualquiera de las siguientes situaciones de error, Dialogflow responde al usuario final con la respuesta integrada configurada para el intent que coincide en la actualidad:

  • Se excedió el tiempo de espera de respuesta
  • Código de estado de error recibido
  • La respuesta no es válida
  • El servicio de webhook no está disponible

Además, si la coincidencia del intent se activó mediante una llamada a la API de intents de detección, el campo status en la respuesta de intents de detección contiene la información del error de webhook. Por ejemplo:

"status": {
    "code": 206,
    "errorType": "webhook call failed with %error Code% error"
}

Ejemplos

En el siguiente ejemplo, se muestra cómo recibir una WebhookRequest y enviar una WebhookResponse. En este ejemplo, se hace referencia a intents creados en la guía de inicio rápido.

Go

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
	}
}