Account linking Google actions via api.api - dialogflow-es

We are using api.api with fulfillment
After asking to sign in with the code:
app.askForSignIn();
We get intent call for input.unknown
We added sign handler but it is not called
const SIGN_IN = 'sign.in';
actionMap.set(SIGN_IN, signInLogic);
function signInLogic(app) {
let intent = app.getIntent();
console.log('signInLogic start intent: ', intent);
}
What needs to define in api.ai as intent to get the correct intent call?
I could not find a place to define system intents

Related

Google Action asking for parameters before account linking

I am using OAuth Authorisation Flow for my google action and for some reason, it is asking for parameters then initiating account linking and then asking for parameters again.
Example Response:
Code
app.intent('Create Channel Intent', async (conv, params) => {
if (!conv.user.access.token) {
conv.ask(new SignIn());
} else {
var locale = conv.user.locale;
if (locale === 'hi-IN') {
var accessToken = conv.user.access.token;
var channelNameRaw = params.channelname;
var channelNameData = await helperFunctions.hinditranslate(channelNameRaw);
var channelNameLwr = channelNameData.toLowerCase();
var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr);
const headers = await helperFunctions.login(accessToken);
const speechText = await helperFunctions.createChannel(channelName, headers);
conv.ask(speechText);
} else {
var accessToken = conv.user.access.token;
var channelNameRaw = params.channelname;
var channelNameData = channelNameRaw.toLowerCase();
var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData);
const headers = await helperFunctions.login(accessToken);
const speechText = await helperFunctions.createChannel(channelName, headers);
conv.ask(speechText);
}
}
});
Dialogflow
You shouldn't add training phrase to your SignIn event intent. If the intent which asks for signin permission has training phares would be enough. Because it directs to actions_intent_SIGN_IN event and continues on there unless user didn't signed in yet. I guess you made these two action in one intent so this makes it confused and tries to call same intent and asks for parameters.
If you had to use this way try to use context so you can pass parameter values to this intent on second call.
I am %99 sure that your intent's sloth filling is off.
Your Create Channel Intent has channelname as required parameter. Without Sloth-filling, intents won't call your server/code until every required parameter is fulfilled.
What happening is:
You are calling Create Channel intent and it asks for channel name as it is mandatory
User gives a channel name, intent calls your code as all required parameters are fulfilled.
Your code trigger sign_in intent as user haven't signed in yet.
User gives permission which triggers actions_intent_SIGN_IN event
Your Create Channel Intent has been called as it has actions_intent_SIGN_IN as trigger and asks for channelname as this intent is brand new.
To fix do one of this:
Enable sloth-filling at the bottom of intent.
Add an output context and add #[CONTEXT-NAME].channelname as default value to channelname parameter (without bracelets) . You can assign default values by clicking the appearing 3 dot when your mouse is over the parameter.
Split Capturing sign_in event from your Create Channel Intent
Hope it helps.

Regarding retrieving prompts

[We have a Dialogflow bot consisting of two intents. Each intent contains some set of questions.
The user answers the questions(prompts) and this process continues. We are getting the fulfillment text only after the intent is completed but we need to get the fulfillment text(Each and every prompt) after completing every question in that particular intent.
Help us in finding the solution.
You can use webhook for slot filling. (under the "Enable webhook call for this intent", enable Enable webhook call for slot filling button). By doing this, you can still stay in intent handler function and prompt what you need until you can finish your steps.
For example:
function flight(agent) {
const city = agent.parameters['geo-city'];
const time = agent.parameters['time'];
const gotCity = city.length > 0;
const gotTime = time.length > 0;
if(gotCity && gotTime) {
agent.add(`Nice, you want to fly to ${city} at ${time}.`);
} else if (gotCity && !gotTime) {
agent.add('Let me know which time you want to fly');
} else if (gotTime && !gotCity) {
agent.add('Let me know which city you want to fly to');
} else {
agent.add('Let me know which city and time you want to fly');
}
}
Also you can use this functionality on actions-on-google library.
Check for more information:
Webhook for slot filling
Enable Webhook for Slot Filling. Dialogflow will call your server to see if you can provide the pending information that your user didn’t.

Handing requests off to other intents

I have a dialogflow agent with 3 intents:
Default Welcome Intent
Default Fallback Intent
My Intent
My intent has a firebase web hook for fulfillment. When I enter a conversation with my chatbot, I get Default Welcome Intent. But as soon, as I ask a question that is handled by My Intent I seem stuck in My Intent even if i say something like hello after that. How do I exit out of my fulfillment and clear the state so that the Default Fallback and Default Welcome start working again? A lot of the fulfillment samples I've seen, handle these other intents within the custom fulfillment which seems wrong when you have these defaults already configured. Another example, is I enabled SmallTalk and after asking a question that's filled by My Intent, I then ask 'how old are you', this intent fires the agent.smalltalk.age against My Intent which makes no sense really.
Fulfillment code:
var https = require ('https');
const functions = require('firebase-functions');
const DialogFlowApp = require('actions-on-google').DialogFlowApp;
const WELCOME_INTENT= 'Default Welcome Intent';
const FALLBACK_INTENT = 'Default Fallback Intent';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
let action = request.body.queryResult.action;
response.setHeader('Content-Type','applicaiton/json');
const parameters = request.body.queryResult.parameters;
console.log("action: " + action)
if (action === 'input.wifi'){
getClientCount(parameters['geo-city'], response);
}
});
function getClientCount(location, CloudFnResponse) {
var chat = "sample text";
CloudFnResponse.send(buildChatResponse(chat));
return;
});
});
}
function buildChatResponse(chat) {
return JSON.stringify({"fulfillmentText": chat});
}
Default Fallback Intent:
Default Welcome Intent:
My Intent:
In the last screenshot please ignore the 'end of conversation' checkbox I was trying it out to see how it changed the behavior when I was taking the screenshot.
Turning off smalltalk solved the issue and exporting all the Smalltalk intents from the prebuilt agent and importing them into my Agent got smalltalk working.

Why doesn't the permission for a name work?

I'm trying to allow a permission in Google Assistant, but the simulator just asks to "repeat the answer" when asking for a name. Here is the code for permission.
app.intent('Default Welcome Intent', (conv) => {
conv.ask(new Permission({
context: 'Hi there, to get to know you better',
permissions: 'NAME'
}));
});
On deploying the code via Firebase, no errors are thrown.
Thanks in advance.
In your agent Default Welcome Intent is the intent which asks for NAME permission.
You will have to implement another intent to handle this permission. Lets call it user_info intent.
So when Actions On Google asks the question, and the user responds “yes” or “no” (grants or declines); Actions On Google will then send an event called “actions_intent_PERMISSION” to DialogFlow. We’ll use that event to trigger this particular intent. Once the intent is triggered, we’ll make sure to send the “user_info” action to our application.
In the application, we’ll register the “user_info” action and make sure to check whether the user has granted or declined the permissions. For that, we call the isPermissionGranted helper method.
app.intent('user_info', (conv, params, permissionGranted) => {
if (!permissionGranted) {
throw new Error('Permission not granted');
}
const {requestedPermission} = conv.data;
if (requestedPermission === 'NAME') {
conv.user.storage.name = conv.user.name.display;
return conv.close(responses.sayName(conv.user.storage.name));
}
throw new Error('Unrecognized permission');
});

DialogFlow NodeJs - Set Response Message after webhookClient.setFollowupEvent

I am using https://github.com/dialogflow/dialogflow-fulfillment-nodejs to create fulfillment webhook for dialogflow.
Currently I have intent that have 1 required parameter with prompt (so the agent will ask specific question for this parameter) and enable webhook call for this intent.
In the webhook, I check the parameter if that parameter is valid (call external api or something else), then I will trigger setFollowupEvent to move to other intent. But if the parameter is not valid, then I will trigger setFollowupEvent to return to this intent so the user should input it again. But I want to give the user a reason why that parameter is not valid.
The code is something like this
function registerUserStartHandler(agent) {
let payload = request.body.originalDetectIntentRequest.payload;
let senderDetail = getSenderDetail(payload);
return isUserRegistered(senderDetail.senderId, senderDetail.platformType).then((res) => {
if (res) {
agent.add('User already registered, enter another user');
//register_user_ask_user is this same intent (so I just returned to current intent if failed)
agent.setFollowupEvent('register_user_ask_user');
} else {
agent.setFollowupEvent('register_user_ask_other_info');
}
return Promise.resolve();
})
}
But, currently dialogflow will return to user the prompt message that I defined for that required parameter not the reason message.
How to replace this prompt message with my message from webhook?

Resources