1 - Build Aura response
Building Aura response in RCS channel
Building Aura response for a use case in the RCS channel has certain particularities due to the limitations of this channel
Introduction
When developing a use case, you should follow the general guidelines for building Aura response, which are common for all channels.
However, for RCS channel, certain specific steps must be carried out regarding rendering limitation of this channel and the configuration of the necessary attachments.
Sending messages to clients
Due to the special format of RCS messages and to avoid the extra complexity and maintainability of a transformation in aura-bridge between Directline messages and RCS messages, a new attachment type has been defined to send directly the payload of RCS messages in the activity. This payload will be sent directly to RCS by aura-bridge without any transformation.
Furthermore, the communication between aura-bridge and aura-bot is done using channelData V3, so dialogs should be implemented following the indications in the document Guidelines for creating/migrating a dialog to channelData v3.
Sending a text message
To send a simple text message, send an activity as shown below:
const dialogSettings = DialogUtils.getDataActiveDialog(stepContext, 'options');
const intentResult = dialogSettings?.intentResult;
await stepContext.context.sendActivity({
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'text': 'Hello, world!'
}
}
}]
});
In the previous example, the text “Hello, world!” will be sent to te user. The text inside the activity’s text field will be ignored.
There is only one special case when the text field of the activity is used to create the message: when the attachment with type application/vnd.telefonica.aura.rcs.message does not exist in a message of an RCS channel. But this case is reserved for error messages or other special situations. By default, text messages should be created with the necessary attachment.
Sending actions
You can send multiple types of actions to the user. All are defined in RCS Documentation.
All these actions have the field postbackData that will be returned to the bot as a text message when the user interacts and the dialog should know how to handle it.
You can set postbackData as a text auraCommand to handle it in a different dialog.
More info in Handling user messages in RCS channel
Sending a dial action
await stepContext.context.sendActivity({
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'text': 'Call technical service',
'suggestions': [
{
'action': {
'text': 'Call us!',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"call"}]}',
'fallbackUrl': 'https://www.google.com/contact/',
'dialAction': {
'phoneNumber': '+66666666666'
}
}
}
]
}
}
}]
});
Sending a location action
await stepContext.context.sendActivity({
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'text': 'Location message',
'suggestions': [
{
'action': {
'text': 'View map',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"location"}]}',
'fallbackUrl': 'https://www.google.com/maps/place/40%C2%B021\'39.5%22N+4%C2%B020\'01.8%22W/@40.3609722,-4.3338333,17z',
'viewLocationAction': {
'latLong': {
'latitude': '40.36085110',
'longitude': '-4.33394257'
},
'label': 'Pelayos de la presa, pedacito de cielo'
}
}
}
]
}
}
}]
});
Sending an URL
await stepContext.context.sendActivity({
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'text': 'Url message',
'suggestions': [
{
'action': {
'text': 'Open Google',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"el link"}]}',
'openUrlAction': {
'url': 'https://www.google.com'
}
}
}
]
}
}
}]
});
Sending a prompt
Here is an example of how to send a prompt to the user in RCS.
Due to the characteristics of this channel, you need to define the prompt options twice: as choices of the prompt and as suggestion buttons for the user.
As you can see, the choices values are set in choices and also
as suggestions in the attachment. The value in the postbackData must be the same as the one set in the choices, because it will be the value
returned when the button is clicked. The text field of the reply object is the text showed to the user and can have any value.
const dialogSettings = DialogUtils.getDataActiveDialog(stepContext, 'options');
const intentResult = dialogSettings?.intentResult;
const choicesText: Choice[] = [
{ value: 'Accept', synonyms: ['ok', 'yes'] },
{ value: 'Deny', synonyms: ['no'] }];
const promptOptions: PromptOptions = {
prompt: {
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'text': 'Hello, write one option or write the associated number',
'suggestions': []
}
}
}]
},
choices: ChoiceFactory.toChoices(choicesText)
};
choicesText.forEach((choice, index) => {
(promptOptions.prompt as Partial<Activity>).attachments[0].content.contentMessage.suggestions.push(
{
'reply': {
'text': choice.value,
'postbackData': choice.value
}
});
});
return await stepContext.prompt(this.promptsNames.COMMAND_CHOICE_PROMPT, promptOptions);
Sending rich cards
Rich cards allows you to send more complex messages to the user. All the info about rich cards in RCS can be found here
await stepContext.context.sendActivity({
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'richCard': {
'standaloneCard': {
'thumbnailImageAlignment': 'RIGHT',
'cardOrientation': 'VERTICAL',
'cardContent': {
'title': 'Hello, world!',
'description': 'RBM is awesome!',
'media': {
'height': 'TALL',
'contentInfo': {
'fileUrl': 'http://www.google.com/logos/doodles/2015/googles-new-logo-5078286822539264.3-hp2x.gif',
'forceRefresh': 'false'
}
},
'suggestions': [
{
'reply': {
'text': 'Suggestion #1',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"suggestion 1"}]}',
}
},
{
'reply': {
'text': 'Suggestion #2',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"suggestion 2"}]}',
}
}
]
}
}
}
}
}
}]
});
Sending carousels
Carousels are a special type of rich cards. You can find more info here
await stepContext.context.sendActivity({
text: 'Text doesn\'t matter',
channelData: ChannelDataResponseMapper.formatChannelDataV3(intentResult, corr),
attachments: [{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'richCard': {
'carouselCard': {
'cardWidth': 'MEDIUM',
'cardContents': [
{
'title': 'Card #1',
'description': 'The description for card #1',
'suggestions': [
{
'reply': {
'text': 'Card #1',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"card 1"}]}',
}
}
],
'media': {
'height': 'MEDIUM',
'contentInfo': {
'fileUrl': 'https://storage.googleapis.com/kitchen-sink-sample-images/cute-dog.jpg',
'forceRefresh': 'false'
}
}
},
{
'title': 'Card #2',
'description': 'The description for card #2',
'suggestions': [
{
'reply': {
'text': 'Card #2',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"card 2"}]}',
}
}
],
'media': {
'height': 'MEDIUM',
'contentInfo': {
'fileUrl': 'https://storage.googleapis.com/kitchen-sink-sample-images/elephant.jpg',
'forceRefresh': 'false'
}
}
}
]
}
}
}
}
}]
});
2 - Handling user messages in RCS channel
Handling user messages in RCS channel
The current document includes the guidelines for handling different types of messages in the RSC channel.
Some messages received from RCS channels have a particular behavior and some data is returned to the dialog in a new field of the
channelData: channelData.payload.suggestionResponse.
Here is an example of a user response of this type:
{
"type": "message",
"id": "d152aee9-1aaa-5b54-95a5-79352eee2e45|MxRCKxirowTtaiNb8-REy9TA",
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225",
"from": {
"id": "34659949469",
"name": "javiagent_crbwyhqz_agent@rbm.goog"
},
"conversation": {
"id": "c0709653-45f7-4fca-9808-3702d11fc346"
},
"channelData": {
"payload": {
"suggestionResponse": {
"postbackData": "{\\"intent\\": \\"intent.factotum-test.rcs-formats\\",\\"entities\\":[{\\"type\\":\\"type\\",\\"entity\\":\\"postback\\"},{\\"type\\":\\"data\\",\\"entity\\":\\"card 1\\"}]}",
"text": "Card #1",
"type": "REPLY"
},
"bridge": {
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225"
},
"auraGroot": {
"channelConversationId": "d152aee9-1aaa-5b54-95a5-79352eee2e45",
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225"
}
},
"version": "3",
"appContext": {
"channel": {
"modality": "text",
"id": "f7fd1021-41cd-588a-a461-387cc24be225"
},
"timestamp": "2024-10-04T16:36:55+02:00",
"timezone": "Europe/Madrid"
},
"correlator": "1be1b360-8cc4-4a4d-845b-bebb47869afd"
},
"text": "{\\"intent\\": \\"intent.factotum-test.rcs-formats\\",\\"entities\\":[{\\"type\\":\\"type\\",\\"entity\\":\\"postback\\"},{\\"type\\":\\"data\\",\\"entity\\":\\"card 1\\"}]}",
"serviceUrl": "http://localhost:8080/api/skills",
"relatesTo": {
"serviceUrl": "http://localhost:8045/aura-services/javiagent",
"activityId": "d152aee9-1aaa-5b54-95a5-79352eee2e45|MxRCKxirowTtaiNb8-REy9TA",
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225",
"conversation": {
"id": "d152aee9-1aaa-5b54-95a5-79352eee2e45"
},
"bot": null
},
"recipient": {
"role": "skill"
},
"callerId": "urn:botframework:aadappid:3837ac07-50e0-4d4e-993b-1bda1349f25a",
"locale": "es-cr"
}
The value of text and postbackData was set by the dialog when the card was sent, you can find more info in building Aura response
Handling suggestion responses
Buttons in cards, prompts or suggestions, return a REPLY response as the following suggestionResponse:
"suggestionResponse": {
"postbackData": "Rock",
"text": "Rock",
"type": "REPLY"
}
If prompts are created as specified in building Aura response,
they will be handled properly without any extra steps, because postbackData will be the text field of the activity and will be recognized by the prompt as an option.
Handling actions responses
Actions return an ACTION response as the following ones:
"suggestionResponse": {
"postbackData": "{\\"intent\\": \\"intent.factotum-test.rcs-formats\\",\\"entities\\":[{\\"type\\":\\"type\\",\\"entity\\":\\"postback\\"},{\\"type\\":\\"data\\",\\"entity\\":\\"la ubicación\\"}]}",
"text": "View map",
"type": "ACTION"
}
"suggestionResponse": {
"postbackData": "{\\"intent\\": \\"intent.factotum-test.rcs-formats\\",\\"entities\\":[{\\"type\\":\\"type\\",\\"entity\\":\\"postback\\"},{\\"type\\":\\"data\\",\\"entity\\":\\"llamar\\"}]}",
"text": "Call",
"type": "ACTION"
}
Ignoring responses
Every button sent to the user must have the postbackData field included:
'contentMessage': {
'text': 'Call technical service',
'suggestions': [
{
'action': {
'text': 'Call us!',
'postbackData': '{"intent": "intent.factotum-test.rcs-formats","entities":[{"type":"type","entity":"postback"},{"type":"data","entity":"call"}]}',
'fallbackUrl': 'https://www.google.com/contact/',
'dialAction': {
'phoneNumber': '+66666666666'
}
}
}
]
}
And this postbackData will be returned as a message to aura-bot when the user clicks the button. If you want to ignore this message or only write a log, you should implement a specific dialog to handle these actions and send every action response to this dialog with an aura-command:
{
contentType: 'application/vnd.telefonica.aura.rcs.message', content: {
'contentMessage': {
'text': 'Location message',
'suggestions': [
{
'action': {
'text': 'View map',
'postbackData': '{"intent": "intent.ignore-user-postback.example-dialog","entities":[]}',
'fallbackUrl': 'https://www.google.com/maps/place/40%C2%B021\'39.5%22N+4%C2%B020\'01.8%22W/@40.3609722,-4.3338333,17z',
'viewLocationAction': {
'latLong': {
'latitude': '40.36085110',
'longitude': '-4.33394257'
},
'label': 'Pelayos de la presa, pedacito de cielo'
}
}
}
]
}
}
}
3 - Start a conversation
Start a conversation in RCS channel
Sending messages through aura push
Introduction
Due to the design of the RCS protocol, the conversation with the user must be started by the server, who always sends the first message. To send this first message or other
messages without being in a conversation, the plugin aura push is used.
Sending text messages to the user
To send a simple text message to the user, a body like the following should be sent to the aura push endpoint:
{
"url":"https://svc-ap-next.auracognitive.com/aura-services/v1/aurapush/messages?channelId=f7fd1021-41cd-588a-a461-387cc24be225&apikey=XXX",
"channelId":"f7fd1021-41cd-588a-a461-387cc24be225",
"from":"+34666666666",
"id":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"text":"Hi! I'm Aura",
"type":"rcs",
"notificationId":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"notificationType":"not declared",
"checkContact":true
}
Sending complex messages to the user
If you need to send a more complex RCS message to the user, like a file, a card or any other type of RCS message, you need to add the rcsContentMessage field, that corresponds
with the contentMessage field of RCS messages:
{
"url":"https://svc-ap-next.auracognitive.com/aura-services/v1/aurapush/messages?channelId=f7fd1021-41cd-588a-a461-387cc24be225&apikey=XXX",
"channelId":"f7fd1021-41cd-588a-a461-387cc24be225",
"from":"34666666666",
"id":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"text":"This text will be ignored",
"type":"rcs",
"notificationId":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"notificationType":"not declared",
"checkContact":true,
"rcsContentMessage": {
"contentInfo": {
"fileUrl": "https://media.tenor.com/3VSWB_GIkqwAAAAe/wololo-age-of-empires.png",
"forceRefresh": "false"
}
}
}
Also, if you want to send all the messages in the same way, text messages can be sent with this format:
{
"url":"https://svc-ap-next.auracognitive.com/aura-services/v1/aurapush/messages?channelId=f7fd1021-41cd-588a-a461-387cc24be225&apikey=XXX",
"channelId":"f7fd1021-41cd-588a-a461-387cc24be225",
"from":"34666666666",
"id":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"text":"This text will be ignored",
"type":"rcs",
"notificationId":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"notificationType":"not declared",
"checkContact":true,
"rcsContentMessage": {
"text": "Hi! I'm Aura"
}
}
Sending messages through aura-bot
The previous messages are sent directly from aura-bridge to the user, but if you need to send a more complex message with data that can only be accessed by a bot dialog, you
can send a message to a bot dialog setting the type field to directline-rcs like this:
{
"url":"https://svc-ap-next.auracognitive.com/aura-services/v1/aurapush/messages?channelId=f7fd1021-41cd-588a-a461-387cc24be225&apikey=XXX",
"channelId":"f7fd1021-41cd-588a-a461-387cc24be225",
"from":"34666666666",
"id":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"text":"{\"intent\": \"intent.rcs.template\"}",
"type":"directline-rcs",
"notificationData":{
"brand":"Vivo",
"anotherCustomParam": "anotherCustomValue"
},
"notificationId":"a1be40d0-b8de-4c2a-8a26-8740a739675e",
"notificationType":"not declared",
"checkContact":true,
"rcsContentMessage": {
"text": "Hi {{customerName}}! I'm Aura, the AI assistant from {{brand}}"
}
}
Sending a message like the previous example, the bot will receive an activity like this, with the fields notificationData,
rcsContentMessage, uuid, notificationType and notificationId forwarded inside the channelData.payload.bridge.customData
field of the activity:
{
"type": "message",
"id": "d152aee9-1aaa-5b54-95a5-79352eee2e45|a1be40d0-b8de-4c2a-8a26-8740a739675e",
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225",
"from": {
"id": "34666666666",
"name": "javiagent_crbwyhqz_agent"
},
"conversation": {
"id": "1f6b5e0e-a5e1-4567-a39d-ba239d7d6d14"
},
"channelData": {
"version": "3",
"appContext": {
"channel": {
"modality": "text",
"id": "f7fd1021-41cd-588a-a461-387cc24be225"
},
"timestamp": "2024-10-14T13:40:54+02:00",
"timezone": "Europe/Madrid"
},
"payload": {
"bridge": {
"customData": {
"uuid": "a1be40d0-b8de-4c2a-8a26-8740a739675e",
"notificationType": "not declared",
"notificationId": "a1be40d0-b8de-4c2a-8a26-8740a739675e",
"notificationData": {
"brand":"Vivo",
"anotherCustomParam": "anotherCustomValue"
},
"rcsContentMessage": {
"text": "Hi {{customerName}}! I'm Aura, the AI assistant from {{brand}}"
}
}
},
"auraGroot": {
"channelConversationId": "d152aee9-1aaa-5b54-95a5-79352eee2e45",
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225"
}
},
"correlator": "078ee5cf-2b9d-4fb6-9268-c9c5685232f8"
},
"text": "{\\"intent\\": \\"intent.rcs.template\\"}",
"serviceUrl": "http://localhost:8080/api/skills",
"relatesTo": {
"serviceUrl": "http://localhost:8045/aura-services/javiagent",
"activityId": "d152aee9-1aaa-5b54-95a5-79352eee2e45|a1be40d0-b8de-4c2a-8a26-8740a739675e",
"channelId": "f7fd1021-41cd-588a-a461-387cc24be225",
"conversation": {
"id": "d152aee9-1aaa-5b54-95a5-79352eee2e45"
},
"bot": null
},
"recipient": {
"role": "skill"
},
"callerId": "urn:botframework:aadappid:3837ac07-50e0-4d4e-993b-1bda1349f25a",
"locale": "es-cr"
}
With this data you can create your custom dialog. The easiest way to reach your dialog is sending an aura-command with the desired intent in the text field as you have seen in the previous example.
In the rcsContentMessage you can send your pre-formated RCS body to be filled by the bot, and if you need more extra params can be sent in the notificationData field.
RCS is enabled in Android since version 5, and in iOS since version 18, but some customers couldn’t have it disabled or not available in their phones. To avoid errors
sending messages to phones that doesn’t allow RCS, you can check with the api if this phone is available, and then, send the message. To do this check, the field checkContact
should be sent to true. Take into account that this extra call consumes time, so if you have a list of already available RCS phones, you can skip this step.
If checkContact is set to true and the api returns an error because this phone doesn’t allow RCS, an error 403 will be returned.
Aura line api
You can send a text message directly to the user using the aura push endpoint /aura-services/v1/aurapush/messages.
All the information about the aura push endpoint could be found in the bridge swagger file: