Embedding Agent Chat

Embed Knowi's Agentic BI chat interface directly into your application. There are two approaches depending on how much control you need over the UI:

  • SSO Chat Embed -- Drop the full Knowi chat interface into your app via iframe. No custom UI needed. Your users get the same chat experience with all built-in features (data sources, suggestions, chat history, themes).

  • Headless Chat API -- Build your own chat UI. Send questions via REST API, get structured responses back. Available in streaming (Server-Sent Events) and synchronous modes.

Interactive Demo -- Try both approaches with a live configuration tool and generated code snippets.


SSO Chat Embed

The SSO embed renders the full Knowi Agentic BI chat inside an iframe using Single Sign-On authentication. This is the fastest way to add AI-powered data chat to your application.

Prerequisites

  • SSO enabled on your Knowi account
  • Your customer SSO token (found in Settings)
  • knowi-api.js included in your page

Step 1: Create an SSO User

Create a user that will interact with the embedded chat. This is typically done server-side when the user logs into your application.

POST /sso/user/create
Content-Type: application/x-www-form-urlencoded

ssoCustomerToken=YOUR_CUSTOMER_SSO_TOKEN
&user=user@example.com
&userToken=a_secret_for_this_user

The response returns an SSO key for the user. Store this -- you'll need it to create sessions.

Step 2: Create a Session Token

Generate a session token each time the user needs to access the embedded chat.

POST /sso/session/create
Content-Type: application/x-www-form-urlencoded

user=user@example.com
&userToken=SSO_KEY_FROM_STEP_1
&expiry=3600

The response is the session token string. Pass this to the embed SDK.

Step 3: Embed the Chat

Include the Knowi embed SDK and render the chat interface:

<script src="https://www.knowi.com/minify/knowi-api.min.js"></script>
<script>
  Knowi.render('#chat-container', {
    type: 'aiConverse',
    url: 'https://www.knowi.com/',
    token: 'SESSION_TOKEN_FROM_STEP_2',
    themeId: 'light',
    view: {
      aiConverseMode: true,
      aiConverseOptions: {
        useSources: 'all',
        chatHistory: 'hidden',
        greeting: 'How can I help you today?',
        suggestions: ['Show revenue by region', 'Create a dashboard']
      }
    }
  });
</script>

Configuration Options

OptionValuesDescription
type'aiConverse'Required. Specifies the chat embed mode.
url'https://www.knowi.com/'Your Knowi instance URL (include trailing slash).
tokenstringSSO session token from Step 2.
themeId'light', 'dark', or custom keyTheme to apply to the embedded chat.

aiConverseOptions

OptionValuesDefaultDescription
useSources'all', 'datasets', 'documents''all'What the AI can search. 'datasets' restricts to structured query data. 'documents' restricts to uploaded documents (PDFs, etc.).
sourcesobjectnoneLimit AI access to specific datasets or documents. Provide datasets array (dataset names or IDs) and/or documents array (document names or IDs). If omitted, all user's datasets/documents are accessible. See example below.
chatHistory'hidden', 'collapsed', 'expanded''hidden'Whether to show the chat history sidebar.
greetingstring'Hi there!'Custom greeting displayed when the chat loads.
suggestionsstring arraynoneSuggested prompts shown below the greeting.
agentsarray of stringsnone (all agents)Restrict which AI agents are available. Pass an array of agent slugs (e.g. ['data-analyst', 'create-dashboard']). If omitted, all agents the user has permission to use are available. Slugs are the lowercase-hyphenated agent names (e.g. 'alert-management', 'report-management', 'create-widget').
showModelSelectorbooleanfalseShow the LLM model selector in the chat.
hideUploadbooleanfalseHide the file upload button.
hideRefreshbooleanfalseHide the refresh/reset button.
hideSourcesbooleanfalseHide the data sources selector button.
hideSkillsbooleanfalseHide the skills/agents selector button.
hideDisclaimerbooleanfalseHide the AI disclaimer text below the input.
showNewChatButtonbooleantrueShow the "New Chat" button in sidebar and top bar.
showResetChatButtonbooleantrueShow the reset/new chat button at bottom (only visible when sidebar is hidden).
welcomeLogostring (URL)hiddenCustom logo URL for welcome screen center icon. Hidden by default in embed mode; set a URL to show a custom logo.
themeobjectnoneCustomize colors, fonts, and button styles. See Theme Customization below.

