@osirus/agent
v1.8.0
Published
Embeddable multi-mode AI agent widget for web apps (chat, code, search, image, video, speech).
Maintainers
Readme
Osirus Agent is a web widget you can embed in any site or app. It supports multiple interaction modes: chat, code, search, image, video, and speech.
Quickstart (60 Seconds)
Fastest (NPM)
npm i @osirus/agentimport OsirusAgent from '@osirus/agent'
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'search', // chat | code | search | image | video | speech
})Fastest (CDN)
<script src="https://agent.osirus.ai/lib/umd/osirusai.min.js" type="text/javascript"></script>
<script type="text/javascript">
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'chat'
})
</script>Installation
You install one package/script for all widget types, then choose the widget behavior with mode.
Local Test Harness (Before Push)
Run the local dev harness page:
npm run devThen open:
http://localhost:4000
Optional URL presets:
http://localhost:4000/?agentId=YOUR_AGENT_ID&mode=chathttp://localhost:4000/?agentId=YOUR_AGENT_ID&mode=search&searchPlaceholder=Search%20docshttp://localhost:4000/?agentId=YOUR_AGENT_ID&mode=speechhttp://localhost:4000/?agentId=YOUR_AGENT_ID&baseApiUrl=https://osirus.ai/api
The page includes controls to:
- Switch
mode(chat,code,search,image,video,speech) - Override
agentId - Override
baseApiUrl - Set
searchPlaceholder - Apply/reload or unmount/mount the widget
NPM
npm i @osirus/agentimport OsirusAgent from '@osirus/agent'
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
})CDN
<script src="https://agent.osirus.ai/lib/umd/osirusai.min.js" type="text/javascript"></script>
<script type="text/javascript">
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID'
})
</script>Multi-Agent Init (One Call)
You can mount many agents at once by passing an array to init.
import OsirusAgent from '@osirus/agent'
OsirusAgent.init([
{ agentId: 'AGENT_CHAT_ID', mode: 'chat' },
{ agentId: 'AGENT_CODE_ID', mode: 'code' },
{ agentId: 'AGENT_IMAGE_ID', mode: 'image' },
])instanceId is optional in array mode. If omitted, it is auto-generated from agentId/name.
Mount Into Tab/Div Containers
Use mountTo to render inside a specific host element (for CMS tab systems, side panels, modals, etc.).
<div id="tab-code"></div>
<div id="tab-media"></div>OsirusAgent.init([
{
agentId: 'AGENT_CODE_ID',
mode: 'code',
mountTo: '#tab-code',
placement: { position: 'absolute', top: '0', right: '0', left: '0', bottom: '0' },
},
{
agentId: 'AGENT_IMAGE_ID',
mode: 'image',
mountTo: '#tab-media',
placement: { position: 'absolute', top: '0', right: '0', left: '0', bottom: '0' },
},
])mountTo accepts either a CSS selector string or an HTMLElement.
Host Callbacks (onOutput, onClose)
Use callbacks to receive generated output in the host app and react when users close the widget.
import type { AgentOutputEvent, AgentCloseEvent } from '@osirus/agent'
OsirusAgent.init({
agentId: 'AGENT_IMAGE_ID',
mode: 'image',
mountTo: '#tab-media',
onOutput: (event: AgentOutputEvent) => {
// event.type: 'code' | 'image' | 'video' | ...
// event.output contains payload from the mode panel
// Example image payload: { urls, primaryUrl, generationId, prompt, source }
console.log('output', event)
},
onClose: (event: AgentCloseEvent) => {
// Example: hide active tab or persist draft state
console.log('closed', event.reason, event.instanceId)
},
})agentId is always included in onOutput/onClose payloads for app-backed widgets and should be used as the host-side auth token when handling callback actions.
Current mode outputs:
code: emits updated HTML after apply.image: emits generated media URLs when create/status returns outputs.video: emits generated media URLs when create/status returns outputs.
React Host Tab Example
import { useEffect } from 'react'
import OsirusAgent from '@osirus/agent'
export function CmsAiTabs() {
useEffect(() => {
OsirusAgent.init([
{
agentId: 'AGENT_CODE_ID',
mode: 'code',
mountTo: '#tab-code',
onOutput: (event) => console.log('code output', event.output),
},
{
agentId: 'AGENT_IMAGE_ID',
mode: 'image',
mountTo: '#tab-media-generate',
onOutput: (event) => console.log('media output', event.output),
},
])
return () => {
OsirusAgent.destroy()
}
}, [])
return (
<>
<div id="tab-code" />
<div id="tab-media-generate" />
</>
)
}Lifecycle Methods
Use these methods when your host controls tab lifecycle explicitly.
// Update an existing mounted widget instance
OsirusAgent.update({
instanceId: 'AGENT_CODE_ID',
searchPlaceholder: 'Search CMS docs...',
})
// Destroy one instance
OsirusAgent.destroy('AGENT_CODE_ID')
// Destroy all instances
OsirusAgent.destroy()Install Each Widget Type
Use mode in your init config to force widget behavior per embed.
If your agent already has a type configured in the app, you can omit mode.
If both are present, mode in OsirusAgent.init(...) overrides the agent default.
Supported values:
chatcodesearchimagevideospeech
Legacy alias:
voiceis normalized tospeech
1. Chat Widget
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'chat',
})2. Code Widget
code mode provides an HTML/code editor panel with prompt + attachment apply flow.
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'code',
})3. Search Widget
search mode replaces the floating chat icon with a floating search bar launcher.
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'search',
searchPlaceholder: 'Search docs, API, pricing...',
})4. Image Widget
image mode includes a Generate tab with a canvas preview and prompt input.
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'image',
})5. Video Widget
video mode includes a Generate tab with video-focused prompting and preview.
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'video',
})6. Speech Widget
speech runs inside chat and supports a fullscreen speech view.
OsirusAgent.init({
agentId: 'YOUR_AGENT_ID',
mode: 'speech',
})Local Configuration Example
Use local configuration when you are not loading agent settings by agentId.
OsirusAgent.init({
name: 'OsirusAgent',
mode: 'chat',
searchPlaceholder: 'Search...',
companyName: 'Osirus',
companyIconUrl: 'https://agent.osirus.ai/images/Osirus-Icon.svg',
customColor: '#006FE5',
description: 'Embedded support and AI agent widget.',
phoneNumber: '123-456-7890',
email: '[email protected]',
docUrl: 'https://osirus.ai/docs',
apiDocUrl: 'https://osirus.ai/docs/api',
support: {
type: 'page',
value: 'https://osirus.ai/support',
},
schedule: 'M - F, 8:30AM - 5:30PM EDT',
address: {
streetAddress: '123 Orange Ave',
city: 'Orlando',
state: 'FL',
postalCode: '38235',
country: 'USA',
},
showMap: true,
googleMapApiKey: 'AIzaS...x2E_k',
greeting: 'Hi, how can I help you today?',
customOptions: [
{
icon: 'people',
label: 'Careers',
link: 'https://www.solodev.com/careers',
openNewTab: true,
},
],
})React Export (@osirus/agent/react)
For React apps, you can import reusable UI components directly (in addition to OsirusAgentProvider).
import {
CodeHtmlEditor,
FieldAssistantBar,
HTMLEditor,
MediaGeneratePanel,
} from '@osirus/agent/react'
import { useRef, useState } from 'react'
export function Example() {
const inputRef = useRef<HTMLInputElement | null>(null)
const [visible, setVisible] = useState(true)
return (
<>
<CodeHtmlEditor
value="<p>Hello</p>"
onApply={async ({ prompt, html }) => {
// Call your API here and return updated HTML.
return html
}}
/>
<HTMLEditor
name="content"
value="<p>Hello world</p>"
onChange={(nextHtml) => console.log(nextHtml)}
onApplyPrompt={async ({ prompt, html, files }) => {
// Call your API and return updated html.
return { html }
}}
/>
<div style={{ position: 'relative', marginTop: 24 }}>
<input
ref={inputRef}
onFocus={() => setVisible(true)}
placeholder="Edit this text with AI"
/>
<FieldAssistantBar
targetRef={inputRef}
visible={visible}
onAssist={async ({ mode, text, prompt }) => {
// Call your API here and return updated text.
return { text: mode === 'prompt' ? `${text} ${prompt || ''}` : text }
}}
/>
</div>
<MediaGeneratePanel
agentId="YOUR_IMAGE_AGENT_ID"
prompt="cinematic sunset mountain"
onPromptChange={(value) => console.log(value)}
onGenerate={({ prompt, aspectRatio, agentId }) => {
console.log('generate', prompt, aspectRatio, agentId)
}}
onAddToLibrary={({ url, agentId }) => {
console.log('add-to-library', url, agentId)
}}
generatedUrls={['https://example.com/generated.png']}
/>
</>
)
}MediaGeneratePanel callback payloads always include agentId so host systems can enforce agent-scoped authorization.
For HTMLEditor and FieldAssistantBar, pass aiContext/context.agentId so callback requests include the same token.
Configuration Reference
App-Backed Config (agentId)
| Property | Type | Required | Description | Example |
|---|---|---|---|---|
| agentId | string | Yes | Agent ID created in the Osirus app. | "abc123" |
| baseApiUrl | string | No | API base URL override. | "https://osirus.ai/api" |
| mode | 'chat' \| 'code' \| 'search' \| 'image' \| 'video' \| 'speech' | No | Overrides widget mode for this embed. | "search" |
| searchPlaceholder | string | No | Search input placeholder for search mode. | "Search docs..." |
| instanceId | string | No | Unique widget instance key used by update/destroy. | "cms-code-tab" |
| mountTo | string \| HTMLElement | No | Mount target selector or element instead of default floating root. | "#tab-code" |
| placement | object | No | Inline placement style for widget overlay. | { position: 'absolute', top: '0', left: '0' } |
| onOutput | (event) => void | No | Receives generated outputs (code, image, video, etc.). | (e) => console.log(e.output) |
| onClose | (event) => void | No | Called when widget closes. | (e) => console.log(e.reason) |
Local Config
| Property | Type | Required | Description | Example |
|---|---|---|---|---|
| name | string | Yes | Agent display name. | "OsirusAgent" |
| mode | 'chat' \| 'code' \| 'search' \| 'image' \| 'video' \| 'speech' | No | Widget mode. | "speech" |
| searchPlaceholder | string | No | Search input placeholder for search mode. | "Search..." |
| instanceId | string | No | Unique widget instance key used by update/destroy. | "cms-local-widget" |
| mountTo | string \| HTMLElement | No | Mount target selector or element instead of default floating root. | "#assistant-tab" |
| placement | object | No | Inline placement style for widget overlay. | { position: 'absolute', top: '0', left: '0' } |
| onOutput | (event) => void | No | Receives generated outputs (code, image, video, etc.). | (e) => console.log(e.output) |
| onClose | (event) => void | No | Called when widget closes. | (e) => console.log(e.reason) |
| companyName | string | No | Replaces agent name in UI. | "Osirus" |
| companyIconUrl | string | No | Company logo URL shown in widget header. | "https://agent.osirus.ai/images/Osirus-Icon.svg" |
| customColor | string | No | Hex color for widget actions. | "#006FE5" |
| description | string | No | Company/agent description text. | "Embedded support and AI agent widget." |
| phoneNumber | string | No | Enables call button. | "123-456-7890" |
| email | string | No | Support email. | "[email protected]" |
| docUrl | string | No | Enables docs panel button. | "https://osirus.ai/docs" |
| apiDocUrl | string | No | Enables API docs panel button. | "https://osirus.ai/docs/api" |
| support | { type: 'page' \| 'email', value: string } | No | Support button behavior and target. | { type: 'page', value: 'https://osirus.ai/support' } |
| schedule | string | No | Operating hours. | "M - F, 8:30AM - 5:30PM EDT" |
| address | object | No | Business address object. | { streetAddress, city, state, postalCode, country } |
| showMap | boolean | No | Shows map preview (requires googleMapApiKey). | true |
| googleMapApiKey | string | No | Google Maps API key for map rendering. | "AIzaS...x2E_k" |
| greeting | string | No | Initial greeting and popup message text. | "Hi, how can I help you today?" |
| customOptions | Array<{ icon, label, link, openNewTab }> | No | Custom action buttons. | [{ icon: 'telephone-plus', label: 'Sales', link: 'https://example.com', openNewTab: true }] |
Callback Event Shapes
onOutput(event):
event.type:'chat' | 'code' | 'image' | 'video' | 'speech' | 'search'event.output: mode-specific payload (for examplehtmlfor code,urlsfor image/video)event.agentId,event.instanceId,event.mode,event.timestamp
onClose(event):
event.reason: close reason string (for example'widget-close')event.agentId,event.instanceId,event.mode,event.timestamp
Icon Notes
customOptions[].icon uses Bootstrap Icons names (without the bi- prefix).
Example: "telephone-plus" renders bi bi-telephone-plus.
