Webhooks

Para ter ainda mais flexibilidade na criação de ações, você pode delegar a lógica para serviços da Web HTTPS (fulfillment). Suas ações podem acionar webhooks que fazer solicitações para um endpoint HTTPS. Alguns exemplos do que você pode fazer do fulfillment incluem:

  • Gerar um comando dinâmico com base nas informações fornecidas pelo usuário.
  • Fazer um pedido em um sistema externo e confirmar que o processo foi bem-sucedido.
  • Validação de slots com dados de back-end.
Figura 1. Intents e cenas de invocação podem acionar webhooks.

Gatilhos e gerenciadores de webhook

Suas ações podem acionar um webhook em intents ou cenas de invocação, envia uma solicitação ao endpoint de fulfillment. O fulfillment contém um webhook que processam o payload JSON na solicitação. É possível acionar webhooks nas seguintes situações:

  • Após uma correspondência de intent de invocação
  • Durante a entrada no palco
  • Depois que uma condição é avaliada como verdadeira no estágio de condição de uma cena
  • Durante a etapa de preenchimento do slot de uma cena
  • Depois que uma correspondência de intent ocorre no estágio de entrada de uma cena

Quando você aciona um webhook nas ações, o Google Assistente envia uma solicitação com um payload JSON para o fulfillment, que contém nome do manipulador a ser usado para processar o evento. O endpoint de fulfillment pode encaminhe o evento ao manipulador apropriado para realizar a lógica e retornar um resposta correspondente com um payload JSON.

Payloads

Os snippets a seguir mostram exemplos de solicitações enviadas pelas suas ações o fulfillment e uma resposta enviada por ele. Consulte a documentação de referência para mais informações imprecisas ou inadequadas.

Exemplo de solicitação

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

Exemplo de resposta

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

Interações no ambiente de execução

As seções a seguir descrevem tarefas comuns que você pode realizar em gerenciadores de webhook.

Enviar comandos

É possível criar comandos com texto simples, rich text, cards e até mesmo Solicitações HTML baseadas em um app da Web com Tela interativa. A documentação de prompts tem informações completas sobre como criar um prompt ao processar um evento de webhook. Os snippets a seguir mostram uma solicitação de card:

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'
    })
  }));
});

JSON de resposta

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

Ler parâmetros de intent

Quando o ambiente de execução do Assistente corresponde a uma intent, ele extrai as parâmetros. A propriedade original era o que o usuário forneceu como entrada, e a propriedade resolvida é o que o PLN resolveu a entrada com base no tipo especificação.

Node.js

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

Solicitação 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"
    ]
  }
}

Ler a localidade do usuário

Esse valor corresponde à configuração de localidade do usuário para o Google Assistente.

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

Armazenamento de leitura e gravação

Consulte a documentação sobre armazenamento para ter informações completas sobre como usar vários recursos de armazenamento.

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 

Solicitação 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"
    ]
  }
}

JSON de resposta

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

Verificar os recursos do dispositivo

É possível conferir os recursos de um dispositivo para oferecer diferentes experiências ou o fluxo de conversas.

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");

Solicitação 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 conferir uma lista completa de recursos da plataforma, consulte Capability. de referência.

Substituições do tipo de ambiente de execução

Os tipos de ambiente de execução permitem modificar as especificações de tipo durante a execução. Você pode usar este para carregar dados de outras fontes e preencher os valores válidos de um tipo. Para por exemplo, é possível usar substituições de tipo de ambiente de execução para adicionar opções dinâmicas a uma pesquisa ou adicionar um item diário a um menu.

Para usar tipos de ambiente de execução, acione um webhook da sua ação que chame um em seu fulfillment. A partir daí, é possível preencher o parâmetro session.typeOverrides em uma resposta à ação. Disponível incluem TYPE_MERGE para preservar entradas de tipo atuais ou TYPE_REPLACE para substituir entradas atuais por substituições.

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']
        },
    ]
  }
}];

JSON de resposta

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

Fornecer polarização de fala

A polarização de fala permite especificar dicas para o PLN para melhorar a correspondência de intent. Você pode especificar até 1.000 entradas.

Node.js

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

JSON de resposta

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

Cenas de transição

Além de definir as transições estáticas no seu projeto do Actions, é possível: fazer com que as transições de cena ocorram no momento da execução.

Node.js

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

JSON de resposta

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

Ler slots de cena

