Implementar webhooks

Este guia oferece vários exemplos de implementação de webhooks e recomendações de solução de problemas.

Definir um parâmetro de sessão

Os exemplos a seguir mostram como definir um parâmetro de sessão.

Go

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Consulte o guia de início rápido dos webhooks.

Java

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// TODO: Change class name to Example
// TODO: Uncomment the line below 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 java.io.BufferedWriter;

public class WebhookConfigureSessionParameters implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject orderParameter = new JsonObject();
    orderParameter.addProperty("order_number", "12345");

    JsonObject parameterObject = new JsonObject();
    parameterObject.add("parameters", orderParameter);

    // Creates webhook response object
    JsonObject webhookResponse = new JsonObject();
    webhookResponse.add("session_info", parameterObject);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonResponseObject = gson.toJson(webhookResponse);

    /** { "session_info": { "parameters": { "order_number": "12345" } } } */
    BufferedWriter writer = response.getWriter();
    // Sends the webhookResponseObject
    writer.write(jsonResponseObject.toString());
  }
}

Node.js

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

functions.http('configureSessionParams', (request, response) => {
  // Session parameter configured by the webhook
  const orderNumber = 123;

  const jsonResponse = {
    sessionInfo: {
      parameters: {
        orderNumber: orderNumber,
      },
    },
  };

  response.send(jsonResponse);
});

Python

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import functions_framework

# TODO (developer): change entry point to configure_session_params in Cloud Function


@functions_framework.http
def configure_session_params(request):
    """Webhook to validate or configure new session parameters."""

    order_number = 123

    json_response = {
        "sessionInfo": {
            "parameters": {
                "orderNumber": order_number,
            },
        },
    }

    return json_response

Retornar uma resposta de fulfillment

Os exemplos a seguir mostram como retornar uma resposta de fulfillment.

Go

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Consulte o guia de início rápido dos webhooks.

Java

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// TODO: Change class name to Example
// 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 BasicWebhook implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    Gson gson = new GsonBuilder().create();
    JsonObject parsedRequest = gson.fromJson(request.getReader(), JsonObject.class);

    // For more information on the structure of this object https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/Fulfillment
    String requestTag = parsedRequest.getAsJsonObject("fulfillmentInfo")
        .getAsJsonPrimitive("tag").toString();
    JsonObject responseObject = null;
    String defaultIntent = "\"Default Welcome Intent\"";
    String secondIntent = "\"get-agent-name\"";
    String responseText = "";

    // Compares the Intent Tag to provide the correct response 
    if (requestTag.equals(defaultIntent)) {
      responseText = "\"Hello from a Java GCF Webhook\"";
    } else if (requestTag.equals(secondIntent)) {
      responseText = "\"My name is Flowhook\"";
    } else {
      responseText = "\"Sorry I didn't get that\"";
    }

    // Constructing the response jsonObject 
    responseObject =
        JsonParser
            .parseString(
                "{ \"fulfillment_response\": { \"messages\": [ { \"text\": { \"text\": ["
                    + responseText
                    + "] } } ] } }")
            .getAsJsonObject();
    BufferedWriter writer = response.getWriter();

    //Sends the responseObject
    writer.write(responseObject.toString());
  }
}

Node.js

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

functions.http('handleWebhook', (request, response) => {
  const tag = request.body.fulfillmentInfo.tag;
  let text = '';

  if (tag === 'Default Welcome Intent') {
    text = 'Hello from a GCF Webhook';
  } else if (tag === 'get-name') {
    text = 'My name is Flowhook';
  } else {
    text = `There are no fulfillment responses defined for "${tag}"" tag`;
  }

  const jsonResponse = {
    fulfillment_response: {
      messages: [
        {
          text: {
            //fulfillment text response to be sent to the agent
            text: [text],
          },
        },
      ],
    },
  };

  response.send(jsonResponse);
});

Python

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import functions_framework

# TODO(developer): change entry point to handle_webhook in cloud function


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

    tag = req["fulfillmentInfo"]["tag"]

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

    # You can also use the google.cloud.dialogflowcx_v3.types.WebhookRequest protos instead of manually writing the json object
    # Please see https://googleapis.dev/python/dialogflow/latest/dialogflow_v2/types.html?highlight=webhookresponse#google.cloud.dialogflow_v2.types.WebhookResponse for an overview
    res = {"fulfillment_response": {"messages": [{"text": {"text": [text]}}]}}

    # Returns json
    return res

Definir parâmetros de formulário conforme necessário

Os exemplos a seguir mostram como sinalizar um parâmetro como obrigatório.

Java

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// TODO: Change class name to Example
// TODO: Uncomment the line below 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.JsonArray;
import com.google.gson.JsonObject;
import java.io.BufferedWriter;

