Headless: @karta/widget
KartaAgentClient is a transport- and UI-agnostic client. Zero runtime
dependencies, ESM-only, strict TypeScript. It talks to the Managed Agents
consumer API by default (the richest token-authed surface: decoupled
POST-event / GET-stream gives reload-resume and tool confirmation), with the
OpenAI Responses API as a portable fallback.
Methods
createSession(): Promise<{ sessionId }>- open a Managed Agents session.sendMessage(text): AsyncGenerator<AgentEvent>- ensure a session, post the message, stream the turn untildone/error.stream(fromSeq?): AsyncGenerator<AgentEvent>- low-level resume of an in-flight turn from a cursor.resume(sessionId): Promise<AgentEvent[]>- adopt an existing session, rebuild its cursor from event history, and return its prior events (normalizedAgentEvents) so a UI can rebuild the transcript.listSessions(): Promise<SessionSummary[]>- the end-user’s past conversations, newest first, for a session sidebar.openSession(sessionId): Promise<TranscriptMessage[]>- reopen a past conversation: load its transcript for display and adopt the session so the nextsendMessagecontinues it.newSession(): void- drop the active session so the nextsendMessageopens a fresh one.confirmTool(requestId, decision): Promise<void>- respond to aninput_requiredpause whosekindis"tool_permission".decisionis one of"approve_once"(allow this one call),"approve_session"(allow this and the rest of the session), or"deny".answerQuestion(requestId, answers): Promise<void>- respond to aninput_requiredpause whosekindis"user_question"(the agent asked the user something). Render the pause’squestionsas choices, then passanswersas an object keyed by question text; for amultiSelectquestion join the chosen labels with", ". Answering never grants a tool for the session.uploadFile(name, contentBase64): Promise<string>- upload a file to the session; returns its workspace-relative path. Opens a session first if none exists.interrupt(): Promise<void>- ask the server to stop the current turn.identify(user): void- set soft / verified identity, applied on the nextcreateSession.shutdown(): void- abort all in-flight work and close the client.
Authentication
Pass exactly one auth source: a publishableembedKey (the client exchanges it
at /v1/embed/session-tokens), a static token, a tokenEndpoint URL the
client GETs for { token }, or a refreshable tokenFn:
React: @karta/react
A thin layer over @karta/widget with two entry points. react and
react-dom (>=18) are peer dependencies.
<KartaWidget/> - the prebuilt widget as a component
document.body as an iframe (the agent-chat app in widget mode),
so <KartaWidget/> itself puts nothing in your React tree. It is SSR-safe
(mounts in a client-only effect) and
re-mounts only when an identity-defining prop changes (agent, embedKey,
baseUrl, token, tokenEndpoint, transport, user.id,
user.identityToken) - changing theme or a callback updates in place without
dropping the conversation.
Wire host-page events via callback props (onReady, onOpen, onClose,
onSessionStarted, onMessageSent, onMessageReceived, onUnread,
onEscalate, onError), and drive it from a ref:
open(), close(), and sendMessage(text).
<KartaWidget/> does not accept tokenFn or model. For a refreshable token
function or a custom model, build a custom UI with useKartaAgent() below,
which exposes the full client option surface.useKartaAgent() - build a custom UI
useKartaAgent() returns { messages, send, status, error, sessionId, reset }:
messages: ChatMessage[]-{ id, role, text, tools?, streaming? }. For an agent message,textis cumulative and is REPLACED on each event (the hook handles this - never concatenate).send(text)- appends a user message and a streaming agent message, then consumes the turn.status-'idle' | 'streaming' | 'error'.error- theErrorfrom the last failed turn (carriescodewhen present).sessionId- the backing session id once a turn has started.reset()- clears the transcript and aborts any in-flight stream.
reset().
Next
Identity
Soft vs verified, and the HMAC scheme the
user/identify fields feed.Security & privacy
The credential boundaries and the data path.

