How to make Zapier Webhooks work as fufillment in API.AI - webhooks

I am experimenting with an API.AI agent. I want the responses to an intent to be fulfilled by webhooks.
I created a Zap that catch Webhooks as a trigger. The "Catch hook" trigger gave me an URL such as https://hooks.zapier.com/hooks/catch/1111111/9aaaaa/ that i entered in the API.AI fulfillment.
API.AI sends correctly the JSON to this URL, and the Zap is triggered, receiving the following example JSON:
result__fulfillment__messages: speech:
type: 0
id: 8551d99c-1ce9-4a0c-b24e-27d4c2090dbf
result__actionIncomplete: False
result__action: Trip-recommendations
result__resolvedQuery: all inclusive
result__metadata__intentId: 314e8e2f-312f-4ebd-93e1-c92da8648725
result__metadata__webhookForSlotFillingUsed: false
status__code: 200
timestamp: 2017-05-16T00:04:37.773Z
result__metadata__intentName: trip-recommendations
result__parameters__trip-who: family
result__parameters__trip-interest: all inclusive
status__errorType: success
lang: en
result__score: 1.0
result__source: agent
result__metadata__webhookUsed: true
sessionId: e28bd01f-2852-4c0c-98d8-ea03d58d87fa
Fields with no value:
result__parameters__trip-destinations
result__fulfillment__speech
result__contexts
result__speech
result__parameters__trip-recomendation-Country
result__parameters__date
result__parameters__unit-currency
result__parameters__date-period
Now i am trying to send a response in the second step of the Zap so as my API.AI agent use the response from the webhook as a fulfillment of the intent.
To do that i configured the second step of the Zap as a Webhooks Custom Request action with the following parameters:
URL: same as the URL entered in API.AI fulfillment menu https://hooks.zapier.com/hooks/catch/1111111/9aaaaa/
Payload Type: Json
Method: POST
Data:
unflatten: yes
url: https://hooks.zapier.com/hooks/catch/1111111/9aaaaa/
"fulfillment": {
"speech": "Today in Boston: Fair, the temperature is 37 F",
"source": "apiai-weather-webhook-sample",
"displayText": "Today in Boston: Fair, the temperature is 37 F"
}
method: POST
pass_through:
But when when i test the agent in Google Assistant simulator the response to the intent is always "I am sorry, the agentname is not available right now"
Does anyone can point me at what I am doing wrong?

Zapier's webhook triggers always respond with a JSON payload containing the same set of status-related properties (basically a confirmation that the webhook request was received and nothing more). There's no way to change that response data, unfortunately.

Related

aws lex v2 dynamic fulfillment from backend

Context
I'm using aws lex V2 and I have already set up a flow so that the user can make an appointment. The thing is that I would like to return (dynamic values) to the user something like:
Expected result
use dynamic values from the backend
ex:
Your appointment has been confirmed. Please keep the following code: {{appointment_code}} when you show up to the interview.
Actual Result
ex:
Your appointment has been confirmed.
When you set up the fulfillment output in aws lex v2, you defined the "static" content of the response, or add the value of the slots using {slotName} in the sentence. No matter what a set my message content from my backend response. i always get the response configure from the aws lex console, but not from the backend.
some code
The response that I'm using after i get all the necessary slots and generate the appointment "code reference" is the following:
function close(sessionAttributes, message) {
return {
"sessionState":{
sessionAttributes,
"dialogAction": {
"type": 'Close',
},
"intent": {
"name": "PetitionsIntent",
"state": "Fulfilled"
},
"messages": [
{
"contentType": "PlainText",
"content": `cool, the apointment code is ${ap_code}`,
}
],
}
};
}
The code works and the intent is fulfilled, but I get the response from the pre-defined lex console(image above) and not from the backend response.
Is there a way to overwrite the predefined output and use the lambda response instead?
What am I missing?
It would appear that your Lambda function has not been invoked.
Clicking the Advanced options button under your fulfillment message will slide in a menu from the right.
Ensure that you've checked the Use a Lambda function for fulfillment option under the Fulfillment Lambda code hook heading.
This assumes that you have correctly configured your bot to make use of a Lambda function.
Also note that Lex will use a different value for invocationSource to denote that all slots have been fulfilled. So your Lambda function will need to look out for FulfillmentCodeHook instead of DialogCodeHook.

Twilio sends call completed status for all calls