public class ConfigureWebhookToSetFormParametersAsOptionalOrRequired implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject parameterObject = new JsonObject();
    parameterObject.addProperty("display_name", "order_number");
    parameterObject.addProperty("required", "true");
    parameterObject.addProperty("state", "VALID");

    JsonArray parameterInfoList = new JsonArray();
    parameterInfoList.add(parameterObject);

    JsonObject parameterInfoObject = new JsonObject();
    parameterInfoObject.add("parameter_info", parameterInfoList);

    JsonObject formInfo = new JsonObject();
    formInfo.add("form_info", parameterInfoObject);

    // Constructs the webhook response object
    JsonObject webhookResponse = new JsonObject();
    webhookResponse.add("page_info", formInfo);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonResponseObject = gson.toJson(webhookResponse);

    /* {
     *   "page_info": {
     *     "form_info": {
     *       "parameter_info": [
     *         {
     *           "display_name": "order_number",
     *           "required": "true",
     *           "state": "VALID"
     *         }
     *       ]
     *     }
     *   }
     * }
     */

    BufferedWriter writer = response.getWriter();

    // Sends the responseObject
    writer.write(jsonResponseObject.toString());
  }
}

Node.js

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

functions.http('configureOptionalFormParam', (request, response) => {
  // The value of the parameter that the webhook will set as optional or required.
  // Note that the webhook cannot add or remove any form parameter

  const jsonResponse = {
    pageInfo: {
      formInfo: {
        parameterInfo: [
          {
            displayName: 'order-number',
            // if required: false, the agent will not reprompt for this parameter, even if the state is 'INVALID'
            required: true,
            state: 'VALID',
          },
        ],
      },
    },
  };

  // Info about form parameter that is sent in the webhook response:
  console.log(
    'Parameter Info: \n',
    jsonResponse.pageInfo.formInfo.parameterInfo[0]
  );

  response.send(jsonResponse);
});

Validar um parâmetro de formulário

Os exemplos a seguir mostram como validar um parâmetro de formulário.

Java

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


// TODO: Change class name to Example
// TODO: Uncomment the line below 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.JsonArray;
import com.google.gson.JsonObject;
import java.io.BufferedWriter;

public class WebhookValidateFormParameter implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject sessionInfo = new JsonObject();
    JsonObject sessionParameter = new JsonObject();

    sessionParameter.addProperty("order_number", "null");
    sessionInfo.add("parameters", sessionParameter);

    JsonObject parameterObject = new JsonObject();
    parameterObject.addProperty("display_name", "order_number");
    parameterObject.addProperty("required", "true");
    parameterObject.addProperty("state", "INVALID");
    parameterObject.addProperty("value", "123");

    JsonArray parameterInfoList = new JsonArray();
    parameterInfoList.add(parameterObject);

    JsonObject parameterInfoObject = new JsonObject();
    parameterInfoObject.add("parameter_info", parameterInfoList);

    JsonObject pageInfo = new JsonObject();
    pageInfo.add("form_info", parameterInfoObject);

    // Constructs the webhook response object
    JsonObject webhookResponse = new JsonObject();
    webhookResponse.add("page_info", pageInfo);
    webhookResponse.add("session_info", sessionInfo);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonResponseObject = gson.toJson(webhookResponse);

    /**
     * { "page_info": { "form_info": { "parameter_info": [ { "display_name": "order_number",
     * "required": "true", "state": "INVALID", "value": "123" } ] } }, "session_info": {
     * "parameters": { "order_number": "null" } } }
     */
    BufferedWriter writer = response.getWriter();

    // Sends the responseObject
    writer.write(jsonResponseObject.toString());
  }
}

Node.js

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

functions.http('validateParameter', (request, response) => {
  // Webhook will validate or invalidate parameter based on logic configured by the user.
  // Access parameter values through the webhook request via `request.body.pageInfo.formInfo.parameterInfo[]`
  const jsonResponse = {
    page_info: {
      form_info: {
        parameter_info: [
          {
            displayName: 'orderNumber',
            required: true,
            state: 'INVALID',
            value: 123,
          },
        ],
      },
    },
    sessionInfo: {
      parameters: {
        // Set session parameter to null if the form parameter is 'INVALID' and your agent needs to reprompt the user
        orderNumber: null,
      },
    },
  };

  response.send(jsonResponse);
});

Python

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import functions_framework


@functions_framework.http
def validate_parameter(request):
    """Webhook will validate or invalidate parameter based on logic configured by the user."""
    return {
        "page_info": {
            "form_info": {
                "parameter_info": [
                    {
                        "displayName": "orderNumber",
                        "required": True,
                        "state": "INVALID",
                        "value": 123,
                    },
                ],
            },
        },
        "sessionInfo": {
            "parameters": {
                # Set session parameter to None if the form parameter is 'INVALID' and your agent needs to reprompt the user
                "orderNumber": None,
            },
        },
    }

ID da sessão do registro

O exemplo a seguir mostra como registrar o session ID de uma solicitação de webhook.

Python

Para autenticar no Dialogflow, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.


import re

import functions_framework


@functions_framework.http
def log_session_id_for_troubleshooting(request):
    """Webhook will log session id corresponding to request."""

    req = request.get_json()
    # You can read more about SessionInfo at https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/SessionInfo
    # Use a regex pattern to get the session ID
    session_id_regex = r".+\/sessions\/(.+)"
    session = req["sessionInfo"]["session"]
    regex_match = re.search(session_id_regex, session)
    session_id = regex_match.group(1)

    # Instead of printing, use the logging tools available to you
    print(f"Debug Node: session ID = {session_id}")

    # Return a generic response
    res = {
        "fulfillment_response": {
            "messages": [{"text": {"text": [f"Request Session ID: {session_id}"]}}]
        }
    }

    # Returns json
    return res

