Integration Tutorial
This guide demonstrates how to integrate the RTC Agent Web Component into your web application, covering both quick CDN setup and full NPM integration with SharedWorker configuration.
Integration Methods
Section titled “Integration Methods”| Method | Use Case | Pros | Cons |
|---|---|---|---|
| CDN (quick start) | Documentation sites, demos, prototypes | Zero config, Workers resolve automatically | Depends on external CDN, limited customization |
| NPM + createRtcAgent() (recommended) | Production applications, full control | Type safety, tree-shaking, SharedWorker for multi-tab | Requires SharedWorker setup (one-time) |
Quick Start: CDN Integration
Section titled “Quick Start: CDN Integration”For documentation sites or quick demos, load via CDN and use the createRtcAgent() factory function:
<!-- Import and configure in one step --><script type="module"> import { createRtcAgent } from 'https://cdn.jsdelivr.net/npm/@rtc-agent/component@0.3.0-rc.4/dist/index.js';
const agent = createRtcAgent({ server: { url: 'https://rtc-agent.cherish.chat' }, });
document.body.appendChild(agent);</script>The component automatically connects to the Server on the current page’s domain.
Example: Astro Documentation Site
Section titled “Example: Astro Documentation Site”File: astro.config.mjs
import { defineConfig } from 'astro/config';import starlight from '@astrojs/starlight';
export default defineConfig({ site: 'https://your-site.github.io', base: '/docs', integrations: [ starlight({ title: 'Your Site', head: [ // Load and configure RTC Agent using factory function { tag: 'script', attrs: { type: 'module' }, content: ` import { z, withMeta, createRtcAgent } from 'https://cdn.jsdelivr.net/npm/@rtc-agent/component@0.3.0-rc.4/dist/index.js';
const initRtcAgent = async () => { if (document.querySelector('#rtc-agent-global')) return;
const agent = createRtcAgent({ appLabel: 'RTC Agent Assistant', theme: 'system', server: { url: 'https://rtc-agent.cherish.chat', redirectUri: '/docs/auth/callback.html', }, window: { defaultMode: 'minimized', draggable: true, resizable: true, bubblePosition: { corner: 'bottom-right', offset: { x: -24, y: 24 }, }, }, agentName: 'DocsAssistant', persona: 'You are a helpful documentation assistant.', groups: [{ name: 'docs', description: 'Documentation functions', functions: [ { name: 'searchDocs', description: 'Search documentation by keywords', zodSchema: z.object({ query: withMeta(z.string(), { example: 'RTC Agent setup' }) .describe('Search keywords') }), handler: async ({ query }) => { // Your search implementation return [{ path: '/getting-started/', title: 'Quick Start' }]; }, }, ], }], });
const container = document.createElement('div'); container.id = 'rtc-agent-global'; container.appendChild(agent); document.body.appendChild(container);
// Global styles const style = document.createElement('style'); style.textContent = \` #rtc-agent-global { position: fixed; bottom: 0; right: 0; z-index: 9999; pointer-events: none; } #rtc-agent-global rtc-agent { pointer-events: auto; } \`; document.head.appendChild(style); };
document.addEventListener('DOMContentLoaded', () => initRtcAgent()); `, }, ], }), ],});Key differences from the old pattern:
- ✅ Import
createRtcAgent,z,withMetafrom CDN - ✅ Use factory function instead of manual element creation
- ✅ All configuration in one declarative object
- ✅ No need to wait for
rtc-agent-readyevent - ✅ Function registration uses
zodSchemawithwithMetaexamples
Create the OAuth Callback Page
Section titled “Create the OAuth Callback Page”If you need GitHub login (or other OAuth providers), create a callback page to handle the OAuth redirect.
File: public/auth/callback.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Authorization Complete</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .container { background: white; border-radius: 16px; padding: 48px; text-align: center; max-width: 400px; } .icon { font-size: 48px; margin-bottom: 16px; } </style></head><body> <div class="container"> <div class="icon" id="icon">⏳</div> <h1 id="title">Processing...</h1> <p id="message">Please wait, completing authorization</p> </div>
<script> (function() { var params = new URLSearchParams(window.location.search); var code = params.get('code'); var state = params.get('state'); var error = params.get('error');
var icon = document.getElementById('icon'); var title = document.getElementById('title'); var message = document.getElementById('message');
if (error) { icon.textContent = '✕'; title.textContent = 'Authorization Failed'; message.textContent = error; return; }
if (code && state) { var target = window.opener || window.parent; if (target) { target.postMessage({ type: 'oauth-callback', code: code, state: state, }, window.location.origin); icon.textContent = '✓'; title.textContent = 'Authorization Successful'; message.textContent = 'Returning to app...'; setTimeout(function() { window.close(); }, 2000); } } })(); </script></body></html>Configure the OAuth Callback URL
Section titled “Configure the OAuth Callback URL”In your GitHub OAuth App (or other provider), set the callback URL:
- Development:
http://localhost:4321/docs/auth/callback.html - Production:
https://your-site.github.io/docs/auth/callback.html
Verify the Integration
Section titled “Verify the Integration”Start the development server:
pnpm devVisit http://localhost:4321/docs/ — you should see the RTC Agent floating widget in the bottom-right corner.
Key Points
Section titled “Key Points”1. Use CDN instead of npm install
Section titled “1. Use CDN instead of npm install”CDN loading ensures SharedWorker file paths resolve correctly without additional build tool configuration.
2. Use the createRtcAgent() factory function
Section titled “2. Use the createRtcAgent() factory function”The factory function consolidates all configuration in a single declarative object — no manual element creation or waiting for rtc-agent-ready events:
const agent = createRtcAgent({ appLabel: 'My AI Assistant', server: { url: 'https://rtc-agent.cherish.chat' }, window: { defaultMode: 'minimized', draggable: true },});3. Using client:only in Astro
Section titled “3. Using client:only in Astro”<!-- Skip SSR, render client-side only --><rtc-agent client:only="astro"></rtc-agent>4. Style Isolation
Section titled “4. Style Isolation”The component uses Shadow DOM for style isolation — no conflicts with your Starlight theme.
Complete Example Project
Section titled “Complete Example Project”This project’s docs site has already completed the integration. Refer to these files:
- astro.config.mjs — CDN injection configuration
- public/auth/callback.html — OAuth callback page
Production Integration: NPM + createRtcAgent()
Section titled “Production Integration: NPM + createRtcAgent()”For production applications, use the createRtcAgent() factory function with full type safety and SharedWorker support for multi-tab synchronization.
Step 1: Install the Package
Section titled “Step 1: Install the Package”pnpm add @rtc-agent/component# ornpm install @rtc-agent/component# oryarn add @rtc-agent/componentStep 2: Setup SharedWorker (Required for Multi-Tab)
Section titled “Step 2: Setup SharedWorker (Required for Multi-Tab)”RTC Agent uses a SharedWorker to multiplex WebSocket connections across browser tabs. The worker file must be accessible from the browser’s public directory.
Automatic Setup (Recommended)
Section titled “Automatic Setup (Recommended)”Run the CLI tool to automatically copy SharedWorker files to the correct location:
npx rtc-agent-setupThe tool automatically:
- Detects your project type (Vite, Webpack, SvelteKit, etc.)
- Copies SharedWorker files to the correct directory (
static/rtc-agent/orpublic/rtc-agent/) - Creates a stable filename
shared-worker.jsfor easy reference - Generates
manifest.jsonwith version information - Cleans up old worker files to prevent accumulation
Automatic Setup on Install (Best Practice)
Section titled “Automatic Setup on Install (Best Practice)”Add the setup tool to your postinstall script to run automatically after npm install:
{ "scripts": { "postinstall": "rtc-agent-setup" }}This ensures:
- SharedWorker files are set up automatically for new developers
- Worker files are updated when upgrading
@rtc-agent/component - No manual steps required after dependency changes
💡 If you already have a
postinstallscript, append&& rtc-agent-setupto it:{"scripts": {"postinstall": "your-existing-script && rtc-agent-setup"}}
Manual Setup
Section titled “Manual Setup”If the CLI tool doesn’t work for your setup, manually copy the worker files:
# Create target directorymkdir -p public/rtc-agent
# Copy worker file and rename to stable filenamecp node_modules/@rtc-agent/component/dist/assets/shared-worker-*.js public/rtc-agent/shared-worker.jsStep 3: Configure createRtcAgent()
Section titled “Step 3: Configure createRtcAgent()”Use the factory function to create and configure the component:
import { z, withMeta, createRtcAgent } from '@rtc-agent/component';import type { RtcAgentWithLifecycle } from '@rtc-agent/component';
// Create the agent instanceconst agent: RtcAgentWithLifecycle = createRtcAgent({ // Basic configuration appLabel: 'My AI Assistant', theme: 'system', lang: 'en-US',
// Server configuration server: { url: 'https://rtc-agent.cherish.chat', redirectUri: '/auth/callback.html', },
// SharedWorker URL (required for multi-tab support) workerURL: '/rtc-agent/shared-worker.js',
// Scenario documentation scenariosURL: '/scenarios/',
// Window configuration window: { defaultMode: 'normal', bubblePosition: { corner: 'bottom-right', offset: { x: -24, y: 24 }, }, },
// Function registration (using Zod schema - recommended) agentName: 'MyApp', agentDescription: 'AI assistant for my application', persona: 'You are a helpful assistant...', groups: [ { name: 'editor', description: 'Editor operations', functions: [ { name: 'getCode', description: 'Get the current code', handler: () => window.editorAPI.getCode(), returns: { zodSchema: z.string().describe('Current code in the editor') }, }, { name: 'setCode', description: 'Set the editor code', zodSchema: z.object({ code: withMeta(z.string(), { example: 'console.log("hello")' }).describe('The code to set'), }), handler: (params) => { window.editorAPI.setCode(params.code); return { success: true }; }, }, ], }, ],
// Event handlers on: { ready: () => { console.log('RTC Agent is ready'); }, },});
// Append to DOMdocument.body.appendChild(agent);
// Cleanup when doneagent.destroy();Step 3.1: Authentication Configuration
Section titled “Step 3.1: Authentication Configuration”The auth property in createRtcAgent() controls how the component authenticates with the server. Choose the mode that fits your application:
Mode 1: Static Token (Dev / CI / Testing)
Section titled “Mode 1: Static Token (Dev / CI / Testing)”Pass a fixed access token directly. Simple but not suitable for production — the token expires and cannot be refreshed.
const agent = createRtcAgent({ server: { url: 'https://rtc-agent.example.com' }, workerURL: '/rtc-agent/shared-worker.js', auth: { accessToken: 'your-jwt-token', userId: 'user-123', },});Mode 2: Dynamic Token (Recommended for Production)
Section titled “Mode 2: Dynamic Token (Recommended for Production)”Provide a getToken callback (required) and an optional refreshToken callback so the component can fetch and renew tokens on demand. This is the recommended approach for most production applications.
const agent = createRtcAgent({ server: { url: 'https://rtc-agent.example.com' }, workerURL: '/rtc-agent/shared-worker.js', auth: { userId: 'user-123', getToken: async () => { const res = await fetch('/api/auth/token'); const data = await res.json(); return data.accessToken; }, refreshToken: async () => { const res = await fetch('/api/auth/refresh', { method: 'POST' }); return res.json(); }, },});Mode 3: Auth Provider (Advanced / Multi-Tenant)
Section titled “Mode 3: Auth Provider (Advanced / Multi-Tenant)”Implement a full auth interface with isLoggedIn and logout hooks. Use this when you have an existing authentication system or need multi-tenant support.
const agent = createRtcAgent({ server: { url: 'https://rtc-agent.example.com' }, workerURL: '/rtc-agent/shared-worker.js', auth: { getToken: async () => myAuthProvider.getToken(), refreshToken: async () => myAuthProvider.refresh(), isLoggedIn: () => myAuthProvider.isLoggedIn(), logout: async () => myAuthProvider.logout(), getUserId: () => myAuthProvider.getUserId(), // returns the current user's unique ID (strongly recommended) },});See Authentication & Authorization for full details on the login flow, token lifecycle, and security best practices.
Step 4: Framework Integration
Section titled “Step 4: Framework Integration”SvelteKit Example
Section titled “SvelteKit Example”<script lang="ts"> import { onMount, onDestroy } from 'svelte'; import { base } from '$app/paths'; import { createRtcAgent } from '@rtc-agent/component'; import type { RtcAgentWithLifecycle } from '@rtc-agent/component';
let rtcAgent: RtcAgentWithLifecycle | null = null;
onMount(() => { rtcAgent = createRtcAgent({ appLabel: 'My App', theme: 'system', server: { url: 'https://rtc-agent.cherish.chat', redirectUri: `${base}/auth/callback.html`, }, workerURL: `${base}/rtc-agent/shared-worker.js`, scenariosURL: `${base}/scenarios/`, // ... other configuration });
document.body.appendChild(rtcAgent); });
onDestroy(() => { if (rtcAgent) { rtcAgent.destroy(); rtcAgent = null; } });</script>React Example
Section titled “React Example”import { useEffect, useRef } from 'react';import { createRtcAgent } from '@rtc-agent/component';import type { RtcAgentWithLifecycle } from '@rtc-agent/component';
function RtcAgentWrapper() { const agentRef = useRef<RtcAgentWithLifecycle | null>(null);
useEffect(() => { agentRef.current = createRtcAgent({ appLabel: 'My App', theme: 'system', server: { url: 'https://rtc-agent.cherish.chat', redirectUri: '/auth/callback.html', }, workerURL: '/rtc-agent/shared-worker.js', // ... other configuration });
document.body.appendChild(agentRef.current);
return () => { if (agentRef.current) { agentRef.current.destroy(); agentRef.current = null; } }; }, []);
return null;}Vue Example
Section titled “Vue Example”<script setup lang="ts">import { onMounted, onUnmounted, ref } from 'vue';import { createRtcAgent } from '@rtc-agent/component';import type { RtcAgentWithLifecycle } from '@rtc-agent/component';
const agentRef = ref<RtcAgentWithLifecycle | null>(null);
onMounted(() => { agentRef.value = createRtcAgent({ appLabel: 'My App', theme: 'system', server: { url: 'https://rtc-agent.cherish.chat', redirectUri: '/auth/callback.html', }, workerURL: '/rtc-agent/shared-worker.js', // ... other configuration });
document.body.appendChild(agentRef.value);});
onUnmounted(() => { if (agentRef.value) { agentRef.value.destroy(); agentRef.value = null; }});</script>createRtcAgent() Configuration Reference
Section titled “createRtcAgent() Configuration Reference”Basic Configuration
Section titled “Basic Configuration”| Property | Type | Default | Description |
|---|---|---|---|
appLabel | string | "RTC Agent" | Title bar text and tooltip |
theme | "light" | "dark" | "system" | "system" | Theme mode |
lang | "zh-CN" | "en-US" | "zh-CN" | UI language |
databaseName | string | "rtc-agent" | IndexedDB name prefix |
Server Configuration
Section titled “Server Configuration”| Property | Type | Default | Description |
|---|---|---|---|
server.url | string | "" | Server address (falls back to current domain) |
server.redirectUri | string | "/auth/callback.html" | OAuth callback URL |
SharedWorker Configuration
Section titled “SharedWorker Configuration”| Property | Type | Default | Description |
|---|---|---|---|
workerURL | string | undefined | URL to the SharedWorker file (required for multi-tab support) |
Authentication Configuration
Section titled “Authentication Configuration”| Property | Type | Default | Description |
|---|---|---|---|
auth.accessToken | string | — | Static JWT token (Mode 1) |
auth.userId | string | — | User identifier |
auth.getToken | () => Promise<string> | — | Async callback to obtain an access token (Mode 2/3) |
auth.refreshToken | () => Promise<object> | — | Async callback to refresh the token (optional in Mode 2, required in Mode 3) |
auth.isLoggedIn | () => boolean | — | Check whether the user is authenticated (Mode 3) |
auth.logout | () => Promise<void> | — | Log the user out (Mode 3) |
auth.getUserId | () => string | — | Return the current user’s unique identifier (Mode 3, strongly recommended for per-user IndexedDB isolation) |
Window Configuration
Section titled “Window Configuration”| Property | Type | Default | Description |
|---|---|---|---|
window.defaultMode | "normal" | "maximized" | "minimized" | "normal" | Initial window mode |
window.embedded | boolean | false | Embedded mode (no drag/resize/buttons) |
window.draggable | boolean | true | Whether window can be dragged |
window.resizable | boolean | true | Whether window can be resized |
window.bubblePosition.corner | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "bottom-right" | Bubble position corner |
window.bubblePosition.offset.x | number | -20 | Horizontal offset |
window.bubblePosition.offset.y | number | 20 | Vertical offset |
Function Registration
Section titled “Function Registration”| Property | Type | Default | Description |
|---|---|---|---|
agentName | string | — | Application name |
agentDescription | string | — | Application description |
persona | string | — | AI persona/instructions |
groups | FunctionGroup[] | [] | Function groups for tool registration |
Event Handlers
Section titled “Event Handlers”| Property | Type | Description |
|---|---|---|
on.ready | () => void | Called when component is ready |
on.beforeDestroy | () => void | Called when the component is about to be destroyed (during disconnectedCallback, before cleanup) |
Upgrading SharedWorker
Section titled “Upgrading SharedWorker”When you upgrade @rtc-agent/component, re-run the setup tool to update the SharedWorker files:
npx rtc-agent-setupThe tool will:
- Copy the new worker files
- Update
manifest.jsonwith the new version - Overwrite the old
shared-worker.js
Cache Management
Section titled “Cache Management”For production deployments, use version-based cache busting:
// Read manifest.jsonconst manifest = await fetch('/rtc-agent/manifest.json').then(r => r.json());const workerURL = `/rtc-agent/shared-worker.js?v=${manifest.version}`;
// Use in createRtcAgent()const agent = createRtcAgent({ workerURL, // ...});Or configure your web server to disable caching for the worker file:
location /rtc-agent/shared-worker.js { add_header Cache-Control "no-cache, must-revalidate";}Troubleshooting
Section titled “Troubleshooting”SharedWorker 404 Error
Section titled “SharedWorker 404 Error”Symptom: Console shows 404 error for SharedWorker file
Solution:
- Verify worker files exist:
ls public/rtc-agent/orls static/rtc-agent/ - Check
workerURLpath matches the actual file location - Restart the dev server
- Re-run
npx rtc-agent-setup
Multi-Tab Not Syncing
Section titled “Multi-Tab Not Syncing”Symptom: Changes in one tab don’t appear in other tabs
Solution:
- Ensure
workerURLis configured increateRtcAgent() - Check browser console for SharedWorker errors
- Verify all tabs are on the same origin (protocol + domain + port)
- Check that SharedWorker is not blocked by browser extensions
Import Resolution Error
Section titled “Import Resolution Error”Symptom: Cannot find module '@rtc-agent/component'
Solution:
- Verify package is installed:
pnpm list @rtc-agent/component - Check
node_modules/@rtc-agent/componentexists - Reinstall:
pnpm install
Next Steps
Section titled “Next Steps”- Web Component API — Full API reference for
<rtc-agent> - Function Registration Guide — Register custom functions via
agentConfig - Scenario Authoring Guide — Write scenario documents to guide AI behavior
- Authentication & Authorization — Learn about the login flow and token mechanism