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/react

The 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.