React SDK
The @informedai/react package provides drop-in React components for embedding AI-powered assistants and chatbots in your application.
Installation#
npm install @informedai/reactThe SDK has zero external dependencies and works with React 18+.
InformedAssistant#
The primary component for AI-powered document editing. It creates a session for a document type and guides users through filling in each field.
Props#
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| documentTypeId | string | Yes | Document type ID to work with |
| apiUrl | string | No | API base URL (defaults to production) |
| accessKey | string | No | Bearer token for authentication (pak_ key) |
| externalId | string | No | Your object's ID for idempotent document linking |
| initialData | Record<string, unknown> | No | Current field values to sync before starting |
| persistSession | boolean | No | Persist session in localStorage (default: true when externalId is set) |
| sessionId | string | No | Existing session ID to resume |
| onReady | (ctx: WidgetReadyContext) => void | No | Called when widget loads with document type schema |
| onFieldApply | (field: string, value: unknown) => void | No | Called when the user applies a field value |
| onSessionChange | (session: Session) => void | No | Called when session state changes |
| onError | (error: Error) => void | No | Called on error |
| getCurrentFieldValues | () => Record<string, unknown> | No | Returns current form values (called before each message) |
| theme | Partial<WidgetTheme> | No | Theme overrides |
| position | 'bottom-right' \| 'bottom-left' \| 'inline' | No | Widget position (default: 'inline') |
| defaultCollapsed | boolean | No | Start widget collapsed |
| className | string | No | CSS class name |
Minimal Example#
import { InformedAssistant } from '@informedai/react';
function Editor() {
return (
<InformedAssistant
documentTypeId="dt_abc123"
onFieldApply={(field, value) => {
// Update your form with the AI-generated value
form.setValue(field, value);
}}
/>
);
}Full Example#
import { InformedAssistant } from '@informedai/react';
function Editor({ recordId }: { recordId: string }) {
const form = useForm();
return (
<InformedAssistant
documentTypeId="dt_abc123"
externalId={recordId}
initialData={form.getValues()}
getCurrentFieldValues={() => form.getValues()}
onFieldApply={(field, value) => {
form.setValue(field, value);
}}
onReady={(ctx) => {
console.log('Schema:', ctx);
}}
theme={{ primaryColor: '#8b5cf6' }}
position="bottom-right"
/>
);
}WebsiteChatbot#
An embeddable chatbot powered by a website agent. Uses domain-based authentication — no API key needed.
Props#
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| agentId | string | Yes | Website agent ID |
| apiUrl | string | No | API base URL |
| theme | Partial<WebsiteChatbotTheme> | No | Theme overrides |
| position | 'bottom-right' \| 'bottom-left' \| 'inline' | No | Widget position |
| defaultCollapsed | boolean | No | Start collapsed |
| title | string | No | Widget title |
| placeholder | string | No | Input placeholder text |
| className | string | No | CSS class name |
Example#
import { WebsiteChatbot } from '@informedai/react';
function SupportPage() {
return (
<WebsiteChatbot
agentId="wa_abc123"
title="Help & Support"
position="bottom-right"
/>
);
}AdminChatbot#
A chatbot for querying your workspace's knowledge library directly. Requires an API key with admin_chatbot scope.
Props#
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| apiKey | string | Yes | API key with admin_chatbot scope (aak_ key) |
| apiUrl | string | No | API base URL |
| systemPrompt | string | No | Custom system prompt |
| allowEditSystemPrompt | boolean | No | Let users edit the system prompt in UI |
| theme | Partial<AdminChatbotTheme> | No | Theme overrides |
| position | 'bottom-right' \| 'bottom-left' \| 'inline' | No | Widget position |
| defaultCollapsed | boolean | No | Start collapsed |
| title | string | No | Widget title |
| placeholder | string | No | Input placeholder text |
| className | string | No | CSS class name |
Example#
import { AdminChatbot } from '@informedai/react';
function KnowledgeExplorer() {
return (
<AdminChatbot
apiKey="aak_your_key"
title="Knowledge Library"
systemPrompt="You are a helpful assistant that answers questions about our products."
position="inline"
/>
);
}SmartQuestionnaire#
A step-by-step questionnaire widget that guides users through questions, matches answers against the knowledge base, and streams results. Option clicks require zero AI calls — only free-text answers and final matching hit the API.
Props#
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| questionnaireId | string | Yes | Questionnaire ID |
| apiUrl | string | No | API base URL |
| theme | Partial<SmartQuestionnaireTheme> | No | Theme overrides |
| position | 'bottom-right' \| 'bottom-left' \| 'inline' | No | Widget position |
| defaultCollapsed | boolean | No | Start collapsed |
| title | string | No | Widget title |
| placeholder | string | No | Placeholder for free-text input |
| className | string | No | CSS class name |
Example#
import { SmartQuestionnaire } from '@informedai/react';
function ProductFinder() {
return (
<SmartQuestionnaire
questionnaireId="sq_abc123"
title="Find the Right Product"
position="inline"
/>
);
}Advanced: InformedAIProvider#
For full control over the assistant lifecycle, wrap your components with InformedAIProvider and use the useInformedAI hook.
import { InformedAIProvider, useInformedAI } from '@informedai/react';
function App() {
return (
<InformedAIProvider config={{ documentTypeId: 'dt_abc123' }}>
<MyCustomUI />
</InformedAIProvider>
);
}
function MyCustomUI() {
const {
session,
document,
isStreaming,
streamingContent,
sendMessage,
applyPendingValue,
skipTask,
} = useInformedAI();
return (
<div>
<p>Active task: {session?.activeTask ?? 'None'}</p>
{isStreaming && <p>{streamingContent}</p>}
<button onClick={() => sendMessage('Write a compelling title')}>
Ask AI
</button>
<button onClick={applyPendingValue}>Apply</button>
<button onClick={skipTask}>Skip</button>
</div>
);
}useInformedAI Return Values#
| Property | Type | Description |
|----------|------|-------------|
| session | Session \| null | Current session state |
| document | Document \| null | Current document |
| documentType | DocumentType \| null | Document type with schema |
| isLoading | boolean | Whether session is loading |
| isStreaming | boolean | Whether AI is streaming a response |
| error | Error \| null | Current error |
| streamingContent | string | Live streamed content |
| sendMessage | (msg: string) => Promise<void> | Send a message |
| sendQuickAction | (action: string) => Promise<void> | Trigger a quick action |
| applyPendingValue | () => Promise<void> | Apply the pending field value |
| skipTask | () => Promise<void> | Skip the current task |
| startNewSession | () => Promise<void> | Start a fresh session |
| endSession | () => Promise<void> | End the current session |
| clearError | () => void | Clear the error state |
Theming#
All components accept a theme prop for visual customization. Pass a partial object — unset properties use defaults.
import type { WidgetTheme } from '@informedai/react';
const customTheme: Partial<WidgetTheme> = {
primaryColor: '#8b5cf6',
backgroundColor: '#fafafa',
textColor: '#1c1917',
borderRadius: '8px',
fontFamily: 'Inter, system-ui, sans-serif',
};
<InformedAssistant
documentTypeId="dt_abc123"
theme={customTheme}
/>WidgetTheme Properties#
| Property | Default | Description |
|----------|---------|-------------|
| primaryColor | '#f59e0b' | Primary accent color |
| backgroundColor | '#ffffff' | Widget background |
| textColor | '#1c1917' | Text color |
| borderRadius | '12px' | Corner rounding |
| fontFamily | 'system-ui, -apple-system, sans-serif' | Font stack |
AdminChatbot defaults to blue (#3b82f6) and SmartQuestionnaire defaults to purple (#8b5cf6) for primary color. Each component has its own theme type with the same properties.
Session Persistence#
The SDK can persist sessions across page reloads using localStorage.
Automatic Persistence#
When you provide an externalId, sessions are automatically persisted and resumed:
<InformedAssistant
documentTypeId="dt_abc123"
externalId="my-record-123"
// persistSession defaults to true when externalId is set
/>Manual Session Resume#
You can also resume a specific session by ID:
<InformedAssistant
documentTypeId="dt_abc123"
sessionId="sess_abc123"
/>Data Sync#
Use initialData to sync your form's current values before the AI starts working. This ensures the assistant sees the latest state even if the user has unsaved changes:
<InformedAssistant
documentTypeId="dt_abc123"
externalId="my-record-123"
initialData={form.getValues()}
getCurrentFieldValues={() => form.getValues()}
/>The getCurrentFieldValues callback is called before each message so the AI always has up-to-date context.