How configuration works
The widget reads its settings from two places, checked in order:
data-*attributes on the<script>tagwindow.VOICE_*globals set before the script loads
data-* attributes take precedence. Use window globals when a tag manager or bundler makes data-* attributes awkward.
Attributes reference
| Attribute | Window global | Type | Default | Description |
|---|---|---|---|---|
data-agent | VOICE_AGENT_SLUG | string | — | Required. The character slug to load (e.g. support-bot). data-agent-id is accepted as an alias. |
data-api-url | VOICE_API_URL | string | https://api.oshara.ai | Base URL for the Oshara backend. Override for self-hosted installs. |
data-appearance-url | VOICE_APPEARANCE_URL | string | auto-derived | Override the URL from which appearance JSON is fetched. Defaults to {apiUrl}/api/agents/{slug}/appearance/. |
data-open-chat | VOICE_OPEN_CHAT | boolean | false | Auto-expand the voice panel on page load. |
data-inline | VOICE_INLINE | boolean | false | Mount the widget inside the script tag’s parent element instead of floating on <body>. Hides the bubble and implies data-open-chat. See Embedding & Placement. |
data-close-button-hide | VOICE_CLOSE_BUTTON_HIDE | boolean | false | Hide the panel’s close button. |
data-context | VOICE_CONTEXT | string | JSON | "" | Free-text context the agent speaks from. A JSON object is flattened into key: value lines. See Context & Metadata. |
data-greeting | VOICE_GREETING | string | "" | The agent’s opening line for this page, instead of the character’s stored greeting. Plain text, one sentence, capped at 400 characters. See Context & Metadata. |
data-metadata | VOICE_METADATA | JSON object | {} | Facts about the visitor (user_id, plan, …). Reaches the agent’s prompt and the session record. |
data-mcp-headers | VOICE_MCP_HEADERS | JSON object | {} | Headers merged into every MCP/HTTP tool call. Nest under a server name to scope them to one server. |
data-mcp-forward-metadata | VOICE_MCP_FORWARD_METADATA | boolean | false | Also send each metadata entry as an X-Oshara-Meta-<key> header on MCP calls. |
data-deepfilter-cdn | VOICE_DEEPFILTER_CDN_URL | string | "" | Base CDN for DeepFilterNet3 model files. Empty uses the package default (cdn.mezon.ai). |
data-deepfilter-wasm-url | VOICE_DEEPFILTER_WASM_URL | string | https://d8t72b7sfcrqv.cloudfront.net/df_bg.wasm | Direct URL to the DeepFilterNet3 WASM binary. Overrides CDN derivation. |
data-deepfilter-onnx-url | VOICE_DEEPFILTER_ONNX_URL | string | https://d8t72b7sfcrqv.cloudfront.net/DeepFilterNet3_onnx.tar.gz | Direct URL to the ONNX model archive. |
data-deepfilter-module-url | VOICE_DEEPFILTER_MODULE_URL | string | https://esm.sh/deepfilternet3-noise-filter@1.2.1 | ESM module URL for the DeepFilterNet3 JS wrapper. |
Minimal example
<script
src="https://api.oshara.ai/widget.js"
data-agent="support-bot">
</script>Self-hosting DeepFilterNet3 models
If you want noise-cancellation models to load from your own CDN (e.g. for CSP compliance), override the three model URLs:
<script
src="https://api.oshara.ai/widget.js"
data-agent="support-bot"
data-deepfilter-wasm-url="https://cdn.yoursite.com/df_bg.wasm"
data-deepfilter-onnx-url="https://cdn.yoursite.com/DeepFilterNet3_onnx.tar.gz"
data-deepfilter-module-url="https://cdn.yoursite.com/deepfilternet3.esm.js">
</script>Download the files from cdn.mezon.ai and host them yourself.
Using window globals
<script>
window.VOICE_AGENT_SLUG = "support-bot";
window.VOICE_API_URL = "https://api.oshara.ai";
window.VOICE_OPEN_CHAT = true;
</script>
<script src="https://api.oshara.ai/widget.js" async></script>Set all globals before the widget script executes. With async, that means setting them synchronously before the <script async> tag.
The runtime handle
window.__OsharaVoiceWidget is installed as soon as widget.js is parsed, before the widget finishes booting:
// Tear down the current instance (removes DOM, disconnects audio)
window.__OsharaVoiceWidget?.destroy();
// Update config
window.VOICE_AGENT_SLUG = "new-bot";
// Re-load the script — or call the init function if you imported it as a moduleIt also carries the context setters — setContext, setGreeting, setMetadata,
setMcpHeaders, setForwardMetadataToMcp — which keep working after destroy(),
so you can hand over a visitor’s details and then re-inject the widget. See
Context & Metadata.
Notes
- The
data-agentslug is the only required attribute. All others have sensible defaults. data-open-chatanddata-inlineare true only for the literal values"true"or"1".data-close-button-hidealso accepts the bare attribute with no value.data-contextaccepts plain text or JSON;data-metadataanddata-mcp-headersmust be valid JSON objects. Malformed JSON is ignored rather than throwing, so a bad attribute costs you the context, not the widget.data-greetingis always plain text — it is spoken verbatim, so it is never parsed as JSON. Newlines collapse to spaces; an empty value falls back to the character’s stored greeting.- Appearance (branding, colors, position, panel size, forms) is controlled server-side via the character’s appearance config, not via
data-*attributes. See Appearance and Embedding & Placement.