Skip to content
kitn AI/UI

Connect any backend

Every integration in this section — a raw provider, a gateway, an agent framework, a harness — is the same job underneath: turn your backend’s output into AI/UI’s messages and stream it in. Learn the contract once; everything else is wiring.

<kai-chat> renders a messages array. You own the array; the component reflects it. A message is plain data:

type Message = {
id: string;
role: 'user' | 'assistant';
content: string; // the text, streamed in token by token
reasoning?: { text: string; label?: string };
tools?: ToolCall[]; // tool calls, in order
};
type ToolCall = {
type: string; // the tool name, e.g. 'web_search'
state: 'input-streaming' | 'input-available' | 'output-available' | 'output-error';
input?: Record<string, unknown>; // arguments
output?: Record<string, unknown>; // result, once it returns
toolCallId?: string;
errorText?: string;
};

Three things stream into a message, and they map from any model:

  • Text → append to content.
  • Reasoning → set reasoning.text; it renders in a collapsible reasoning panel.
  • Tool calls → push a ToolCall and advance its state as the arguments arrive (input-streaminginput-available) and the result returns (output-available, or output-error).

Set messages in JavaScript — arrays can’t be HTML attributes — and assign a new array on each update. That reassignment is what drives the re-render.

Your model key never touches the browser. Put a thin route on your own server — call it /api/chat — that authenticates the user, calls the provider, and streams the result back:

browser ──fetch /api/chat──▶ your server ──▶ provider · gateway · harness
▲ │
└────────── stream ───────────────┘
(read tokens into messages)

The browser reads that stream and mutates messages — the Streaming recipe is the exact reader loop. Your server route is the only piece that changes per backend, and that’s what the rest of this section covers, one provider at a time.

<kai-chat> is a web component — it hydrates and runs in the browser. That holds in a plain HTML page, a React app, or a Next.js route (where it’s a client island). The component is the front end; your /api/chat route is the back end. Server rendering emits the tag; the chat comes alive on hydration.

  • Harnesses — wire AI/UI to Mastra, Pi, OpenClaw, or your own agent loop.
  • Streaming — the reader loop that drives messages.
  • kai-chat reference — every prop and event the contract exposes.