Skip to main content

Websocket

The /ws endpoint opens a websocket connection to allow bidirectional communication between frontend and the Progress Agentic RAG service. This connection is used to send user inputs and receive responses from the agent, but also to stream intermediate results, or to let the agent ask for more information to the user (like asking for a missing parameter, or to trigger an OAuth flow).

The typical URL to open the websocket connection is wss://<region>.dp.progress.cloud/api/v1/agent/<agent-id>/session/ephemeral/ws?eph-token=<ephemeral-token>&workflow_id=<workflow-id>. The workflow_id query parameter is optional and can be used to specify a workflow to execute. If not provided, the default workflow of the agent will be executed.

Opening a connection

Calling the /ws endpoint with GET will open a websocket connection. It requires an authentication token to be passed as a query parameter (eph-token) that can be obtain from the /ephemeral_token (see Create an ephemeral token for more details).

You can then send a message to the websocket connection with the following format:

{
question: string;
operation: 0 | 1; // 0 for question, 1 for quit
chat_history?: { question: string; answer: string }[]; // optional, can be used to provide the previous chat history
}

The initial message must have the operation field set to 0 and contain the user input in the question field. The agent will then process the question and send back responses through the websocket connection. If at any point you want to end the interaction, you can send a message with the operation field set to 1. If you are implementing a chat interface, you can also include the previous chat history in the chat_history field to provide more context to the agent. The chat_history field is an array of objects, each containing a question and an answer field.

warning

To effectively utilize the chat history in your workflow we recommend having the following agents:

  • Rephrase agent with the history option enabled: This enables enriching the query with information from the history.
  • Summarize agent with the conversational option enabled: This will produce a final answer that flows with the existing chat, instead of a standalone answer.

Messages

The messages sent by the agent through the websocket connection can have different contents depending on the type of response:

interface AragAnswer {
operation: AnswerOperation;
exception: ARAGException | null;
answer: string | null;
answer_citations: Memory.Citations | null;
agent_request: string | null;
generated_text: string | null;
step: Memory.Step | null;
possible_answer: Memory.Answer | null;
context: Memory.Context | null;
seqid: number | null;
original_question_uuid: string | null;
actual_question_uuid: string | null;
feedback: Feedback | null;
oauth: OAuthRedirection | null;
data_visualizations: Memory.DataVisualization[] | null;
streaming_response_chunk: StreamingChunk | null;
reasoning: StreamingChunk | null;
}

enum AnswerOperation {
answer = 0,
quit = 1,
start = 2,
done = 3,
error = 4,
agent_request = 5,
answer_chunk = 6,
reasoning = 7,
}

interface ARAGException {
detail: string;
}

interface Feedback {
request_id: string;
feedback_id: string;
question: string;
module: string;
agent_id: string;
data: any;
timeout_ms: number;
response_schema?: JSONSchema4;
get_credentials?: { [key: string]: string };
credentials?: OAuthCredentials;
}

interface OAuthCredentials {
[key: string]: { [key: string]: any };
}

interface OAuthRedirection {
oauth_url: string;
}

interface StreamingChunk {
text: string;
last: boolean;
}

namespace Memory {
interface Answer {
answer: string;
original_question_uuid?: string | null;
actual_question_uuid?: string | null;
module: string;
agent_path: string;
}

interface Citations {
metadata: {
[block: string]: {
chunk_index: number | null;
context_id: string;
origin_urls: string[];
};
};
}

interface Chunk {
chunk_id: string;
title?: string | null;
source?: string | null;
text: string;
labels: string[];
url: string[];
metadata?: { [key: string]: any } | null;
action?: string | null;
origin_url?: string | null;
origin_agent?: string | null;
}

interface Context {
id: string;
actual_question_uuid?: string | null;
agent: string;
chunks: Chunk[];
citations: string[] | null;
images: Record<string, any>;
missing?: string | null;
original_question_uuid?: string | null;
question: string;
source: string;
structured: string[];
summary: string;
title?: string | null;
agent_id: string;
}

interface DataVisualization {
type: 'vega_lite';
vega_lite_obj: { [key: string]: any };
}

interface Step {
original_question_uuid?: string | null;
actual_question_uuid?: string | null;
module: string;
title: string;
value?: string | null;
agent_path: string;
reason?: string | null;
timeit: number;
input_nuclia_tokens?: number | null;
output_nuclia_tokens?: number | null;
error?: string | null;
}
}

Citations

The answer_citations field in the AragAnswer interface contains the citations related to the answer provided by the agent. Each citation has a block id which is referring to the block-AA, block-AB, etc. mentioned in the generated answer. The value of the citation has a context_id entry that is referring to the corresponding Context message sent previously by the agent, and that contains the actual content of the citation (in the chunks field). The frontend can then use this information to display the citations in the answer, and to provide more details about them when the user clicks on them.

Note: implementation example of how to handle citations in the frontend

Agent-to-user interactions

The feedback field in the AragAnswer interface allows the agent to send a request to the user through the websocket connection. This can be used to ask for missing information, or to get OAuth credentials.

Note: The message also contains a timeout_ms field that indicates the time the agent will wait for the user's response before timing out. If the user does not respond within this time, the agent will continue its processing without the required information.

For missing information, the message sent by the agent will contain a feedback object with a question field that contains the question to ask to the user, and a response_schema field that contains a JSON schema describing the expected format of the user's response. The frontend can then use this information to display a form to the user and collect the required information. Once the information is collected, the frontend must send it back to the agent through the websocket connection in a message with the following format:

{
request_id: "abc-123", // the request_id received in the feedback message
response: JSON.stringify(data), // the data respecting the response_schema sent by the agent
}

For OAuth credentials, there is fist a message with an oauth field indicating the OAuth url (in oauth_url). The frontend must open this URL and then wait for redirection. After beign redirected to the frontend app and once the websocket connection has been restored, the agent will send a feedback message with the question "Get credentials". The frontend must then send the obtained credentials back to the agent through the websocket connection in a message with the following format:

{
request_id: "abc-123", // the request_id received in the feedback message
existing_credentials: {
[key: string]: string; // the keys are the same as the ones sent in the get_credentials field of the feedback message
}
}

SDK (and implementation example)

Our JavaScript SDK provides a convenient way to interact with the websocket connection. Here's an example of how to use it:

const nucliaAPI = new Nuclia(nucliaOptions);
nucliaAPI.arag.interact('ephemeral', question, 'default', 'WS', undefined, true).subscribe({
next: (response) => {
console.log('Received response:', response);
},
error: (error) => {
console.error('Error:', error);
},
complete: () => {
console.log('Interaction complete');
},
});

If you do not want to use our SDK, its corresponding implementation can be used for inspiration:

https://github.com/nuclia/frontend/blob/main/libs/sdk-core/src/lib/db/retrieval-agent/retrieval-agent.ts