Chat agents & widget.
AgentClient sends messages to a conversational agent and returns its replies.
ChatWidget puts the same conversation in a chat bubble on your web page. Both come
with @olbrain/js-sdk.
AgentClient and the Olbrain client are separate.
Both call https://webhook.olbrain.com, but they report errors differently, so don't
mix their options. This page describes @olbrain/js-sdk 1.4.0; earlier
versions called a host that no longer exists, so upgrade.
Install
npm install @olbrain/js-sdk
It needs a global fetch, AbortController, and TextDecoder — Node.js 18+ or any modern browser.
Send a message
import { AgentClient } from '@olbrain/js-sdk';
const client = new AgentClient({
agentId: 'your-agent-id',
apiKey: process.env.OLBRAIN_API_KEY!,
});
const sessionId = await client.createSession({ title: 'Support chat', userId: 'u_42' });
const reply = await client.sendAndWait(sessionId, 'Hello!');
if (reply.success) console.log(reply.text);
else console.error(reply.error);
client.close();
| Option | Type | Description |
|---|---|---|
agentId | string | Required. The agent to talk to. |
apiKey | string | Required. An Access Key (ak_, the only kind issued today; sk_live_, org_live_, sk_ and org_ still pass validation). |
baseUrl | string | Defaults to https://webhook.olbrain.com. |
Chat calls are POST /api/agents/webhook/{agentId}; session reads are
GET /api/agents/{agentId}/sessions/{sessionId} and …/messages. Every call
sends Authorization: Bearer <apiKey>, and a key limited to one agent gets
404 for any other. Check reply.success as well as catching
errors — a 200 can still carry success: false
and an error.
Methods
| Method | Returns | Notes |
|---|---|---|
createSession({ title?, userId?, metadata? }) | Session id | Sends title (default 'Chat Session') to the agent as the first message. |
sendAndWait(sessionId, message, { metadata?, timeout? }) | ChatResponse | Waits for the reply. timeout is in milliseconds, default 30000. An empty message throws ValidationError. |
send(sessionId, message) | Nothing | Same request; waits for the server, then discards the reply. |
listen(sessionId, onMessage, onError?) | Nothing | Polls the session's messages every 2 seconds and calls onMessage once for each new one (earlier messages are not replayed). A refused read goes to onError and is retried with backoff from 5 to 60 seconds. |
stopListening(sessionId) | Nothing | Stops one listener. |
close() | Nothing | Stops every listener. |
getSession(sessionId) | SessionInfo | Throws SessionNotFoundError for an unknown session (or another agent's). |
getMessages(sessionId, limit?) | Message[] | Oldest first, at most 200. Throws on error. |
getSessionStats(sessionId) | SessionStats | Message count, total tokens and timestamps. Throws on error. |
updateSession(sessionId, { title?, metadata?, status? }) | — | Always throws OlbrainError: the API has no endpoint to change a session. |
deleteSession(sessionId) | — | Always throws OlbrainError: the API has no endpoint to delete a session. |
Responses
interface ChatResponse {
text: string; sessionId: string; success: boolean;
tokenUsage?: {
promptTokens: number; completionTokens: number; totalTokens: number; cost?: number;
};
modelUsed?: string; responseTimeMs?: number; error?: string;
}
interface Message {
role: 'user' | 'assistant'; content: string; timestamp: string;
metadata?: Record<string, any>;
}
Errors
| Class | When |
|---|---|
AuthenticationError | 401 or 403. |
SessionNotFoundError | 404. sessionId names the session. |
RateLimitError | 429. retryAfter holds the seconds to wait, when the server sends it. |
NetworkError | Any other error status (statusCode holds it), or the request failed. |
ValidationError | A missing or badly prefixed key, an empty agentId, or an empty message. |
A timed-out request throws the runtime's AbortError, which is not an OlbrainError.
Embed a chat widget
<script src="https://unpkg.com/@olbrain/js-sdk@1.4.0/dist/widget.widget.global.js"></script>
<script>
const widget = new OlbrainWidget.ChatWidget({ agentId: '…', apiKey: 'ak_…' });
widget.mount(); // or widget.mount('#chat')
</script>
Anyone who loads the page can read the widget's apiKey and use it to call, and
bill, your agent. On a public website, use the website chat embed code from the
agent's Website channel instead (Alchemist's hand-over shows it too); it is locked to your site's
domains. Use ChatWidget with a key only for internal tools or testing, with a key
limited to one agent.
| Option | Default | Description |
|---|---|---|
agentId, apiKey | — | Required. |
position | 'bottom-right' | Or 'bottom-left', 'custom'. |
theme | 'auto' | Or 'light', 'dark'. |
primaryColor | '#4f46e5' | |
title | 'Chat with us' | |
greeting | 'Hi! How can I help you today?' | |
placeholder | 'Type your message...' | |
autoOpen | false | |
persistSession | true | Keeps the session id in localStorage. |
target | document.body | |
onMessage(msg) | — | Called for every user and assistant message. |
baseUrl | AgentClient's |
Methods: mount(target?), unmount(), open(),
close(), and sendMessage(text), which is ignored while a reply is
pending. ChatWidget is not in the main package entry — load it from the widget
bundle as above.