Webhooks

Para brindarte aún más flexibilidad en la compilación de acciones, puedes delegar la lógica a los servicios web HTTPS (entregas). Tus acciones pueden activar webhooks que realizan solicitudes a un extremo HTTPS. Estos son algunos ejemplos de lo que puedes hacer en las entregas:

  • La generación de una instrucción dinámica basada en información proporcionada por el usuario.
  • Realizar un pedido en un sistema externo y confirmar que se realizó correctamente
  • Valida ranuras con datos de backend.
Figura 1: Los intents y las escenas de invocación pueden activar webhooks.

Activadores y controladores de webhooks

Tus acciones pueden activar un webhook dentro de intents o escenas de invocación, que envía una solicitud a tu extremo de entrega. Tu entrega contiene controladores de webhook que procesan la carga útil de JSON en la solicitud. Puedes activar webhooks en las siguientes situaciones:

  • Después de que se detecta una coincidencia con un intent de invocación
  • Cuando una escena está en el escenario
  • Después de que una condición se evalúa como verdadera en la etapa de condición de una escena
  • Durante la etapa de relleno de ranuras de una escena
  • Después de que se produce una coincidencia de intent en la etapa de entrada de una escena

Cuando activas un webhook en tus acciones, Asistente de Google envía una solicitud con una carga útil de JSON a tu entrega, que contiene el nombre del controlador que se debe usar para procesar el evento. Tu extremo de entrega puede enrutar el evento al controlador apropiado para llevar a cabo la lógica y mostrar una respuesta con una carga útil de JSON correspondiente.

Cargas útiles

En los siguientes fragmentos, se muestran ejemplos de solicitudes que tus acciones envían a la entrega y una respuesta que esta envía de vuelta. Consulta la documentación de referencia para obtener más información.

Ejemplo de solicitud

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "example_session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Ejemplo de respuesta

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello World.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

Interacciones de tiempo de ejecución

En las siguientes secciones, se describen las tareas comunes que puedes realizar en los controladores de webhook.

Enviar instrucciones

Con Interactive Canvas, puedes crear instrucciones con texto simple, texto enriquecido, tarjetas o incluso mensajes HTML completos respaldados por una app web. La documentación de prompts tiene información completa sobre cómo crear un mensaje cuando se controla un evento de webhook. En los siguientes fragmentos, se muestra un mensaje de tarjeta:

Node.js

app.handle('rich_response', conv => {
  conv.add('This is a card rich response.');
  conv.add(new Card({
    title: 'Card Title',
    subtitle: 'Card Subtitle',
    text: 'Card Content',
    image: new Image({
      url: 'https://developers.google.com/assistant/assistant_96.png',
      alt: 'Google Assistant logo'
    })
  }));
});

Respuesta JSON

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "content": {
      "card": {
        "title": "Card Title",
        "subtitle": "Card Subtitle",
        "text": "Card Content",
        "image": {
          "alt": "Google Assistant logo",
          "height": 0,
          "url": "https://developers.google.com/assistant/assistant_96.png",
          "width": 0
        }
      }
    },
    "firstSimple": {
      "speech": "This is a card rich response.",
      "text": ""
    }
  }
}

Cómo leer los parámetros de los intents

Cuando el tiempo de ejecución de Asistente coincide con un intent, extrae los parámetros definidos. La propiedad original era lo que el usuario proporcionó como entrada y la propiedad resuelta es la que resolvió la entrada según la especificación del tipo.

Node.js

conv.intent.params['param_name'].original
conv.intent.params['param_name'].resolved

Cómo solicitar JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "intent_name",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Leer configuración regional del usuario

Este valor corresponde a la configuración regional del usuario para Asistente de Google.

Node.js

conv.user.locale

JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Almacenamiento de lectura y escritura

Consulta la documentación sobre almacenamiento para obtener información completa sobre cómo usar varias funciones de almacenamiento.

Node.js

//read
conv.session.params.key
conv.user.params.key
conv.home.params.key

// write
conv.session.params.key = value
conv.user.params.key = value
conv.home.params.key = value 

Cómo solicitar JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    },
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Respuesta JSON

{
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello world.",
      "text": ""
    }
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  }
}

