Skip to main content

Web SDK quickstart

Browser clients should normally talk to a same-origin backend or gateway, not directly to a daemon exposed on the public internet. Local development can call the daemon or kheish-web gateway from loopback origins. Hosted web apps should proxy daemon requests through a backend that owns the daemon URL and bearer token.

Submit a run

const daemonBase = "http://127.0.0.1:4000";
const token = "<admin-or-scoped-token>";

const sessionResponse = await fetch(`${daemonBase}/v1/sessions`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${token}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({ session_id: "demo" }),
});

if (!sessionResponse.ok && sessionResponse.status !== 409) {
  throw new Error(await sessionResponse.text());
}

const response = await fetch(`${daemonBase}/v1/sessions/demo/runs`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${token}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    input_items: [
      {
        type: "text",
        text: "Reply with exactly WEB_OK.",
      },
    ],
    source_plugin: "web",
    source_kind: "browser",
    actor_id: "operator",
  }),
});

if (!response.ok) {
  throw new Error(await response.text());
}

const run = await response.json();
content can be omitted when input_items carries the full ordered input.

Inspect a run

const runResponse = await fetch(`${daemonBase}/v1/runs/${encodeURIComponent(run.run_id)}`, {
  headers: {
    authorization: `Bearer ${token}`,
  },
});

const latestRun = await runResponse.json();

Stream run events

Native EventSource cannot set custom authorization headers. Use one of these patterns:
  • same-origin backend session auth that injects the daemon bearer token server-side
  • a gateway endpoint that accepts the browser request and forwards Authorization
  • fetch plus readable-stream parsing when you control the request headers
Example with a same-origin gateway:
const events = new EventSource(`/api/kheish/v1/runs/${encodeURIComponent(run.run_id)}/stream`);

events.addEventListener("run_updated", (event) => {
  console.log(JSON.parse(event.data));
});

events.onerror = () => {
  events.close();
};

CORS and gateway notes

The daemon’s built-in browser CORS policy is intentionally loopback-oriented. By default it allows common local origins and the headers needed for bearer auth, JSON, and the local web gateway:
  • authorization
  • content-type
  • x-kheish-daemon-token
  • x-kheish-daemon-url
For a fixed local web app, restrict the daemon to exact browser origins:
./target/debug/kheish-daemon serve \
  --http-cors-allow-origin http://localhost:5173
Use KHEISH_HTTP_CORS_ALLOW_ORIGINS for the same comma-delimited setting in deployed environments. The daemon rejects wildcard, non-loopback, and path-bearing origins. For kheish-web, the gateway target defaults to KHEISH_DAEMON_URL. A browser-supplied x-kheish-daemon-url is accepted by default only when it matches that configured target. To let operators choose a different local daemon from the browser UI, set KHEISH_ALLOW_CLIENT_DAEMON_URLS=true. To permit non-loopback browser-selected daemon targets, also set KHEISH_ALLOW_REMOTE_DAEMON_URLS=true and restrict KHEISH_WEB_TRUSTED_ORIGINS.