@wallavi/widget
Chat copilot for Wallavi agents. Install it with a component or a script; your app passes only the session and what the user is viewing.
pnpm add @wallavi/widget
"use client";
import { WallaviCopilot } from "@wallavi/widget";
import "@wallavi/widget/styles.css";
<WallaviCopilot
agentId="your-agent-id"
session={{
userId: currentUser.id,
userName: currentUser.name,
userEmail: currentUser.email,
headers: async () => ({ Authorization: `Bearer ${await getToken()}` }),
identityToken: currentUser.identityToken,
}}
viewing="Purchase order PO-2026-0142"
/>;
Without React, paste this before </body>:
<script>
window.wallavi =
window.wallavi ||
function () {
(window.wallavi.q = window.wallavi.q || []).push(arguments);
};
wallavi("identify", {
userId: currentUser.id,
userName: currentUser.name,
userEmail: currentUser.email,
identityToken: currentUser.identityToken,
});
wallavi("viewing", "Purchase order PO-2026-0142");
</script>
<script
src="https://app.wallavi.com/embed.min.js"
data-agent-id="your-agent-id"
async
></script>
Presentation (layout, colors, texts, shortcut) is changed in the Wallavi panel; you don't need to redeploy your app.
Migrating to 2.0.0
Private mode no longer reads window.Clerk. Before 2.0.0, a widget with
workspaceId looked up a Clerk session on the page and sent its token. The
widget now knows no auth provider: it sends only the headers the host returns
from userContext.headers.
If you use private mode, pass your token yourself. A function is called before every message, so short-lived tokens are never sent stale:
<WallaviWidget
agentId="..."
workspaceId="..."
userContext={{
headers: async () => {
const token = await getToken(); // your auth provider
return token ? { Authorization: `Bearer ${token}` } : {};
},
}}
/>
Without headers, private requests go out with no Authorization header.