Cómo verificar las funciones del dispositivo

Puedes verificar las capacidades de un dispositivo para ofrecer diferentes experiencias o flujos de conversación.

Node.js

const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
const supportsLongFormAudio = conv.device.capabilities.includes("LONG_FORM_AUDIO");
const supportsSpeech = conv.device.capabilities.includes("SPEECH");
const supportsInteractiveCanvas = conv.device.capabilities.includes("INTERACTIVE_CANVAS");

Cómo solicitar JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO",
      "INTERACTIVE_CANVAS"
    ]
  }
}

Para obtener una lista completa de las funciones de plataforma, consulta la referencia de Capability.

Anulaciones de tipos de entornos de ejecución

Los tipos de entorno de ejecución te permiten modificar las especificaciones de tipo durante el tiempo de ejecución. Puedes usar esta función para cargar datos de otras fuentes a fin de propagar los valores válidos de un tipo. Por ejemplo, puedes usar anulaciones de tipo de entorno de ejecución para agregar opciones dinámicas a una pregunta de encuesta o para agregar un elemento diario a un menú.

Para usar tipos de entorno de ejecución, debes activar un webhook desde tu Acción que llame a un controlador en tu entrega. Desde allí, puedes propagar el parámetro session.typeOverrides en una respuesta a tu acción. Los modos disponibles incluyen TYPE_MERGE para conservar las entradas de tipo existentes o TYPE_REPLACE para reemplazar las entradas existentes con las anulaciones.

Node.js

conv.session.typeOverrides = [{
    name: type_name,
    mode: 'TYPE_REPLACE',
    synonym: {
      entries: [
        {
          name: 'ITEM_1',
          synonyms: ['Item 1', 'First item']
        },
        {
          name: 'ITEM_2',
          synonyms: ['Item 2', 'Second item']
       },
       {
          name: 'ITEM_3',
          synonyms: ['Item 3', 'Third item']
        },
        {
          name: 'ITEM_4',
          synonyms: ['Item 4', 'Fourth item']
        },
    ]
  }
}];

Respuesta JSON

{
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [
      {
        "name": "type_name",
        "synonym": {
          "entries": [
            {
              "name": "ITEM_1",
              "synonyms": [
                "Item 1",
                "First item"
              ]
            },
            {
              "name": "ITEM_2",
              "synonyms": [
                "Item 2",
                "Second item"
              ]
            },
            {
              "name": "ITEM_3",
              "synonyms": [
                "Item 3",
                "Third item"
              ]
            },
            {
              "name": "ITEM_4",
              "synonyms": [
                "Item 4",
                "Fourth item"
              ]
            }
          ]
        },
        "typeOverrideMode": "TYPE_REPLACE"
      }
    ]
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  }
}

Proporcionar personalización de voz

La personalización de voz te permite especificar sugerencias a la CLN para mejorar la coincidencia de intents. Puedes especificar hasta 1,000 entradas.

Node.js

conv.expected.speech = ['value_1', 'value_2']
conv.expected.language = 'locale_string'

Respuesta JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  },
  "expected": {
    "speech": "['value_1', 'value_2']",
    "language": "locale_string"
  }
}

Escenas de transición

Además de definir transiciones estáticas en tu proyecto de acciones, puedes hacer que ocurran transiciones de escena durante el tiempo de ejecución.

Node.js

app.handle('transition_to_hidden_scene', conv => {
  // Dynamic transition
  conv.scene.next.name = "HiddenScene";
});

Respuesta JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "HiddenScene"
    }
  }
}

Cómo leer ranuras de escena

Durante el relleno de ranuras, puedes usar la entrega para validar la ranura o verificar el estado del llenado de ranuras (SlotFillingStatus).

Node.js

conv.scene.slotFillingStatus  // FINAL means all slots are filled
conv.scene.slots  // Object that contains all the slots
conv.scene.slots['slot_name'].<property_name> // Accessing a specific slot's properties

Por ejemplo, supongamos que deseas extraer la zona horaria de una respuesta. En este ejemplo, el nombre de la ranura es datetime1. Para obtener la zona horaria, utiliza lo siguiente:

conv.scene.slots['datetime1'].value.time_zone.id

