Embeddable AI chat widget + React hooks for building AI-powered chat interfaces.
Works with PromptRails, OpenAI, or any custom SSE/WebSocket backend.
- React Hooks —
useChat(),useStreaming(),useAgent(),useApproval() - React Components —
<ChatWindow />,<MessageBubble />,<AgentSteps />,<ApprovalCard /> - Embeddable Widget — One
<script>tag, no React needed. Shadow DOM isolation. - Multi-Provider — PromptRails, OpenAI, or any custom backend
- Agent Step Tracking — Real-time multi-step execution timeline
- Human-in-the-Loop — Built-in approval flow UI
- Streaming — SSE and WebSocket support
- TypeScript — Full type safety
npm install @promptrails/ai-chat<script
src="https://cdn.jsdelivr.net/npm/@promptrails/ai-chat/dist/widget.global.js"
data-provider="promptrails"
data-api-key="pr_your_api_key"
data-agent-id="your_agent_id"
data-title="Support Chat"
data-greeting="Hi! How can I help you today?"
></script>Or initialize programmatically:
<script src="https://cdn.jsdelivr.net/npm/@promptrails/ai-chat/dist/widget.global.js"></script>
<script>
PromptRailsChat.init({
provider: {
type: "openai",
apiKey: "sk-...",
model: "gpt-4o-mini",
},
title: "AI Assistant",
position: "bottom-right",
primaryColor: "#2563eb",
greeting: "Hi! How can I help?",
});
</script>Widget API:
PromptRailsChat.open(); // Open the chat panel
PromptRailsChat.close(); // Close the chat panel
PromptRailsChat.toggle(); // Toggle open/close
PromptRailsChat.destroy(); // Remove from DOMimport { ChatWindow, createPromptRailsProvider } from "@promptrails/ai-chat";
import "@promptrails/ai-chat/styles.css";
const provider = createPromptRailsProvider({
apiKey: "pr_your_api_key",
agentId: "your_agent_id",
});
export default function App() {
return (
<ChatWindow
provider={provider}
title="Support Chat"
placeholder="Ask anything..."
showAgentSteps
showApprovals
/>
);
}import { useChat, createOpenAIProvider } from "@promptrails/ai-chat";
const provider = createOpenAIProvider({
apiKey: "sk-...",
model: "gpt-4o-mini",
});
export default function CustomChat() {
const { messages, isLoading, input, setInput, handleSubmit } = useChat({
provider,
});
return (
<div>
{messages.map((msg) => (
<div key={msg.id} className={msg.role}>
{msg.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a message..."
/>
<button disabled={isLoading}>Send</button>
</form>
</div>
);
}import { createPromptRailsProvider } from "@promptrails/ai-chat";
const provider = createPromptRailsProvider({
apiKey: "pr_...",
agentId: "your_agent_id",
});Supports: streaming, sessions, agent execution tracking, approvals.
import { createOpenAIProvider } from "@promptrails/ai-chat";
const provider = createOpenAIProvider({
apiKey: "sk-...",
model: "gpt-4o-mini", // default
baseUrl: "https://api.openai.com/v1", // default
});Works with any OpenAI-compatible API (DeepSeek, Together, Groq, etc.).
import { createCustomProvider } from "@promptrails/ai-chat";
const provider = createCustomProvider({
sendUrl: "https://your-api.com/chat",
streamUrl: "https://your-api.com/chat/stream", // optional
transport: "sse", // or "websocket"
headers: { Authorization: "Bearer ..." },
});Main hook for chat functionality.
const {
messages, // Message[]
isLoading, // boolean
error, // Error | null
input, // string — controlled input value
setInput, // (value: string) => void
sendMessage, // (content: string) => Promise<void>
handleSubmit, // (e?: FormEvent) => void
retry, // (messageId: string) => Promise<void>
clearMessages,// () => void
setMessages, // (messages: Message[]) => void
} = useChat({ provider, sessionId, initialMessages, onError, onFinish });Low-level streaming control.
const {
isStreaming, // boolean
content, // string — accumulated content
error, // Error | null
startStream, // (generator: AsyncGenerator<StreamEvent>) => void
stopStream, // () => void
} = useStreaming({ onChunk, onComplete, onError });Track multi-step agent executions.
const {
steps, // AgentStep[]
currentStep, // AgentStep | null
isRunning, // boolean
error, // Error | null
trackExecution, // (executionId: string) => void
cancel, // () => void
} = useAgent({ provider, onStepUpdate, onComplete, onError, pollIntervalMs });Human-in-the-loop approval flow.
const {
pendingApprovals, // ApprovalRequest[]
approve, // (id: string, reason?: string) => Promise<void>
reject, // (id: string, reason?: string) => Promise<void>
isDeciding, // boolean
addApproval, // (request: ApprovalRequest) => void
} = useApproval({ provider, onApprovalRequired, onApprovalDecided });| Component | Description |
|---|---|
<ChatWindow /> |
Full chat interface with header, messages, input |
<MessageBubble /> |
Single message bubble with markdown support |
<MessageInput /> |
Auto-resizing textarea with send button |
<TypingIndicator /> |
Bouncing dots animation |
<AgentSteps /> |
Collapsible execution step timeline |
<ApprovalCard /> |
Approve/reject card with reason input |
<ChatHeader /> |
Title bar with online indicator |
<ScrollAnchor /> |
Auto-scroll to newest messages |
Import components individually or from the main entry:
import { ChatWindow } from "@promptrails/ai-chat";
// or
import { ChatWindow } from "@promptrails/ai-chat/components";Tree-shake by importing only what you need:
import { useChat } from "@promptrails/ai-chat/core";
import { ChatWindow } from "@promptrails/ai-chat/components";
import { createOpenAIProvider } from "@promptrails/ai-chat/providers";| Attribute | Description | Default |
|---|---|---|
data-provider |
"promptrails", "openai", "custom" |
required |
data-api-key |
API key for the provider | — |
data-base-url |
Backend API URL | — |
data-agent-id |
PromptRails agent ID | — |
data-model |
LLM model name (OpenAI) | "gpt-4o-mini" |
data-title |
Chat window title | "Chat" |
data-placeholder |
Input placeholder text | "Type a message..." |
data-greeting |
Initial greeting message | — |
data-position |
"bottom-right" or "bottom-left" |
"bottom-right" |
data-primary-color |
Hex color for theming | "#2563eb" |
data-width |
Panel width in pixels | 380 |
data-height |
Panel height in pixels | 600 |
data-z-index |
CSS z-index | 9999 |
npm install # Install dependencies
npm run build # Build library + widget
npm test # Run tests
npm run typecheck # TypeScript check
npm run lint # ESLint + Prettier
npm run lint:fix # Auto-fix lint issues
npm run dev # Watch modeMIT — PromptRails