PAIPAI

createPaiHttpClient()

HTTP/SSE client for a createPai Express receiver.

createPaiHttpClient is the browser (and Node) client for an HTTP-served createPai app. Call .agent(id) to get a typed thread API.

Live watches use SSE. For networks that buffer SSE events, pair the HTTP receiver with createPaiSocketIoServer() and use createPaiSocketIoClient(). Socket.IO can carry incremental watch events over HTTP long-polling when WebSocket is unavailable.

import { createPaiHttpClient } from "@pai/client-http";
import type { AssistantPai } from "@server/http-server";

const paiClient = createPaiHttpClient<AssistantPai>({
  url: "/api/pai",
  headers: () => ({
    "x-user-id": "dev-user",
    "x-workspace-id": "dev",
  }),
});

const assistant = paiClient.agent("main");

Import

import { createPaiHttpClient } from "@pai/client-http";

Signature

function createPaiHttpClient<TPai extends PaiContractShape>(
  options: HttpAgentClientOptions,
): PaiHttpClient<TPai>;

type HttpAgentClientOptions = {
  url: string;
  fetch?: typeof globalThis.fetch;
  headers?: HeadersInit | (() => MaybePromise<HeadersInit>);
  credentials?: RequestCredentials;
  telemetry?: { serializeContext?(): Record<string, string> | undefined };
  streamIdleTimeoutMs?: number;
};

type PaiHttpClient<TPai> = {
  agent<TId extends keyof TPai["agents"] & string>(
    id: TId,
  ): AgentClient<TPai["agents"][TId]>;
};

Parameters

options: HttpAgentClientOptions

url: string

Base URL where the Express PAI receiver is mounted.

fetch?: typeof fetch

Override for tests, workers, or non-browser hosts.

headers?: HeadersInit | (() => MaybePromise<HeadersInit>)

Static or lazy headers, usually auth.

credentials?: RequestCredentials

Browser credential mode for cross-origin requests.

telemetry?: { serializeContext?(): Record<string, string> }

Propagate trace context on outbound requests.

streamIdleTimeoutMs?: number

How long a watch stream may deliver nothing before it is treated as dead. 0 waits forever.

Returns

A PaiHttpClient<TPai>.

Call .agent(id) to select a registered agent. Non-success HTTP/SSE failures that are not a portable PAI error throw PaiHttpError.

PaiHttpError

class PaiHttpError extends Error {
  readonly phase: "response" | "stream";
  readonly status?: number;
  readonly code?: string;
  readonly errorId?: string;
  readonly retryable?: boolean;
}

The transport throws PaiHttpError for a non-success response or established SSE stream failure that is not one of PAI's portable typed domain errors. Network and response-decoding failures use phase: "response"; SSE read, decoding, and malformed-event failures use phase: "stream". status is present when an HTTP response exists and absent when opening the request fails or an already-established stream reports an error.

message, code, retryable, and errorId are client-safe fields. The original server exception is available only through the server diagnostic hook. Known thread error DTOs are reconstructed into their existing portable classes before this fallback is used. Unexpected server metadata is trusted only when it matches PAI's versioned safe-error DTO; proxy and transport details receive a generic message. Caller abort reasons remain unchanged.

try {
  await assistant.thread("thread-1").stop();
} catch (error) {
  if (error instanceof PaiHttpError) {
    showError(error.message, { reference: error.errorId });
  }
}

See Errors.

Learn more

On this page