Limiting Access to Specific Datasets or Documents

Use the sources parameter to restrict which datasets and documents the AI can access. This is useful for embedded scenarios where you want to limit the scope of data available to specific users or contexts.

Example:

aiConverseOptions: {
  useSources: 'all',
  sources: {
    datasets: ['Sales Data', 'Customer Analytics', 334, 445],
    documents: ['Product Guide', 'FAQ', 'doc-abc123', 'doc-xyz789']
  }
}

Datasets can be specified by name or ID:

  • By name: 'Sales Data', 'Customer Analytics'
  • By ID: 334, 445
  • Both names and IDs can be combined in the same array

Documents can be specified by name or identifier:

  • By name: 'Product Guide', 'FAQ'
  • By identifier: 'doc-abc123', 'doc-xyz789'
    • Document identifiers are unique string values, not numeric IDs
    • You can find the identifier in the document properties or via the Management API

Additional notes: - You can specify only datasets or only documents (both are not required) - If sources is omitted, the AI can access all datasets/documents the user has permission to view - Names and identifiers are matched exactly (case-sensitive)

How It Works:

When sources is provided, AI agents enforce a two-layer security model:

  1. Layer 1: User Permissions - The user must have access to the dataset/document
  2. Layer 2: Sources Filter - The dataset/document must be in the sources whitelist

This ensures users can only interact with the specific data you've explicitly allowed in the embedded context.

Theme Customization

The theme object in aiConverseOptions allows you to customize the look and feel of the embedded chat to match your brand.

All properties are optional - sensible defaults are applied automatically. You can override any specific property while keeping the rest at their default values.

How defaults work: - If you don't specify a theme object, all elements use default styling - primaryColor is used ONLY for user message bubbles (unless overridden by userBubbleColor) - Buttons, inputs, and other UI elements have their own independent defaults - You can customize any specific property while keeping the rest at their defaults

Example - Minimal theme: ```javascript theme: { primaryColor: '#667eea' // Only this one property } // Result: User message bubbles will be blue // All buttons, inputs, and other elements use their default styling (orange/gray) ```

Basic Colors

theme: {
  primaryColor: '#667eea',
  backgroundColor: '#F9FAFB',
  userBubbleColor: '#667eea',
  userBubbleTextColor: '#FFFFFF',
  aiBubbleColor: '#f5f5f5',
  aiBubbleTextColor: '#333333',
  fontFamily: 'Arial, sans-serif'
}
PropertyDefaultDescription
primaryColor#f28c37Primary brand color used for accents and highlights.
backgroundColor#F9FAFBMain background color of the chat interface.
userBubbleColor#667eeaBackground color of user message bubbles.
userBubbleTextColor#FFFFFFText color inside user message bubbles.
aiBubbleColor#f5f5f5Background color of AI message bubbles.
aiBubbleTextColor#333333Text color inside AI message bubbles.
fontFamily'Inter, sans-serif'Font family for the entire chat interface.

Button Styling

