Dialai can be embedded in your application via a single script tag. This method gives you a floating chat button (bottom-right) that opens the AI agent in a modal when clicked — your visitors talk to the agent without leaving your application.
Prerequisites
Before you begin, you’ll need:
- A Dial AI chat ID (see Creating a Chat ID below)
- The backend URL for your Dial AI instance
- A unique anchor ID for mounting the chat button
Creating a Chat ID
A chat ID is the UUID of a Web Point of Contact. Create one under Agent > Points of Contact > Web — see iframe integration for the step-by-step.
Basic Integration
Add the following to your HTML file, replacing the placeholder values as needed:
- Load the widget script in your
<head> tag:
<script defer type="module" src="https://cdn.dialai.ca/v1/esm/{version}/dial-ai.js"></script>
Replace {version} with a specific release version (e.g. 0.0.1329) from the versions manifest.
- Add the mount point and initialization script:
<!-- Mount point for the chat widget (renders in the bottom right) -->
<span id="your-anchor-id"></span>
<script>
document.addEventListener("DOMContentLoaded", function() {
window.renderModal("your-anchor-id", {
iconUrl: "https://www.yourdomain.com/path/to/icon.svg",
chatId: "YOUR_CHAT_ID",
backendUrl: "https://your-dialai-instance.com"
});
});
</script>
Configuration Options
The renderModal function accepts the following configuration options:
iconUrl (string, required): URL to the icon that will be displayed in the chat button
chatId (string, required): Your unique Dial AI chat identifier
backendUrl (string, required): The base URL of your Dial AI instance
brandVariants (object, optional): Custom color scheme for the chat interface (see Brand Variants below)
Brand Variants
By default, the widget uses the theme configured for the chat link’s tenant. If you need to override this to match your site’s branding, pass a brandVariants object with color values on a scale from 10 (darkest) to 160 (lightest):
brandVariants: {
10: "#001018",
20: "#002030",
30: "#003049",
40: "#004062",
50: "#00507a",
60: "#006093",
70: "#0070ab",
80: "#0080c4",
90: "#0090dc",
100: "#00a1f5",
110: "#10adfe",
120: "#2bb6ff",
130: "#45bfff",
140: "#60c8ff",
150: "#7ad1ff",
160: "#95dafe"
}
Omit brandVariants to use the tenant’s default theme.
CORS Configuration
The widget script is served from our CDN with permissive CORS headers (Access-Control-Allow-Origin: *), so it can be loaded from any domain without additional configuration.
Troubleshooting
- If the chat button doesn’t appear, check your browser’s console for any error messages
- Ensure the anchor element with the specified ID exists in the DOM when the script runs
- Make sure the chat ID and backend URL are correct
Example Implementation
Here’s a complete example of how to integrate the chat button into a simple HTML page:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My App with Dial AI</title>
<script defer type="module" src="https://cdn.dialai.ca/v1/esm/0.0.1329/dial-ai.js"></script>
</head>
<body>
<h1>Welcome to My App</h1>
<p>Click the chat button in the bottom right to get help.</p>
<!-- Mount point for the chat widget -->
<span id="dial-ai-button"></span>
<script>
document.addEventListener("DOMContentLoaded", function() {
window.renderModal("dial-ai-button", {
iconUrl: "https://cdn.dialai.ca/v1/esm/0.0.1329/favicon.ico",
chatId: "00000000-0000-0000-0000-000000000000",
backendUrl: "https://demo.dialai.ca"
});
});
</script>
</body>
</html>
Versions
The widget is hosted on our CDN at https://cdn.dialai.ca/v1/esm/{version}/dial-ai.js. You can find available versions in the versions manifest. Pin to a specific release version to avoid unexpected changes.
Internal-Agent embed: page-aware integrations
In addition to the customer-facing chat (renderModal), the same bundle exposes renderInternalAgentApp — used to embed an internal agent (back-office assistant) into your own internal tooling. This embed exposes two host-page hooks that let the agent become aware of, and act on, the page it’s running inside.
onNavigate — let the agent drive page navigation
When an agent tool result includes the field X-DialAI-Navigation-Path, the widget invokes your onNavigate(path) callback. Use this to wire the agent into your app’s router so the agent can say “I’ve opened the customer record for you” and actually open it.
<div id="agent-app"></div>
<script defer type="module" src="https://cdn.dialai.ca/v1/esm/{version}/dial-ai.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
window.renderInternalAgentApp("agent-app", {
tenantId: "your-tenant",
backendUrl: "https://your-instance.dialai.ca",
onNavigate: (path) => {
// Route using your framework, e.g.:
// window.history.pushState({}, "", path); router.refresh();
window.location.href = path;
}
});
});
</script>
The callback fires exactly once per tool completion that contains a navigation path. The path is a string — the host decides how to interpret it (absolute URL, relative route, anchor). If onNavigate is omitted, navigation results are silently ignored.
onMessageSend — inject page context with every user message
Before each user message is sent to the agent, the widget calls your onMessageSend() callback. Return { contextAdditions: string } and the string is appended to the outgoing user message after a delimiter, so the agent can see what’s currently on the page without the user having to type it.
<div id="agent-app"></div>
<script defer type="module" src="https://cdn.dialai.ca/v1/esm/{version}/dial-ai.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
window.renderInternalAgentApp("agent-app", {
tenantId: "your-tenant",
backendUrl: "https://your-instance.dialai.ca",
onMessageSend: () => ({
contextAdditions: [
`Current page URL: ${window.location.href}`,
`Selected record ID: ${document.querySelector("[data-selected-id]")?.dataset.selectedId ?? "none"}`,
`Filters: ${JSON.stringify(window.__appState?.filters ?? {})}`
].join("\n")
})
});
});
</script>
The widget appends the returned string to the user’s message using a <!-- dialai-context --> marker; the agent sees both the original user input and the appended context.
The callback must be synchronous — return a value immediately, don’t await anything. Use cached/derived values that are already in memory.
Common things to pass via contextAdditions:
- The current route, page title, or page-level entity ID.
- The currently-selected item (row in a table, item in a list).
- Active filters or search terms the user has applied.
- The viewport-visible portion of a long document, if the agent should “see what the user sees”.
When to use this vs the chat-link iframe
| renderInternalAgentApp | Customer chat (renderModal / iframe) |
|---|
| Audience | Your internal staff. | Your end customers. |
| Auth | Operator-authenticated session (the host page is already signed in). | Anonymous; uses a Web POC chat link UUID. |
| Page hooks | onNavigate, onMessageSend. | None — chat is sandboxed in an iframe. |
| Conversation persistence | Backed by the internal-agent SSE stream. | One-shot chat session per visitor. |
Pick renderInternalAgentApp when you’re building an in-house tool where the agent should do things in your app on the user’s behalf. Pick renderModal (or the iframe) when you’re putting a customer-facing AI agent on a public page.
ESM vs UMD
The widget is available in two module formats:
- ESM (recommended) — loaded with
<script type="module">. This is the current format used for all new releases (/v1/esm/{version}/dial-ai.js).
- UMD (legacy) — loaded with a plain
<script> tag. Older releases (pre-0.0.1323) were published in UMD format and remain available at /v1/umd/dial-ai-{version}.umd.js for backward compatibility.
New integrations should use the ESM format. Existing UMD integrations will continue to work but will not receive new releases.