
createClient.
The widget has two modes:
- Ready-made widget (
mountChatWidget) — a complete floating chat bubble and panel with streaming responses, a processing indicator (animated dots while the agent works), markdown rendering, and image support. One function call and you’re done. - Custom UI (
createClient) — a headless client that handles backend communication, streaming, and markdown rendering while you build the UI entirely yourself.
<script> tag pointing at the Abundly-hosted loader — no npm install or build step required. If you’re building a custom UI or working in a React/Next.js project, install the @abundly/widget npm package instead. Both approaches share the same backend proxy contract.
The examples on this page use the shared hosts
app.abundly.ai (the widget.js loader) and service.abundly.ai (the ABUNDLY_SERVICE_URL your backend proxy calls). Enterprise customers on a dedicated deployment have their own hosts, in the form https://<your-tenant>.app.abundly.ai and https://<your-tenant>.service.abundly.ai.How it works
The widget never talks to Abundly directly. A server-side proxy on your backend holds the API key and forwards requests to Abundly server-to-server:
All upstream requests use header
X-Agent-Access-Key: {API_KEY}. The full upstream URL pattern is {SERVICE_URL}/agents/{AGENT_ID}/widget/{route}.
Streaming: the /chat stream opens as soon as the request is accepted — response headers and a first {"status": "processing"} event arrive before the agent starts its reply, so your proxy can forward the response immediately and a slow agent never looks like an unreachable service. Anything that fails before the stream opens comes back as an ordinary HTTP status code instead.
CORS: the widget runs in the visitor’s browser. If backendUrl points to a different origin than the page, your proxy must allow cross-origin requests. A same-origin route (e.g. /api/abundly on the same host) avoids this entirely.
Setting up
1
Configure the agent
In the Abundly portal, open your agent’s Settings → API Access tab. Turn on Enable widget and choose which capabilities the widget may use. The agent’s API Capabilities and MCP servers are listed separately in the same picker — like capabilities, they are unavailable in widget conversations unless selected. Then create an API access key (starts with
ak_) in the API Keys section — you’ll store this on your server only.You can also configure:- Daily credit limit — a separate cap for widget usage, independent of the agent’s main limit
- Widget instructions — dedicated instructions for widget conversations, replacing the agent’s main instructions (if empty, the agent’s default instructions are used)
- Demo response override — a fixed reply for presentations (skips the LLM)
- Model override — run widget conversations on a specific model
2
Implement the backend proxy
Create a server-side endpoint that the widget can call. It must expose
/status, /chat, and /images/<path> under a single base URL. Each route forwards the request to Abundly with your API key.You need three environment variables (values shown in the portal):See backend proxy examples below for ready-to-use code in Node.js, Express, Next.js, and PHP.
3
Embed the widget
Add the widget script to your page and mount it, pointing at your backend:The loader injects the current versioned widget bundle automatically — your snippet stays the same across releases.For React / Next.js, install the npm package instead:
Backend proxy examples
Pick your backend language — each example creates a self-contained project you can run locally. The frontend embed code is the same for all of them.- Node.js
- Express.js
- Next.js
- PHP
server.js:public/index.html:http://localhost:3000 (port 8080 for PHP). You should see the chat bubble in the bottom-right corner. Click it, type a message, and see the streamed response from your agent.
Configuration
mountChatWidget requires only backendUrl — everything else is optional. Use textOptions to customize labels and uiOptions to match your site’s colors.
Text options
All text options are optional and have sensible defaults.UI options
All color options are optional and default to brand colors. Values accept any valid CSS — named colors, hex, rgba, or gradients.What the ready-made widget handles
mountChatWidget takes care of these concerns automatically:
- Availability check — calls
/statusbefore showing the bubble; stays hidden if the agent is unavailable or the daily limit is exhausted - SSE streaming — character-by-character reveal animation as the response arrives
- Processing indicator — animated dots while the agent is working (tools, sub-agents, or waiting for a response). Internal reasoning text is never shown in the widget.
- Markdown rendering — safe HTML output with XSS protection
- Image support — URL rewriting, preloading, and authenticated image loading through the proxy
- Mobile layout — soft-keyboard detection and layout adjustment
- Auto-resizing input — textarea grows up to three lines
- Rate limiting — displays errors and suspends input on HTTP 429
mountChatWidget returns a handle with two methods:
Custom UI with createClient
If you need full control over the chat interface — your own layout, animations, or interaction model — usecreateClient instead of mountChatWidget. It provides the same streaming and protocol engine without any DOM or styles.
client.checkStatus()— check if the agent is availableclient.sendMessage(text, callbacks)— stream a response via SSE withonChunk,onProcessing,onDone, andonStreamErrorcallbacksclient.resetSession()— clear the server-side session so the next message starts a new conversationclient.renderMarkdown(text)— convert markdown to safe HTML (optional — use your own library instead if you prefer)client.stripPartialMd(text)— clean up half-formed markdown tokens during streaming
Message[] for rendering your UI. The client handles protocol details, session management, URL rewriting, and optionally markdown rendering. You own all markup and styling.
The methods listed above are the most commonly used — the full client API includes additional helpers for image authentication, blob URL management, and more. See the
@abundly/widget package on npm for the complete reference.- Backend first — same proxy as above (
/status,/chat,/images/<path>) - Install the SDK —
npm install @abundly/widget - Create a client —
const client = createClient("/api/abundly") - Build your component — use
client.sendMessagefor streaming,client.renderMarkdownfor replies,client.checkStatusfor availability. Authenticated proxies and inline images require additional client helpers — see the npm package docs for details - Ship it — mount wherever it should live; no
mountChatWidgetrequired
Minimal React example
Minimal React example
@abundly/widget on npm.
Authentication
If your proxy is same-origin and uses session cookies, no extra configuration is needed — cookies flow automatically. For token-based or cross-origin setups, passheaders and/or credentials on the mount call. Both mountChatWidget and createClient accept the same options.
- Bearer / JWT
- Static header
Use the function form so the token is re-read on every request:
headers is applied to every request the widget makes (/status, /chat, and image loads). User-supplied headers override built-in headers with the same name. credentials maps directly to the fetch option.Learn more
API Access
Configure API keys, HTTP endpoints, MCP, and webhooks alongside the widget
@abundly/widget on npm
Full API reference, TypeScript types, and advanced customization
Monitoring
Review widget conversations in the portal chat list and monitor credit usage

