Working with Dynamic Responses
Learn what Dynamic Responses are and how to use them to manage application state.
Some Houndify domains may return more than one response and require clients to choose between those responses. These domains are using a feature called Dynamic Responses. In this tutorial, we’ll talk about what Dynamic Responses are, why they are useful, and how to leverage them in your client.
Checking if a domain uses Dynamic Responses
You can determine if a domain is using Dynamic Responses by checking the Client Integration Requirement section on the domain’s documentation page.
Additionally, the Try API tool will warn about this requirement and will display both default and success responses.
Let’s dig deeper into how Dynamic Responses work by looking at the SMS domain as an example.
Example: Dynamic Responses in the SMS Domain
The SMS domain allows composing text messages to your uploaded contacts using conversation state and dynamic responses. Let’s walk through how this works.
- Assume that we have uploaded the following contact information. The Syncing User Data tutorial covers how to upload JSON contact such as the one below.
{
"FirstName": "Bob",
"ID": 1,
"PhoneEntries": [
{
"Category": "Personal",
"Address": "(555)-555-5555"
}
]
}
2. If we make a query “Text Bob” we will get an SMSCommand
JSON result. It will contain NativeData
field of type ComposeSMSCommandNativeData
. It will also contain the information required for sending the SMS.
// ComposeSMSCommandNativeData{
"SMS": {
"Recipients": [
{
"PhoneNumber": "(555)-555-5555",
"Contacts": [
{
"FirstName": "Bob",
"PhoneEntries": [
{
"Category": "Personal",
"Number": "(555)-555-5555"
}
],
"ID": 1
}
],
"ToUserWrittenName": "Bob's Personal",
"ToUserSpokenName": "Bob's Personal"
}
],
"Body": "",
"To": {
"MissingPhoneNumbers": [],
"DisambiguatePhoneNumbers": [],
"ValidPhoneNumbers": [
{
"ContactName": "Bob's Personal",
"PhoneNumber": "(555)-555-5555"
}
]
}
},
"FocusHint": "Body",
"AutoListen": true,
"State": "ExpectingStartOfBody",
"OverwroteBody": false
}
Apart from NativeData
, the result will contain several dynamic responses. You can choose which response to use based on the state of your client.
ClientActionSucceededResult
: Use this if the SMS was sent correctly.ClientActionFailedResult
: Use this if the SMS failed to send.NoSMSAppResult
: Use this if there is no SMS application available on the client.ComposeSMSResult
: Use this if you are missing the body of the SMS, and have only received the sender’s information.DisambiguationSMSResult
: Use this if the query cannot be fulfilled because the user didn’t provide enough information to uniquely specify the needed information.ExitSMSResult
: Use this to
Since we are missing the body of the text, we should choose ComposeSMSResult
and continue the conversation. We pick the ConversationState
for this dynamic response and send it with the next query that contains the text message.
// ComposeSMSResult{
"SpokenResponse": "What's your message?",
"SpokenResponseLong": "What's your message?",
"WrittenResponse": "What's your message?",
"WrittenResponseLong": "What's your message?",
"AutoListen": true,
"UserVisibleMode": "Compose Text Message",
"ConversationState": {
"ConversationStateTime": 1519154951,
"Mode": "SMS",
"VoiceActivityDetectionMinima": {
"MaxSilenceAfterPartialQuerySeconds": 3
},
"SMSConversationStateContent": [
{
"CommandKind": "ComposeSMSCommand",
"ComposeSMSCommandKind": "SMSCreateCommand",
"PropagatedData": {
"SMS": {
"Recipients": [
{
"PhoneNumber": "(555)-555-5555",
"Contacts": [
{
"FirstName": "Bob",
"PhoneEntries": [
{
"Category": "Personal",
"Number": "(555)-555-5555"
}
],
"ID": 1
}
],
"ToUserWrittenName": "Bob's Personal",
"ToUserSpokenName": "Bob's Personal"
}
],
"Body": "",
"To": {
"MissingPhoneNumbers": [],
"DisambiguatePhoneNumbers": [],
"ValidPhoneNumbers": [
{
"ContactName": "Bob's Personal",
"PhoneNumber": "(555)-555-5555"
}
]
}
}
},
"State": "ExpectingStartOfBody",
"SMSDynamicResponseKind": "ComposeSMSResult"
}
]
}
}
3. After we send “Where are you?” as a follow up query we will get similar set of dynamic responses, but ComposeSMSResult
will now respond with “Would you like to send, review, continue, or cancel?”. NativeData
will contain all the data we need to send the text.
// ComposeSMSCommandNativeData{
"SMS": {
"Recipients": [
{
"PhoneNumber": "(555)-555-5555",
"Contacts": [
{
"FirstName": "Bob",
"PhoneEntries": [
{
"Category": "Personal",
"Number": "(555)-555-5555"
}
],
"ID": 1
}
],
"ToUserWrittenName": "Bob's Personal",
"ToUserSpokenName": "Bob's Personal"
}
],
"SpokenBody": "Where are you?",
"WrittenBody": "Where are you?",
"Body": "Where are you?",
"To": {
"MissingPhoneNumbers": [],
"DisambiguatePhoneNumbers": [],
"ValidPhoneNumbers": [
{
"ContactName": "Bob's Personal",
"PhoneNumber": "(555)-555-5555"
}
]
}
},
"LastEditedTextFieldType": "Body",
"NewBody": "Where are you?",
"AutoListen": true,
"State": "ExpectingContinuationOfBody",
"EditBodyState": "SET",
"FirstTimeAddingToBody": true
}
4. If we reply with query “Send it” and ConversationState
from ComposeSMSResult
, NativeData
will contain flag SendSMSNow: true
.
Now we can send the SMS. Note that it is a client’s responsibility to send the actual text and choose the correct dynamic response based on the status.
We hope that this tutorial helps you understand how Dynamic Responses work. Leave a comment if you have any questions.