Solução de problemas

Ao resolver problemas com um webhook, é útil registrar o ID da sessão dele. O campo sessionInfo.session do WebhookRequest contém o ID da sessão. O ID de sessão precisa ser exclusivo para cada conversa e pode ajudar a comparar os registros do agente com os registros do webhook para solicitações que usam o mesmo ID de sessão. A seção Registrar o ID da sessão acima mostra como registrar o ID da sessão em um webhook.

Além disso, se você estiver hospedando seu webhook no Cloud Functions ou em uma opção sem servidor semelhante do Google Cloud, use o campo trace das entradas de registro como um filtro de registro. Uma única execução de uma função resulta em várias entradas de registro com o mesmo valor de rastreamento.

O exemplo abaixo usa o ID da sessão e o valor de rastreamento para associar um determinado registro de erros de agente de conversação (Dialogflow CX) às entradas de registro de webhook do Cloud Functions correspondentes. O exemplo usa filtros do Cloud Logging para um agente que ativou o Cloud Logging.

1. Filtrar os registros de erros de um agente específico dos agentes de conversação (Dialogflow CX)

Use o seguinte filtro de registro do Cloud para filtrar os registros de agentes de conversação (Dialogflow CX) de um agente específico:

labels.location_id="global"
labels.agent_id="AGENT_ID"
severity=ERROR

Uma entrada de registro de erro de webhook tem este formato:

{
  "insertId": "-zi368ye1ie3r",
  "jsonPayload": {
    "message": "Webhook error: State: URL_UNREACHABLE, Reason: UNREACHABLE_5xx, HTTP status code: 500",
    "code": 14
  },
  "resource": {
    "type": "global",
    "labels": {
      "project_id": "PROJECT_ID"
    }
  },
  "timestamp": "2022-10-05T19:44:53.098938Z",
  "severity": "ERROR",
  "labels": {
    "session_id": "ec8781-f28-7e6-791-d7e992e8f",
    "location_id": "global",
    "agent_id": "807346f0-f501-42b5-9642-af59d5e98165"
  },
  "logName": "projects/PROJECT_ID/logs/dialogflow-runtime.googleapis.com%2Frequests",
  "receiveTimestamp": "2022-10-05T19:44:53.222552658Z"
}

Observe o campo labels.session_id, que contém o ID da sessão. Você vai usar o ID da sessão na próxima etapa.

2. Filtrar os registros da função do Cloud para o ID da sessão

Use o seguinte filtro do Cloud Logging para filtrar os registros da Função do Cloud pelo ID da sessão:

resource.type = "cloud_function"
resource.labels.function_name = "CLOUD_FUNCTION_NAME"
resource.labels.region = "CLOUD_FUNCTION_REGION"
textPayload="Debug Node: session ID = SESSION_ID"

Os registros resultantes correspondem aos registros de webhook feitos durante a sessão fornecida. Exemplo:

{
  "textPayload": "Debug Node: session ID = ec8781-f28-7e6-791-d7e992e8f",
  "insertId": "632bdb2b000b7c6c77d0cc62",
  "resource": {
    "type": "cloud_function",
    "labels": {
      "project_id": "PROJECT_ID",
      "function_name": "webhook",
      "region": "us-central1"
    }
  },
  "timestamp": "2022-10-05T19:44:53.098938Z",
  "severity": "INFO",
  "labels": {
    "execution_id": "ozt5bnz50eeo",
    "instance_id": "00c61b117c1f116421aa5503bc80f9aa636b9ef117bb2722f3d54414085e62be6e55af0aa0250a63534262b31a3d3a14af8c940203f1915db8b25b"
  },
  "logName": "projects/PROJECT_ID/logs/cloudfunctions.googleapis.com%2Fcloud-functions",
  "trace": "projects/PROJECT_ID/traces/e41eefc1fac48665b442bfa400cc2f5e",
  "receiveTimestamp": "2022-10-05T19:44:53.222552658Z"
}

Observe o campo trace, que será usado na próxima etapa.

3. Filtrar registros do Cloud Functions para um rastro específico

Use o seguinte filtro do Cloud Logging para filtrar os registros do função do Cloud de um determinado rastro:

resource.type = "cloud_function"
resource.labels.function_name = "CLOUD_FUNCTION_NAME"
resource.labels.region = "CLOUD_FUNCTION_REGION"
trace="projects/PROJECT_ID/traces/TRACE_ID"

em que TRACE_ID é o último segmento do rastro. Por exemplo, o TRACE_ID para projects/PROJECT_ID/traces/e41eefc1fac48665b442bfa400cc2f5e é e41eefc1fac48665b442bfa400cc2f5e.

Os registros resultantes correspondem a todos os registros de webhook gerados durante a execução da solicitação de webhook associada ao ID da sessão da etapa 1 e ao rastreamento da etapa 2.