theme: {
  buttons: {
    submit: {
      backgroundColor: '#667eea',
      color: '#FFFFFF',
      borderRadius: '8px',
      fontSize: '14px',
      padding: '8px 16px'
    },
    upload: {
      color: '#98A2B3',
      hoverColor: '#475467',
      hoverBackgroundColor: '#F2F4F7'
    },
    reset: {
      color: '#98A2B3',
      hoverColor: '#475467'
    },
    sources: {
      color: '#475467',
      backgroundColor: 'transparent',
      hoverBackgroundColor: '#F2F4F7'
    },
    skills: {
      color: '#475467',
      borderColor: '#E4E7EC'
    },
    newChat: {
      backgroundColor: '#f28c37',
      color: '#FFFFFF'
    },
    sidebarToggle: {
      color: '#475467',
      hoverColor: '#101828'
    }
  }
}
ButtonSupported PropertiesDefaultsDescription
submitbackgroundColor, color, borderRadius, fontSize, paddingOrange (#f28c37), white text, 8px radiusThe send message button (arrow icon).
uploadcolor, hoverColor, hoverBackgroundColorGray (#98A2B3) with darker hoverThe file upload button (plus icon).
resetcolor, hoverColorGray (#98A2B3) with darker hoverThe reset/clear button (refresh icon).
sourcescolor, backgroundColor, hoverBackgroundColorDark gray text, transparent backgroundThe data sources button (shows selected datasets/documents).
skillscolor, borderColorGray text and borderThe skills selector button (AI agent selection).
newChatbackgroundColor, colorOrange (#f28c37), white textThe "New Chat" button (appears in header and sidebar).
sidebarTogglecolor, hoverColorGray with dark hoverThe sidebar expand/collapse button (hamburger icon).

Input Styling

theme: {
  input: {
    backgroundColor: '#FFFFFF',
    borderColor: '#E4E7EC',
    textColor: '#344054',
    placeholderColor: '#98A2B3',
    focusBorderColor: '#f28c37'
  }
}
PropertyDefaultDescription
backgroundColor#FFFFFFBackground color of the input box.
borderColor#E4E7ECBorder color when input is not focused.
textColor#344054Text color inside the input box.
placeholderColor#98A2B3Color of the placeholder text.
focusBorderColor#f28c37 (orange)Border color when input is focused.

Sidebar Styling

theme: {
  sidebar: {
    backgroundColor: '#FFFFFF',
    borderColor: '#E4E7EC',
    sessionHoverColor: '#F2F4F7',
    sessionActiveColor: 'rgba(242, 140, 55, 0.06)'
  }
}
PropertyDefaultDescription
backgroundColor#FFFFFFBackground color of the chat history sidebar.
borderColor#E4E7ECBorder color between sidebar and main chat area.
sessionHoverColor#F2F4F7Background color when hovering over a chat session.
sessionActiveColorrgba(242, 140, 55, 0.06)Background color of the currently active chat session.

Welcome Area Styling

theme: {
  welcome: {
    greetingColor: '#101828',
    subtitleColor: '#475467',
    disclaimerColor: '#667085'
  }
}
PropertyDefaultDescription
greetingColor#101828Text color of the main greeting message.
subtitleColor#475467Text color of the subtitle below the greeting.
disclaimerColor#667085Text color of the disclaimer text.

Suggestion Chips Styling

theme: {
  suggestionChips: {
    backgroundColor: '#F2F4F7',
    color: '#344054',
    hoverBackgroundColor: '#E4E7EC',
    borderColor: '#D0D5DD'
  }
}
PropertyDefaultDescription
backgroundColor#F2F4F7Background color of suggestion chips.
color#344054Text color of suggestion chips.
hoverBackgroundColor#E4E7ECBackground color when hovering over a chip.
borderColor#D0D5DDBorder color of suggestion chips.

Complete Theme Example

Knowi.render('#chat-container', {
  type: 'aiConverse',
  url: 'https://www.knowi.com/',
  token: 'YOUR_SSO_TOKEN',
  view: {
    aiConverseMode: true,
    aiConverseOptions: {
      greeting: 'Welcome to our AI assistant!',
      suggestions: ['Show revenue trends', 'Create a dashboard'],
      theme: {
        // Basic colors
        primaryColor: '#4F46E5',
        backgroundColor: '#FFFFFF',
        userBubbleColor: '#4F46E5',
        userBubbleTextColor: '#FFFFFF',
        aiBubbleColor: '#F3F4F6',
        aiBubbleTextColor: '#1F2937',
        fontFamily: 'Roboto, sans-serif',

        // Buttons
        buttons: {
          submit: {
            backgroundColor: '#4F46E5',
            color: '#FFFFFF',
            borderRadius: '12px'
          },
          newChat: {
            backgroundColor: '#10B981',
            color: '#FFFFFF'
          }
        },

        // Input
        input: {
          borderColor: '#D1D5DB',
          focusBorderColor: '#4F46E5',
          placeholderColor: '#9CA3AF'
        },

        // Suggestion chips
        suggestionChips: {
          backgroundColor: '#EEF2FF',
          color: '#4F46E5',
          hoverBackgroundColor: '#E0E7FF'
        }
      }
    }
  }
});

Headless Chat API

The headless API lets you build your own chat interface. You send questions via REST, and get back structured JSON responses with text, data tables, widget embeds, or clarification prompts.

Authentication

All API requests use the Authorization: Bearer <token> header. Three token types are accepted (the server tries them in order):

  1. SSO Session Token -- from /sso/session/create
  2. Management API Bearer Token -- from Settings > Management API > Bearer Tokens
  3. API Key -- from Settings > Management API > API Keys

Endpoints

EndpointMethodDescription
/api/v1/agent/chatPOSTSynchronous -- returns the full response in one JSON payload.
/api/v1/agent/chat/streamPOSTStreaming -- returns Server-Sent Events with real-time progress updates.

Request Body

POST /api/v1/agent/chat
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "message": "show top 10 customers by revenue",
  "sessionId": "optional-session-id-for-follow-ups",
  "contextType": "global",
  "contextId": "optional-widget-or-dashboard-id",
  "settings": {
    "model": "gpt-4o",
    "targetAgent": "DataAnalyst",
    "selectedDatasets": ["dataset-id-1", "dataset-id-2"],
    "useDatasets": true
  }
}
FieldRequiredDescription
messageYesThe user's question or instruction.
sessionIdNoInclude to continue a conversation. Omit to start a new session.
contextTypeNoScope the AI to a specific context: 'global' (default), 'widget', or 'dashboard'.
contextIdNoThe ID of the widget or dashboard when contextType is not 'global'.
settings.modelNoOverride the default LLM model (e.g., 'gpt-4o', 'claude-3-5-sonnet').
settings.targetAgentNoRoute to a specific agent instead of auto-routing. Pass the enum name (e.g., 'DATA_ANALYST', 'CREATE_DASHBOARD'). See Available Agents section below for the complete list with display names and enum values.
settings.selectedDatasetsNoRestrict the AI to specific dataset IDs.
settings.useDatasetsNoEnable/disable automatic dataset discovery. Default: true.

Response Body

{
  "responseType": "data",
  "text": "Here are the top 10 customers by revenue.",
  "sessionId": "abc123-def456-...",
  "data": {
    "columns": [
      { "name": "Customer", "type": "string" },
      { "name": "Revenue", "type": "number" }
    ],
    "rows": [
      { "Customer": "Acme Corp", "Revenue": 52000 },
      ...
    ]
  }
}
FieldDescription
responseTypeOne of: 'text', 'data', 'widget', 'dashboard', 'clarification'.
textThe AI's response message. Always present.
sessionIdSession ID for follow-up messages. Always present.
dataPresent when responseType is 'data'. Contains columns and rows.
embedPresent when responseType is 'widget' or 'dashboard'. Contains url and html (ready-to-use iframe HTML).
optionsPresent when responseType is 'clarification'. Array of { label, value } objects the user can pick from.

Response Types

text -- A plain text answer from the AI.

data -- Structured query results with columns and rows. Render as a table or pass to a charting library.

widget -- The AI created a widget. The embed field contains a url to the widget and html with a ready-to-use iframe tag.

dashboard -- The AI created a dashboard. Same embed structure as widget.

clarification -- The AI needs more information. The options array contains choices to present to the user. Send the selected value back as the next message.

Streaming (Server-Sent Events)

The streaming endpoint returns real-time progress as the AI works. Events follow the SSE format:

event: progress
data: {"type":"progress","message":"Searching datasets..."}

event: progress
data: {"type":"progress","message":"Running query..."}

event: result
data: {"responseType":"data","text":"Here are the results.","sessionId":"...","data":{...}}
Event TypeDescription
progressIntermediate status update. Show to the user as a loading indicator.
resultFinal response. Same structure as the synchronous response body.
errorAn error occurred. Contains code and message fields.

Error Responses

{
  "error": true,
  "code": "PERMISSION_DENIED",
  "message": "User does not have permission to use AI agents."
}
CodeHTTP StatusDescription
PERMISSION_DENIED403User lacks AI agent permissions.
APPLICATION_ERROR400Invalid request (e.g., empty message, invalid session).
INTERNAL_ERROR500Unexpected server error.

Example: Synchronous Request

const response = await fetch('https://www.knowi.com/api/v1/agent/chat', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_TOKEN'
  },
  body: JSON.stringify({
    message: 'show top 10 customers by revenue'
  })
});

const data = await response.json();
console.log(data.text);
if (data.data) console.table(data.data.rows);
if (data.embed) document.getElementById('container').innerHTML = data.embed.html;

Example: Streaming Request

const response = await fetch('https://www.knowi.com/api/v1/agent/chat/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_TOKEN'
  },
  body: JSON.stringify({
    message: 'show top 10 customers by revenue'
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let eventType = null;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop();
  for (const line of lines) {
    if (line.startsWith('event:'))
      eventType = line.slice(6).trim();
    else if (line.startsWith('data:')) {
      const data = JSON.parse(line.slice(5));
      if (eventType === 'progress') {
        showLoadingMessage(data.message);
      } else if (eventType === 'result') {
        displayResponse(data);
      } else if (eventType === 'error') {
        showError(data.message);
      }
    }
  }
}

Session Management

Sessions maintain conversation context so follow-up questions work. When you send the first message without a sessionId, the API creates a new session and returns the ID in the response. Include that sessionId in subsequent requests to continue the conversation.

// First message -- new session
{ "message": "show revenue by region" }
// Response includes sessionId: "abc123..."

// Follow-up -- same session
{ "message": "now filter that to Q4 only", "sessionId": "abc123..." }

To start a fresh conversation, omit the sessionId.

Available Agents

When using the settings.targetAgent parameter, you can route requests to specific AI agents instead of relying on automatic routing. Pass the enum name (e.g., 'DATA_ANALYST', 'CREATE_DASHBOARD') as the value.

DATA & ANALYTICS

Display NameEnum ValueDescription
Search AssetsSEARCH_ASSETSSearch across all Knowi assets - dashboards, widgets, datasets, reports, and documents
Data AnalystDATA_ANALYSTAnswer questions about data using datasets and documents. Generates charts, text answers, and searches knowledge base.
Get RecommendationsRECOMMENDATIONGenerate AI-powered insights and recommendations for widgets (requires widget context)
Create DatasetCREATE_DATASETCreate datasets from natural language descriptions by searching across datasources
Connect DatasourceCREATE_DATASOURCEGuide users through connecting datasources via conversation
Query Your DataNLP_AGENTConvert natural language to SQL queries for data analysis
Export DataDATA_EXPORTExport widget or dashboard data to CSV or Excel format for download


DASHBOARDS

Display NameEnum ValueDescription
Create DashboardCREATE_DASHBOARDCreate AI-powered dashboards from natural language descriptions
Manage FiltersDASHBOARD_FILTERSet up and configure dashboard filters using natural language (requires dashboard context)
Dashboard SettingsDASHBOARD_SETTINGSConfigure dashboard properties: name, theme, header, footer, description, and dimensions (requires dashboard context)
Dashboard SummaryDASHBOARD_SUMMARYGenerate summaries and narratives that describe the current dashboard state (requires dashboard context)
Share DashboardSHARE_DASHBOARDGenerate shareable URL for dashboard that can be accessed without login (requires dashboard context)
Rearrange LayoutWIDGET_LAYOUTReposition and resize widgets on a dashboard grid (requires dashboard context)
Add Widget to DashboardADD_WIDGET_TO_DASHBOARDAdd an existing widget to a dashboard (requires dashboard context)


WIDGETS

Display NameEnum ValueDescription
Create WidgetCREATE_WIDGETCreate the appropriate widget type with optimal settings based on data and requirements (requires dashboard context)
Customize WidgetUPDATE_WIDGET_SETTINGSUpdate widget visual settings, formatting, and display options without changing the data (requires widget context)


REPORTS & ALERTS

Display NameEnum ValueDescription
Send ReportREPORT_DELIVERYDeliver dashboards, widgets, or datasets via Email, Slack, Teams, or Webhooks
Manage ReportsREPORT_MANAGEMENTCreate, list, edit, pause, unpause, test run, and delete scheduled reports
Manage AlertsALERT_MANAGEMENTCreate, list, edit, pause, unpause, test, and delete data alerts


Example Usage:

{
  "message": "create a sales dashboard",
  "settings": {
    "targetAgent": "CREATE_DASHBOARD"
  }
}

Note: Some agents require specific context via contextType and contextId parameters (e.g., dashboard ID or widget ID).