SDK Requests
Handle requests with the SDK
The Telygent SDK offers two primary ways to communicate with the AI: SSE Streaming for a dynamic, real-time user experience, and Direct Requests for simple, atomic operations.
Streaming Requests (SSE)
Streaming is the recommended method for conversational interfaces. It uses Server-Sent Events (SSE) to push progress updates, tool-call statuses, and message fragments to the client as they are generated.
Method
Best For
1// Example: Implementing an SSE route in Express
2app.post("/stream", async (req, res) => {
3 // Required headers for SSE
4 res.setHeader("Content-Type", "text/event-stream");
5 res.setHeader("Cache-Control", "no-cache");
6 res.setHeader("Connection", "keep-alive");
7
8 // initiate the client, redis store, adapter, user context and registry
9 ...
10
11 const {question, conversationId} = req.body;
12
13 let streamClosed = false;
14
15 const handleEvent = (event: StreamEvent) => {
16 if (streamClosed) {
17 return;
18 }
19 const filtered: Record<string, unknown> = {
20 phase: event.phase,
21 status: event.status,
22 content: event.content,
23 conversationId: event.conversationId,
24 visualizations: event.visualizations,
25 summaryCards: event.summaryCards,
26 };
27
28 res.write(`data: ${JSON.stringify(filtered)}\n\n`);
29 if (event.phase === "final" || event.phase === "error") {
30 streamClosed = true;
31 res.end();
32 }
33 };
34
35 await client.queryStream(
36 {
37 question,
38 conversationId,
39 userContext: {
40 userId: conversationId,
41 firstName: userContext.userFirstName,
42 lastName: userContext.userLastName,
43 },
44 },
45 handleEvent
46 );
47
48 if (!streamClosed) {
49 res.end();
50 }
51
52});Important things to note
- Always close the stream when you receive a
finalorerrorevent, and also abort any in-flight stream when a new request starts. - Make sure you clean up on unmount to prevent dangling network connections and memory leaks.
- If your client uses a streaming adapter (SSE, fetch reader, etc.), explicitly cancel the reader after completion to free resources.
Direct Requests (non-streaming)
For tasks where real-time feedback isn't necessary—like generating a report in the background or performing a quick lookup—use a direct request. The SDK will wait for the full reasoning process to finish before returning a single JSON object.
Method
Best For
1app.post("/ask", async (req, res) => {
2 const { question, conversationId } = req.body;
3
4 // initiate the client, redis store, adapter, user context and registry
5 ...
6
7 const response = await client.query({
8 question,
9 conversationId,
10 userContext,
11 });
12
13 res.json(response);
14});Context
When sending a query, the userContext object is a very critical part of the payload. It acts as the "Identity Token" that the DB Adapter uses to resolve the requiredFilterswe defined in the Registry.
1const response = await client.query({
2 question: "Show me recent transactions",
3 conversationId: "conv_123",
4 userContext: {
5 // These keys must match the 'contextKey' in your Registry
6 userId: "user_1",
7 tenantId: "tenant_1",
8 email: "user@example.com",
9 },
10});Reloading Conversation History
To maintain context across browser refreshes or to hydrate a "Conversation History" side panel, use the getConversationMessages method. This retrieves the full audit log of a specific thread.
1const messages = await client.getConversationMessages("conv_123");
2console.log(messages);