Connect
How to connect to an API
You can connect to any API by defining their details inside the connect
property. The target endpoint will need to be able to accept
and respond using the formats described below.
Video demo
Request message
The outgoing Deep Chat request body is encapsulated in one of the following formats:
-
When sending text based messages only, the request body will have the following JSON type:
{messages: MessageContent[]
} -
When sending messages that contain files, the request body is going to be serialized inside a FormData type where files are set inside an array property called "files" and each text message is stored inside a "message{index}" property with a corresponding index:
{files: File[]
,message1: MessageContent
,message2: MessageContent
... }
Response message
Response from the target server needs to use the Response
JSON type.
If you don't want / can't change the target server to handle the required object types, use the interceptor
properties
to augment the transferred objects or the handler
function to control the request code.
Connection properties
connect
-
Type: {
url?: string
,
method?: string
,
headers?: {[string]: string}
,
additionalBodyProps?: {[string]: any}
,
credentials?: string
,
websocket?: Websocket
,
stream?: Stream
,
handler?: Handler
} -
Default: { method: "POST", credentials: "same-origin" }
Settings for the outgoing API requests. This object MUST have url
or handler
property defined.
additionalBodyProps
is used to add additional key value properties to the outgoing message body.
credentials
is used to configure whether the outgoing request should contain cookies. More info.
websocket
is used to establish a websocket connection instead of sending REST requests.
Video demo
Example
- Sample code
- Full code
<deep-chat
connect='{
"url": "https://customapi.com/message",
"method": "POST",
"headers": {"customName": "customHeaderValue"},
"additionalBodyProps": {"customBodyField": "customBodyValue"}
}'
></deep-chat>
<!-- This example is for Vanilla JS and should be tailored to your framework (see Examples) -->
<deep-chat
connect='{
"url": "https://customapi.com/message",
"method": "POST",
"headers": {"customName": "customHeaderValue"},
"additionalBodyProps": {"customBodyField": "customBodyValue"}
}'
style="border-radius: 8px"
></deep-chat>
requestBodyLimits
- Type: {
maxMessages?: number
,totalMessagesMaxCharLength?: number
}
Used to limit the content that is going to be included in the outgoing requests.
maxMessages
is the maximum number of messages counting from the most recent one. If this is set to a number higher than 0 such as 1 - the outgoing request will only include the new user message,
if it is 2 - it will also include the message before the latest one (from AI or the user) and so on... If the number is 0 or below - the request will include all messages in the chat. If
it is undefined, the request will only include the input text/files.
totalMessagesMaxCharLength
is the total maximum number of text characters sent in the request counting from the most recent message.
These limits do not include the introMessage
.
Example
- Sample code
- Full code
<deep-chat
requestBodyLimits='{
"totalMessagesMaxCharLength": 20,
"maxMessages": 2
}'
></deep-chat>
<!-- This example is for Vanilla JS and should be tailored to your framework (see Examples) -->
<deep-chat
requestBodyLimits='{
"totalMessagesMaxCharLength": 20,
"maxMessages": 2
}'
style="border-radius: 8px"
demo="true"
introMessage='{"text": Observe the data that is going to be sent below."}'
></deep-chat>
Types
Types shared with other component properties:
Response
- Type: {
MessageContent
,error?: string
,overwrite?: boolean
}
Object containing response information from the target service. It has the same properties as MessageContent
with additional optional error
and
overwrite
properties:
text
is the content for a text message.
files
is an array that encapsulates details on the response files.
html
is a string that defines the markup for custom elements. It must describe full elements.
error
describes information about a server error. If the displayServiceErrorMessages property in errorMessages
is set to true, the same message will be displayed in the chat's error bubble.
overwrite
replaces last message from the same role or creates a new one if not found. Status bubble example.
Examples:
Simple - {text: "Simple response"}
Mixed - {files: [{name: "file.txt"}], html: "<div>Custom Element</div>"}
Custom role - {role: "bob", text: "Message from bob"}
Error - {error: "Service Error"}
Overwrite - {text: "New text", overwrite: true}
Websocket
- Type:
boolean
|string
|string[]
This is used to establish a websocket connection with your server. Enable it by defining the websocket
property inside the connect
object
as a boolean
true or as a string connection protocol
(or an array of strings for multiple protocols).
It is important to note that exchanged messages must be Stringified JSONs where Deep Chat will send its messages using the Request message format
and the server must send its messages using the Response
format. Example messages:
Deep Chat message:
'{"messages":[{"role":"user","text":"Message from Deep Chat"}]}'
Server message:
'{"text":"Message from the server"}'
Example
- Sample code
- Full code
<deep-chat connect='{"url": "ws://customapi.com", "websocket": true}'></deep-chat>
<!-- This example is for Vanilla JS and should be tailored to your framework (see Examples) -->
<deep-chat
connect='{"url": "ws://customapi.com", "websocket": true}'
style="border-radius: 8px"
introMessage='{"text": Chat will attempt to establish a websocket connection as soon as the component loads up."}'
></deep-chat>
Check the websocket server template to help you get started.
Status Bubble Example
- Sample code
- Full code
Messages from the server:
1: {text: "Downloading...", overwrite: true}
2: {text: "Loading...", overwrite: true}
3: {text: "Processing...", overwrite: true}
4: {text: "Ready...", overwrite: true}
Component configuration:
<deep-chat connect='{"url": "ws://customapi.com", "websocket": true}'></deep-chat>
Messages from the server:
1: {text: "Downloading...", overwrite: true}
2: {text: "Loading...", overwrite: true}
3: {text: "Processing...", overwrite: true}
4: {text: "Ready...", overwrite: true}
Stream
- Type:
boolean
| {simulation?: boolean | number | string
}
Used to stream responses from the target service.
By setting true - the chat will stream incoming server-sent events
from
the server. See example
server code.
The responses are expected to contain partial text, however you can use overwrite
to overwrite each one.
You can alternatively use the simulation
object property to facilitate a stream-like experience for any other connection type where the received content wil be
gradually populated in the message bubble. You can control the millisecond interim of each word's appearance by assigning it a number with the default being 6.
A string value is used to act like an end-phrase for individual websocket messages that act like a stream.
Stream Service Example
- Sample code
- Full code
<deep-chat connect='{"stream": true}'></deep-chat>
<!-- This example is for Vanilla JS and should be tailored to your framework (see Examples) -->
<deep-chat
connect='{"stream": true}'
demo="true"
style="border-radius: 8px"
introMessage='{"text": The response message bubble will be populated gradually with text events."}'
></deep-chat>
Regular Service Example
- Sample code
- Full code
<deep-chat connect='{"stream": {"simulation": 6}}'></deep-chat>
<!-- This example is for Vanilla JS and should be tailored to your framework (see Examples) -->
<deep-chat
connect='{"stream": {"simulation": 6}}'
demo="true"
style="border-radius: 8px"
introMessage='{"text": The response message bubble will be populated gradually with text events."}'
></deep-chat>
Handler
- Type: (
body: any
,signals: Signals
) =>void
This function gives developers full control for making server requests using their own code.
It is invoked when the user
attempts to send a message and consists of two core arguments:
body
is an object that contains the outgoing message details and uses the Request message
type.
signals
is a map of functions which are used to notify Deep Chat on the status of the request and its result. The available
signal functions differ based on the type of connection you are establishing. See examples below.
Video demo
Example
- Basic
- Stream
- Websocket
chatElementRef.connect = {
handler: (body, signals) => {
try {
fetch('custom-url').then((response) => {
signals.onResponse({text: 'Handler response'}); // displays the response text message
});
} catch (e) {
signals.onResponse({error: 'Error'}); // displays an error message
}
},
};
chatElementRef.stream = true;
chatElementRef.connect = {
handler: (body, signals) => {
try {
// this is PSEUDO CODE for creating a stream
fetchEventSource('custom-url', {
async onopen(response) {
if (response.ok) {
signals.onOpen(); // stops the loading bubble
} else {
signals.onResponse({error: 'error'}); // displays an error message
}
},
onmessage(message) {
signals.onResponse({text: message}); // adds text into the message bubble
},
onerror(message) {
signals.onResponse({error: message}); // displays an error message
},
onclose() {
signals.onClose(); // The stop button will be changed back to submit button
},
});
// triggered when the user clicks the stop button
signals.stopClicked.listener = () => {
// logic to stop your stream, such as creating an abortController
};
} catch (e) {
signals.onResponse({error: 'error'}); // displays an error message
}
},
};
// this handler is invoked when the component is loaded
chatElementRef.connect = {
websocket: true,
handler: (_, signals) => {
try {
const websocket = new WebSocket('custom-url');
websocket.onopen = () => {
signals.onOpen(); // enables the user to send messages
};
websocket.onmessage = (message) => {
const response = JSON.parse(message.data);
signals.onResponse(response); // displays a text message from the server
};
websocket.onclose = () => {
signals.onClose(); // stops the user from sending messages
};
websocket.onerror = () => {
// 'Connection error' is a special string that will also display in Deep Chat
signals.onResponse({error: 'Connection error'});
};
// triggered when the user sends a message
signals.newUserMessage.listener = (body) => {
websocket.send(JSON.stringify(body));
};
} catch (e) {
signals.onResponse({error: 'error'}); // displays an error message
signals.onClose(); // stops the user from sending messages
}
},
};
Error handling must be done within the handler
function.
Signals
- Type: {
onResponse: (response: Response) => void
,
onOpen: () => void
,
onClose: () => void
,
stopClicked: {listener: () => void}
,
newUserMessage: {listener: (body: any) => void}
}
Object containing functions that are used to notify the Deep Chat component about the status of the current request.
The stopClicked
and newUserMessage
functions are triggered by Deep Chat itself and contain listener
properties
which can be assigned with custom functions to listen for when they are called (see the examples above).