Durante o preenchimento de slot, é possível usar o fulfillment para validar o slot ou verificar o status de preenchimento de slot (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 exemplo, suponha que você queira extrair o fuso horário de uma resposta. Em Neste exemplo, o nome do slot é datetime1. Para obter o fuso horário, você usar:

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

Solicitação 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 slots de cena

É possível invalidar slots e fazer o usuário fornecer um novo valor.

Node.js

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

JSON de resposta

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

Opções de desenvolvimento

O Actions Builder oferece um editor in-line chamado editor do Cloud Functions. que permite criar e implantar uma função do Cloud para Firebase diretamente no no console do Google Cloud. Você também pode criar e implantar o fulfillment na hospedagem que preferir e registrar o endpoint de fulfillment HTTPS como o gerenciador de webhook.

Editor in-line

Para desenvolver com o editor do Cloud Functions:

  1. Crie o arquivo sdk/webhooks/ActionsOnGoogleFulfillment.yaml, e definir os gerenciadores da ação e da função do Cloud inline usada para o fulfillment.
    handlers:
    - name: questionOnEnterFunc
    - name: fruitSlotValidationFunc
    inlineCloudFunction:
      executeFunction: ActionsOnGoogleFulfillment
        
  2. Crie a pasta sdk/webhooks/ActionsOnGoogleFulfillment, e adicionar um arquivo index.js que implemente os gerenciadores definido anteriormente e um arquivo package.json que define o npm requisitos para seu código.
    // index.js
    const {conversation} = require('@assistant/conversation');
    const functions = require('firebase-functions');
    
    const app = conversation();
    
    app.handle('questionOnEnterFunc', conv => {
      conv.add('questionOnEnterFunc triggered on webhook');
    });
    
    app.handle('fruitSlotValidationFunc', conv => {
      conv.add('fruitSlotValidationFunc triggered on webhook');
    });
    
    exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
        
    // package.json
    {
      "name": "ActionsOnGoogleFulfillment",
      "version": "0.1.0",
      "description": "Actions on Google fulfillment",
      "main": "index.js",
      "dependencies": {
        "@assistant/conversation": "^3.0.0",
        "firebase-admin": "^5.4.3",
        "firebase-functions": "^0.7.1"
      }
    }
        

Endpoint HTTPS externo

Nesta seção, descrevemos como configurar o Cloud Functions para Firebase como um de processamento para sua ação de conversa. No entanto, é possível implantar do processamento do pedido para um serviço de hospedagem.

Configurar o ambiente

Recomendamos a seguinte estrutura de projeto ao usar o Cloud Functions para Firebase como um serviço de fulfillment:

ProjectFolder        - Root folder for the project
  sdk                - Actions project configuration files
  functions          - Cloud functions for Firebase files

Para configurar o ambiente, siga estas etapas:

  1. Faça o download e instale o Node.js.
  2. Configurar e inicializar a CLI do Firebase. Se o comando a seguir falhar com um erro EACCES, talvez seja necessário mudar as permissões do NPM.

    npm install -g firebase-tools
    
  3. Autentique a ferramenta do Firebase com sua Conta do Google:

    firebase login
    
  4. Inicie o diretório em que você salvou seu projeto do Actions. Você precisará selecionar para quais recursos da CLI do Firebase quer configurar seu projeto do Actions. Escolha Functions e outros recursos que talvez você queira use, como Firestore, e pressione Enter para confirmar e continuar:

    $ cd <ACTIONS_PROJECT_DIRECTORY>
    $ firebase init
    
  5. Associe a ferramenta do Firebase ao seu projeto do Actions selecionando-o usando Use as teclas de seta para navegar pela lista de projetos:

  6. Depois de escolher o projeto, a ferramenta do Firebase inicia o Functions e pergunta qual idioma você quer usar. Selecione usando as teclas de seta e pressione Enter 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. Escolha se quer usar o ESLint para detectar prováveis bugs e aplicar o estilo digitando Y ou N:

    ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
  8. Acesse as dependências do projeto digitando Y no comando:

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

    Quando a configuração for concluída, uma resposta semelhante a esta vai aparecer:

    ✔  Firebase initialization complete!
    
  9. Instale a dependência @assistant/conversation:

    $ cd <ACTIONS_PROJECT_DIRECTORY>/functions
    $ npm install @assistant/conversation --save
    
  10. Acesse as dependências do fulfillment e implante a função de fulfillment:

    $ npm install
    $ firebase deploy --only functions
    

    A implantação leva alguns minutos. Quando terminar, você vai ver uma saída semelhante para o seguinte. Você precisará do URL da função para inserir no 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. Copie o URL de fulfillment para usar na próxima seção.

Registrar gerenciador de webhook

  1. Crie o arquivo sdk/webhooks/ActionsOnGoogleFulfillment.yaml e defina os gerenciadores da sua ação e o URL das solicitações do webhook.
    httpsEndpoint:
      baseUrl: https://my.web.hook/ActionsOnGoogleFulfillment
      endpointApiVersion: 2
    handlers:
    - name: questionOnEnterFunc
    - name: fruitSlotValidationFunc