Cómo solicitar JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "FINAL",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "SLOT_UNSPECIFIED",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    },
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Invalidar ranuras de escena

Puedes invalidar las ranuras y hacer que el usuario proporcione un valor nuevo.

Node.js

conv.scene.slots['slot_name'].status = 'INVALID'

Respuesta JSON

{
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "INVALID",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

Opciones de desarrollo

Actions Builder proporciona un editor directo llamado editor de Cloud Functions que te permite compilar e implementar una función de Cloud Functions para Firebase directamente en la consola. También puedes compilar e implementar la entrega en el hosting que elijas y registrar tu extremo de entrega HTTPS como el controlador de webhook.

Editor directo

Sigue estos pasos para desarrollar con el editor de Cloud Functions:

  1. Abre tu proyecto de Acciones y ve a la pestaña Desarrollo > Webhook > Cambiar método de entrega. Aparecerá la ventana Métodos de entrega.
  2. Selecciona Cloud Functions intercaladas y haz clic en Confirmar.

Extremo HTTPS externo

En esta sección, se describe cómo configurar Cloud Functions para Firebase como un servicio de entrega para tu acción de conversación. Sin embargo, puedes implementar la entrega en el servicio de hosting que prefieras.

Cómo configurar el entorno

Para configurar tu entorno, sigue estos pasos:

  1. Descarga y, luego, instala Node.js.
  2. Configura y, luego, inicializa Firebase CLI. Si el siguiente comando falla con un error EACCES, es posible que debas cambiar los permisos de npm.

    npm install -g firebase-tools
    
  3. Autentica la herramienta de Firebase con tu Cuenta de Google:

    firebase login
    
  4. Inicia el directorio del proyecto en el que guardaste tu proyecto de Acciones. Se te pedirá que selecciones las funciones de Firebase CLI que quieres configurar para tu proyecto de Acciones. Elige Functions y otras funciones que quizás quieras usar, como Firestore, y presiona Intro para confirmar y continuar:

    $ cd <ACTIONS_PROJECT_DIRECTORY>
    $ firebase init
    
  5. Para asociar la herramienta de Firebase con tu proyecto de acciones, selecciónalo con las teclas de flecha a fin de navegar por la lista de proyectos:

  6. Después de elegir el proyecto, la herramienta de Firebase inicia la configuración de Functions y te pregunta qué lenguaje quieres usar. Selecciona con las teclas de flecha y presiona Intro para continuar.

    === Functions Setup
    A functions directory will be created in your project with a Node.js
    package pre-configured. Functions can be deployed with firebase deploy.
    
    ? What language would you like to use to write Cloud Functions? (Use arrow keys)
    > JavaScript
    TypeScript
    
  7. Elige si deseas usar ESLint para detectar posibles errores y aplicar el estilo escribiendo Y o N:

    ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
  8. Para obtener las dependencias del proyecto, escribe Y en el mensaje:

    ? Do you want to install dependencies with npm now? (Y/n)

    Una vez completada la configuración, verás un resultado similar al siguiente:

    ✔  Firebase initialization complete!
    
  9. Instala la dependencia @assistant/conversation:

    $ cd <ACTIONS_PROJECT_DIRECTORY>/functions
    $ npm install @assistant/conversation --save
    
  10. Obtén las dependencias de entrega y, luego, implementa la función de entrega:

    $ npm install
    $ firebase deploy --only functions
    

    La implementación tarda unos minutos. Una vez que se complete, verás un resultado similar al siguiente. Necesitarás la URL de la función para ingresar en Dialogflow.

    ✔  Deploy complete!
    Project Console: https://console.firebase.google.com/project/<PROJECT_ID>/overview Function URL (<FUNCTION_NAME>): https://us-central1-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>
  11. Copia la URL de entrega para usarla en la siguiente sección.

Registra el controlador de webhook

Sigue estos pasos para registrar tu extremo de Cloud Function como un controlador de webhook:

  1. En la Consola de Actions, haz clic en Develop > Webhook.
  2. Haz clic en Change fulfillment method. Aparecerá la ventana Métodos de entrega.
  3. Selecciona Webhook y haz clic en Confirmar.
  4. Pega la URL del servicio web en el campo Webhook.
  5. Haz clic en Guardar.