Skip to main content

HttpConnector

Plain REST polling adapter. The simplest deployment — no WebSockets, no SSE, no SignalR. The connector POSTs outgoing messages and GETs new ones on a fixed interval.

import { HttpConnector } from "@chativa/connector-http";

ConnectorRegistry.register(
new HttpConnector({
url: "https://api.example.com/chat",
pollInterval: 2000,
headers: { Authorization: `Bearer ${token}` },
})
);
chatStore.getState().setConnector("http");

Tool calls, GenUI and human-in-the-loop chips work over this connector via the shared JSON frame vocabulary — see Rich frames.

Options

Schema: schemas/connectors/http.schema.json.

FieldDefaultDescription
url (required)Base URL of the chat REST API.
pollInterval2000Polling interval in milliseconds.
headers{}Headers sent with every request.
maxErrors5After this many consecutive fetch errors, stop polling and report disconnect.

Wire format

EndpointMethodRequestResponse
/messages?cursor=...GET{ messages: IncomingMessage[], cursor?: string }
/messagesPOSTOutgoingMessage200 / 201, body ignored
/surveyPOSTSurveyPayload200 / 201, body ignored
/history?cursor=...GET (optional)HistoryResult

The connector tracks the last seen cursor in memory (_cursor) and keeps requesting ?cursor=... to fetch only new messages.

Rich frames in a poll batch

A messages array isn't limited to chat bubbles — it can interleave any rich frame. Polling carries the same vocabulary as the streaming connectors, just a batch at a time:

{
"messages": [
{ "type": "typing", "isTyping": true },
{ "type": "tool_call", "data": { "id": "c1", "name": "get_sales", "status": "running" } },
{ "type": "tool_call", "data": { "id": "c1", "name": "get_sales", "status": "completed", "result": "42 orders" } },
{ "type": "genui", "streamId": "s1", "chunk": { "type": "ui", "component": "sales-chart", "props": { "orders": 42 }, "id": 1 }, "done": true },
{ "type": "text", "id": "m1", "from": "bot", "data": { "text": "Generate the PDF?" }, "actions": [{ "label": "Approve" }] },
{ "id": "m2", "type": "text", "from": "bot", "data": { "text": "Anything else?" } }
],
"cursor": "m2"
}

Everything except the last entry is routed to a dedicated handler; only m1 (as quick-reply chips) and m2 reach the transcript.

GenUI component events are POSTed back to /messages alongside normal sends:

{ "type": "genui_event", "streamId": "s1", "eventType": "form_submit", "payload": { "email": "[email protected]" } }

Because chunks only arrive as fast as you poll, a GenUI stream renders in pollInterval steps rather than smoothly — send fewer, larger chunks here than you would over a socket.

When to use it

Choose HTTP polling when:

  • Your infra already exposes REST and you don't want to deploy a WebSocket layer.
  • Latency tolerance is ≥ 1–2 seconds.
  • You need predictable behaviour through corporate proxies / firewalls.

Pick a streaming connector (SSE, WebSocket, SignalR, or DirectLine) when sub-second latency matters — tool-call traces and GenUI work here too, but they advance one poll at a time.