A successful request returns 200 and the streamingUrl to use to create the SSE stream. Additionally it returns a streamId. Save this Id and use it to reconnect SSE in-case the stream disconnects.
The streaming URL is only valid for 30 seconds. After that time, the connection will be rejected and you will need to request a new URL.
Initiate the SSE stream by connecting to the URL and handle the events. How you connect to an SSE stream depends on the language you use and what are your preferred libraries. We include an example in NodeJS below.
You need to process each event from GenerativeAgent. The data sent via SSE needs to be parsed into a JSON, and then handled accordingly.
Determining the conversation the event pertains to and take the necessary action depending on the event type.
For a given analyze request on a conversation, you may receive any of the following event types:
processingStart: The bot started processing. This can be used to trigger user feedback such as showing a “typing” indicator.
authenticationRequired: Some API Connections require additional User authentication. Refer to User authentication required for more information.
reply: The bot has a reply for the conversation. We will automatically create a message for the bot, but you will need to send back the response to your user. This can be text directly when on a text based system, or your TTS for voice channels.
processingEnd: The bot finished processing. This indicates there will be no further events until analyze is called again.
transferToAgent: The bot could not handle the request and the conversation should be transferred to an agent.
transferToSystem: The bot is transferring control to an external system. This is a system transfer function.
Here is an example set of events where analyze is called:
{ generativeAgentMessageId: '116aaf51-8180-47b7-9205-9f61c8799c52', externalConversationId: '33411121', conversationId: '01HMVXRVSA1EGC0CHQTF1X2RN3', type: 'processingStart'}{ generativeAgentMessageId: '5c020ad9-4a25-4746-a345-017bb9711dbe', externalConversationId: '33411121', conversationId: '01HMVXRVSA1EGC0CHQTF1X2RN3', type: 'reply', reply: { messageId: '01HMVXSZANHNGJ49R83HENDAJB', text: "I'm happy to help you! One moment please." }}{ generativeAgentMessageId: 'd566fda8-3b7c-42a2-ae39-d08b66397238', externalConversationId: '33411121', conversationId: '01HMVXRVSA1EGC0CHQTF1X2RN3', type: 'reply', reply: { messageId: '01HMVXTDR1AT9CNQXPYKKBPJ7F', text: 'You can pay your bill by calling (XXX) XXX-6094, using the Mobile App, or with a customer service agent over the phone (with a $5 fee).' }}{ generativeAgentMessageId: 'bba4320f-de53-4874-83b4-6c8704d3620c', externalConversationId: '33411121', conversationId: '01HMVXRVSA1EGC0CHQTF1X2RN3', type: 'processingEnd'}
A key power of GenerativeAgent is it’s ability to call your APIs to look up information or perform an action. These are determined by the API Connections you create.
Some APIs require end user authentication. When this is the case, we sent the authenticationRequested event. Work with your ASAPP team to determine those authentication needs and what needs to passed back to ASAPP.
Based on the specifics of your API, you will need to gather the end user authentication information and call /authenticate on the conversation:
curl -X POST 'https://api.sandbox.asapp.com/conversation/v1/conversations/[conversation Id]/authenticate' \--header 'asapp-api-id: <API KEY ID>' \--header 'asapp-api-secret: <API TOKEN>' \--header 'Content-Type: application/json' \--data '{ "customerExternalId": "[Your Id of the customer]", "auth": { {{Your predetermined authentication payload}} }}'
A successful response returns a 204 response and no body. GenerativeAgent will continue processing and send you subsequent events.
Here is an example of initiate the SSE stream and listening for the events using nodeJS. This uses axios to get the URL and the EventSource package for handling the events:
import axios from 'axios';import EventSource from 'eventsource';const response = await axios.post('https://api.sandbox.asapp.com/generativeagent/v1/streams', {}, { headers: { 'asapp-api-id': '[Your API key id]', 'asapp-api-secret': '[Your API secret]', 'Content-Type': 'application/json' }});console.log('Using streaming URL:', response.data.streamingUrl);const eventSource = new EventSource(response.data.streamingUrl);eventSource.onopen = (event) => { console.log('Connection opened:', event.type);};eventSource.onerror = (error) => { console.error('EventSource failed:', error); eventSource.close();};eventSource.onmessage = (event) => { console.log('Received uncategorized data:', event.data);};eventSource.addEventListener('status', (event) => { console.log('Received status ping:', event.data);})eventSource.addEventListener('generative-agent-message', (event) => { console.log('Received generative-agent-message:', event.data); try { const parsedData = JSON.parse(event.data); console.log('Parsed data:', parsedData); // Handle different event types here switch (parsedData.type) { case "processingStart": console.log("Bot started processing."); break; case "authenticationRequired": console.log("Initiate customer authentication."); break; case "reply": console.log("GenerativeAgent responded:", parsedData.content); break; case "processingEnd": console.log("Bot finished processing"); break; case "transferToAgent": console.log("Bot could not handle request, transfer to a live agent."); break; default: console.log("Unknown event type:", parsedData.type); } } catch (error) { console.error('Error parsing event data:', error); }})
Each event is a json format with several fields with the following specification:
Field Name
Type
Description
generativeAgentMessageId
string
A unique identifier for this webhook request.
conversationId
string
The internal identifier for the conversation from the ASAPP system.
externalConversationId
string
The external identifier for the conversation from your external system.
type
string, enum
The type of bot response. It can be one of the following:
reply
processingStart
processingEnd
authenticationRequired
transferToAgent
transferToSystem
reply.*
object
If the type is reply then the bot’s reply is contained in this object.
reply.messageId
string
The identifier of the message sent in the reply
reply.text
string
The message text of the reply
transferToSystem.*
object
If the type is transferToSystem then the variables to be transferred to the external system are contained in this object.
transferToSystem.referenceVariables
object
A Hash map of reference variables to be transferred to the external system.
transferToSystem.transferVariables
object
A Hash map of transfer variables to be transferred to the external system.
transferToSystem.currentTaskName
string
The name of the current task that is being transferred to the external system.
{ "generativeAgentMessageId": "d566fda8-3b7c-42a2-ae39-d08b66397238", "externalConversationId": "33411121", "conversationId": "01HMVXRVSA1EGC0CHQTF1X2RN3", "type": "reply", "reply": { "messageId": "01HMVXTDR1AT9CNQXPYKKBPJ7F", "text": "You can pay your bill by calling (XXX) XXX-6094, using the Mobile App, or with a customer service agent over the phone (with a $5 fee)." }}
{ "generativeAgentMessageId": "d566fda8-3b7c-42a2-ae39-d08b66397238", "externalConversationId": "33411121", "conversationId": "01HMVXRVSA1EGC0CHQTF1X2RN3", "type": "reply", "reply": { "messageId": "01HMVXTDR1AT9CNQXPYKKBPJ7F", "text": "You can pay your bill by calling (XXX) XXX-6094, using the Mobile App, or with a customer service agent over the phone (with a $5 fee)." }}