I was setting up Status Callbacks for calls in nodeJS. I've set the 'CALL STATUS CHANGES' in phone number configuration to do a POST request to my node. But twilio seems to be sending call status completed for all calls no matter is the answer was 'busy', 'unanswered' or 'completed'.
Here's my node code for displaying call status sent by Twilio:
app.post("/status", (req, res) => {
res.sendStatus(200);
console.log(req.body);
});
Output for a busy call:
{
ApiVersion: '2010-04-01',
Called: '',
CallStatus: 'completed',
Duration: '15',
From: 'client:AbrasiveHannahLiberty',
CallDuration: '15',
Direction: 'inbound',
Timestamp: 'Fri, 20 Mar 2020 05:43:09 +0000',
AccountSid: 'ACxxxxxxxx',
CallbackSource: 'call-progress-events',
ApplicationSid: 'APxxxxxxxx',
Caller: 'client:AbrasiveHannahLiberty',
SequenceNumber: '0',
To: '',
CallSid: 'CAxxxxxxxx'
}
Twilio client calls have two call legs. When the Twilio client places an outbound call, that is the parent leg. Twilio automatically answers that call leg, so the TwiML associated with your Voice Request URL can be accessed, all calls will result in completed calls.
Once the client call is placed, the TwiML Application you defined (and convey to your Twilio Client via the Access Token) has a Request URL which is used to obtain TwiML, so Twilio knows what to do with the call and for example, places an outbound call to the public switched telephone network (PSTN), the child leg.
It is the TwiML in that Request URL that should use a Dial verb with Number noun and the statusCallback URL to get the status you are looking for.
TwiML™ Voice: Number
I think you should check the statusCallback URL in $dial->number() have to be different from URL of statusCallback you have configured in TwiML App?
Example: if statusCallback URL you config in TwiML App is ..../status, then in the $dial->number() you have to set to ..../events (or anything URL you like) just like this:
$response = new VoiceResponse();
$dial = $response->dial('');
$dial->number('+12349013030',
['statusCallbackEvent' => 'initiated ringing answered completed',
'statusCallback' => '..../events',
'statusCallbackMethod' => 'POST']);

get username when user speaks to a dialogflow bot in Hangouts chat

I am building several bots with DialogFlow and Hangouts Chat integration.
How can I retrieve the user email of the user spraking to the bot ?
When I see the request sent from Hangouts chat to Dialogflow I cannot see any information about the user, it's like an anonymous request.
Has anybody find a workaround for that ?
It can be retrieved using events:
For each event like a message, a new user added or removed to the chat you can call event.user and it has the following fields:
event.user.name: The user name
event.user.email: The user email
event.user.displayName: The 'display' user name
event.user.avatarUrl: The user avatar's img url
For example, a working code using onMessage(event) function, for each interaction with the bot, the bot will answer with the user name and the message:
function onMessage(event) {
if (event.type == "MESSAGE" || event.space.type == "DM" ) {
var message = event.user.displayName + " said " + event.message.argumentText;
return { "text": message };
}
}
Response:
Benoit said How to get usernames on Hangouts bots?
A diagram of the JSON event format on Hangouts:
More documentation on hangouts events format and examples of use
Ok. Figured it out...
Indeed, you'll need to handle the intent using a Fullfilment.
In the default fullfilment function, you'll see this bit of code:
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
//... REST OF THE CODE WHERE YOU 'LL HANDLE THE INTENTS
});
The event info that you normally get out of an apps script chat bot is in the
request.body
For example email:
const email = request.body.originalDetectIntentRequest.payload.data.event.user.email;
In that user object, you'll also find:
email
avatarUrl
displayName
Ok, solution here is to enable fulfilment and process this as a cloud function. The input json of the cloud function contains all the event json.
I wanted to reply back "Hello #name" without using cloud function

How can I get the phone number from Twilio in fulfillment dialogflow

I'm working in a whastapp bot between Twilio and Dialogflow. In one of the intents, I'm sending media files from dialogflow to the user. Here it's the problem, now it's working with my mobile number hardcoded, but I need to access to the user phone number in each case to send the media file.
I develop this in fulfillment dialogflow, inline editor, using some nodejs code, but there I can't access to the user number.
Fulfillment node js
function sendAudioMensaje(agent) {
client.messages.create({
body: 'Body message',
to: 'whatsapp:+34---------', // Text to this number
from: 'whatsapp:+14155238886', // From a valid Twilio number
mediaUrl: 'https://demo.twilio.com/owl.png'
}).then((message) => agent.add(message.sid));
}
I expect that the message would be sent to the current number in each conversation
Twilio developer evangelist here.
As far as I can tell, the Dialogflow webhook request comes with a originalDetectIntentRequest property in the JSON. This contains a OriginalDetectIntentRequest object, which has a payload property that contains the original request.
I'd start by logging the contents of the webhook request to see what is fully available to you though.
Let me know if that helps at all.
In the payload of the OriginalDetectIntent request you will see a JSON like this in the webhook if it's enabled.
{
"source": "twilio",
"data": {
"SmsSid": "",
"Body": "",
"SmsStatus": "received",
"MessageSid": "",
"ApiVersion": "2010-04-01",
"From": "",
"AccountSid": "",
"NumMedia": "0",
"To": "",
"SmsMessageSid": "",
"NumSegments": "1"
}
}

Can a webhook server have no response?

I have a dialogflow implementation using Google assistant, a nodeJS server to serve the webhook calls. Some of the user intents are empty phrases, and they do not need any response from webhook server. However, the webhook must be called with every user sentence.
Can the webhook response return an empty response and not crash while doing so?
The server returns the response in predefined JSON format known to google assistant. When I set this response to NULL OR when I set the payload part of this response to BLANK, the application crashes.
var simpleChatResponse = {
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
]
}
}
},
"outputContexts": [
]
};
Actual results: "myAgent1 is not responding" and the application crashes.
No, you can not send an empty response. As the docs state:
The first item in a rich response must be a simple response.

Resources