Embeddable chat widget that adds a <kuralle-widget> Web Component to any web page.
Include the built embed script on your page:
<script src="/path/to/widget.js"></script>Or install for programmatic use:
npm install @kuralle-agents/widgetRegisters a <kuralle-widget> custom element backed by a Preact component. The widget resolves agent configuration from an HTTP endpoint, opens a WebSocket connection to the agent, and renders a floating chat UI with streaming, message queuing, and auto-reconnect.
<kuralle-widget>— HTML custom element. Accepts HTML attributes for agent endpoint, theme, position, and colors.WidgetClient— programmatic client class. Fetches agent config fromGET /api/agent/:agentId, connects via WebSocket, and exposes callback-based APIs for messages, streaming state, connection state, and suggestions.AgentConfig/Message— types for the resolved agent configuration and chat messages.
<kuralle-widget
agent-url="https://your-api.example.com"
agent-id="support"
position="bottom-right"
theme="light"
title="Chat with us"
subtitle="We're here to help">
</kuralle-widget>The widget calls GET /api/agent/support on agent-url to resolve the WebSocket URL, then connects directly to the agent.
import { WidgetClient } from '@kuralle-agents/widget';
const client = new WidgetClient('https://your-api.example.com', 'support');
const config = await client.initWidget();
client.onMessages((messages) => console.log(messages));
client.onConnectionChange((connected) => console.log('connected:', connected));
await client.sendMessage('Hello!');
// Cleanup
client.dispose();| Attribute | Description |
|---|---|
agent-url |
HTTP base URL for the agent config endpoint (required) |
agent-id |
Agent identifier (required) |
position |
bottom-right (default), bottom-left, top-right, top-left |
theme |
light (default) or dark |
title |
Header title |
subtitle |
Header subtitle |
accent-color |
Primary accent color |
base-color |
Base color for theming |
button-base-color |
Launcher button base color |
button-accent-color |
Launcher button accent color |
provider |
Transport backend: syrinx, platform, elevenlabs, vapi, livekit, pipecat |
voice-url |
Syrinx WebSocket URL (Syrinx provider) |
public-key |
Vapi public API key |
assistant-id |
Vapi assistant ID (also used by ElevenLabs when provider=elevenlabs) |
token |
LiveKit access token |
ws-url |
LiveKit WebSocket URL |
connect-endpoint |
Pipecat bot connect endpoint |
mode |
chat (default) or voice — initial panel when voice is available |
The widget exposes a single AgentTransport port. Each provider is a lazy-loaded adapter under src/transport/adapters/; createTransport() in src/transport/factory.ts resolves the provider and dynamically imports only the adapter you use. Vendor SDKs (@elevenlabs/client, @vapi-ai/web, livekit-client, @pipecat-ai/client-js, etc.) are optional peer dependencies — install only the SDK for your chosen provider; the widget bundle does not ship them.
| Provider | Required attributes | text | audio | selfHandlesMedia | Notes |
|---|---|---|---|---|---|
syrinx |
voice-url |
yes | yes | no | Default when voice-url is set and provider is omitted. Widget captures mic and plays audio via jitter buffer. |
platform |
agent-url, agent-id |
yes | no | no | Chat-only Kuralle platform transport via GET /api/agent/:agentId. |
elevenlabs |
provider=elevenlabs, agent-id |
yes | yes | yes | Requires @elevenlabs/client at runtime. |
vapi |
public-key, assistant-id |
yes | yes | yes | Requires @vapi-ai/web at runtime. Set provider=vapi explicitly. |
livekit |
ws-url, token |
yes | yes | yes | Requires livekit-client at runtime. Set provider=livekit explicitly. |
pipecat |
connect-endpoint |
yes | yes | yes | Requires @pipecat-ai/client-js and @pipecat-ai/small-webrtc-transport. Set provider=pipecat explicitly. |
Load the built widget once, then mount <kuralle-widget> with the attributes your provider needs.
<script type="module" src="/path/to/dist/widget.js"></script>
<kuralle-widget
provider="syrinx"
voice-url="wss://voice.example.com/studio"
title="Chat with us">
</kuralle-widget><script type="module" src="/path/to/dist/widget.js"></script>
<kuralle-widget
provider="platform"
agent-url="https://your-api.example.com"
agent-id="support"
title="Chat with us">
</kuralle-widget><script type="module" src="/path/to/dist/widget.js"></script>
<kuralle-widget
provider="elevenlabs"
agent-id="your-elevenlabs-agent-id"
title="Chat with us">
</kuralle-widget><script type="module" src="/path/to/dist/widget.js"></script>
<kuralle-widget
provider="vapi"
public-key="pk_your_vapi_public_key"
assistant-id="asst_your_assistant_id"
title="Chat with us">
</kuralle-widget><script type="module" src="/path/to/dist/widget.js"></script>
<kuralle-widget
provider="livekit"
ws-url="wss://livekit.example.com"
token="your-livekit-access-token"
title="Chat with us">
</kuralle-widget><script type="module" src="/path/to/dist/widget.js"></script>
<kuralle-widget
provider="pipecat"
connect-endpoint="https://pipecat.example.com/connect"
title="Chat with us">
</kuralle-widget>A static provider switcher lives at example/index.html. Build the widget, then serve the package root:
npm run exampleOpen http://localhost:4173/example/ and switch providers to see the same element render for each backend. Placeholder credentials are used; real conversations require valid provider config.