Skip to content

SSE Backend

createSseAgentBackend creates an AgentBackend that communicates with the agent server via Server-Sent Events (SSE). The backend sends the execute request via HTTP POST and receives streaming responses as SSE events. It also provides a non-streaming execute method for compatibility.

Import

import { createSseAgentBackend } from "@modernpath/agent-ui-react";

Options

interface CreateSseAgentBackendOptions {
  /**
   * Base URL for the agent API.
   * @default ""
   */
  baseUrl?: string;

  /**
   * Custom path builder. Receives the auditing ID and returns the
   * request path (appended to baseUrl).
   * @default (auditingId) => `/api/agents/${auditingId}/execute/stream`
   */
  buildPath?: (auditingId: number) => string;

  /**
   * Function that returns headers to include in every request.
   * Called on each request to support token refresh.
   */
  getHeaders?: () => Record<string, string>;

  /**
   * Custom parser for SSE data fields. Receives the raw string from
   * the `data:` field and returns a parsed object.
   * @default JSON.parse
   */
  parseData?: (raw: string) => any;
}

Return Value

Returns an AgentBackend with both execute and executeStream methods:

interface AgentBackend {
  /**
   * Send an execute request and return the complete response.
   * The SSE backend collects all stream events and returns
   * the final response as a single object.
   */
  execute: (
    request: AgentExecuteRequest,
    signal?: AbortSignal
  ) => Promise<AgentExecuteResponse<any>>;

  /**
   * Send an execute request and stream the response via SSE.
   * Calls `onEvent` for each SSE event received.
   */
  executeStream: (
    request: AgentExecuteRequest,
    onEvent: (event: AgentStreamEvent) => void,
    signal?: AbortSignal
  ) => Promise<void>;
}

Default Path

POST {baseUrl}/api/agents/{auditingId}/execute/stream

SSE Protocol

The server sends events as newline-delimited data: fields. Each line contains a JSON object conforming to AgentStreamEvent:

data: {"type":"delta","content":"The current"}
data: {"type":"delta","content":" temperature is"}
data: {"type":"delta","content":" 21.5 degrees."}
data: {"type":"final","data":{...full response...}}

Stream Event Types

type AgentStreamEvent =
  | { type: "delta"; content: string }
  | { type: "final"; data: AgentExecuteResponse<any> }
  | { type: "error"; error: string; code?: string };
Event Type Description
delta Incremental text content. Append to the current message.
final Complete response object. Marks the end of the stream. Contains the full AgentExecuteResponse including execution details, grounding context, and statistics.
error Error event. Contains an error message and optional error code.

Usage

Basic SSE Backend

import {
  createSseAgentBackend,
  AgentChat,
} from "@modernpath/agent-ui-react";

const backend = createSseAgentBackend({
  baseUrl: "https://api.example.com",
  getHeaders: () => ({
    Authorization: `Bearer ${getToken()}`,
  }),
});

function App() {
  return (
    <AgentChat
      backend={backend}
      auditingId={1}
      agentType="qa-chat"
      title="Streaming Chat"
      stream
    />
  );
}

Custom Path

const backend = createSseAgentBackend({
  baseUrl: "https://api.example.com",
  buildPath: (auditingId) => `/v2/agents/${auditingId}/stream`,
});

Custom Data Parser

const backend = createSseAgentBackend({
  baseUrl: "/api",
  parseData: (raw) => {
    // Handle non-standard JSON encoding
    try {
      return JSON.parse(raw);
    } catch {
      return { type: "delta", content: raw };
    }
  },
});

Using executeStream Directly

import {
  createSseAgentBackend,
  AgentStreamEvent,
} from "@modernpath/agent-ui-react";

const backend = createSseAgentBackend({ baseUrl: "/api" });

async function streamResponse() {
  const controller = new AbortController();

  await backend.executeStream!(
    {
      agentType: "qa-chat",
      prompt: "Explain RAG in simple terms",
    },
    (event: AgentStreamEvent) => {
      switch (event.type) {
        case "delta":
          process.stdout.write(event.content);
          break;
        case "final":
          console.log("\n\nFull response:", event.data);
          break;
        case "error":
          console.error("Stream error:", event.error);
          break;
      }
    },
    controller.signal
  );
}

Non-Streaming Fallback

The SSE backend also implements execute() for non-streaming use. It internally collects all delta events and returns the assembled final response:

const backend = createSseAgentBackend({ baseUrl: "/api" });

// Works without streaming -- collects events internally
const response = await backend.execute({
  agentType: "qa-chat",
  prompt: "Hello",
});
  • HTTP Backend -- non-streaming alternative
  • AgentChat -- component that consumes AgentBackend with stream prop
  • useAgentChat -- hook that consumes AgentBackend with stream option
  • TypeScript Types -- AgentBackend, AgentStreamEvent, AgentExecuteResponse