Usher for web

Beta
Last updated  Sep 23, 2026

Usher is an assistant that lives inside your signed-in React web app. Your users talk to it or type to it, and on every turn it decides whether to answer, offer a page, take them there, or ask a clarifying question. It moves them through your own router and only ever to pages you’ve listed.

What Usher does

  • A floating orb (bottom-right) starts a voice conversation. Its Aa button opens a chat panel. Voice and chat are one conversation with one context.
  • It knows your app through a destination map: an id, a route pattern, a title, a description, and the phrases people use for each page. The model picks an id from that list. It never produces a URL.
  • It can answer from a small knowledge base you pass in, and link an answer to the page it’s about.
  • It respects roles. A destination with roleScopes is hidden from users outside those roles. The model is never told it exists.
DecisionExampleWhen
Navigate“Take me to billing”Imperative phrasing, one confident destination, and you aren't already on it.
Offer“How do I book a consult?”Answers, then offers to take you there. You confirm before anything moves.
Answer“What's your refund policy?”Nothing to navigate to, or you're already on the page. Replies in a sentence or two.
Clarify“Open settings”Two destinations are about equally likely. Asks one short question.
RefuseA page this user can't reachThe page doesn't exist or is out of role (the user isn't told which), or the target is unresolved, unsafe, or rejected by your router. It says so plainly. Nothing moves.

How a turn works

Your router adapter supplies the route tree. Your manifest adds titles, descriptions, aliases, and roles. buildDestinationMap merges the two into the destinations you pass to <Usher>. On each turn the model chooses a tool (navigate, offer_navigation or clarify) or simply replies. Before anything moves, a deterministic validation chain checks the choice: the id must be listed, the role must allow it, every dynamic param must come from a safe source, and the final path must be relative. Only then does Usher call your router, so your route guards still run.

The model is never trusted with ids. For a route like /cases/:caseId, the caseId comes from the selected entity in context, the current URL, or your own resolveEntity function. A value the model invents is ignored. See Dynamic params.

Packages

Install the React bindings, the core, and the one adapter that matches your router.

PackageInstallWhat it gives you
@voqal/usher-reactRequiredThe <Usher> component: the orb, the chat panel, voice audio, and the imperative handle.
@voqal/usher-coreRequiredTypes, buildDestinationMap, the validation chain, the policy, and the session runtime. Framework-agnostic.
@voqal/usher-react-routerOne adapterreactRouterAdapter(router) for React Router 6.4+ and 7 data routers. Discovers routes and navigates through router.navigate().
@voqal/usher-nextOne adapternextAdapter(router, options) for Next.js. Navigates with router.push(); you pass the route list.

Requirements

  • React 18 or newer (react and react-dom are peer dependencies).
  • A client-side router: React Router 6.4+ or 7 with a data router (createBrowserRouter), Next.js 13+, or your own adapter.
  • A publishable key from Voqal, registered for every origin you serve the app from.
  • ES modules. The packages ship ESM with type definitions and no CommonJS build.
  • For voice: a secure context (HTTPS or localhost), microphone permission, and AudioWorklet support in a current browser.

What the beta covers

  • Included: navigate, offer, answer (including from your knowledge base), clarify, and refuse. Voice with hands-free or push-to-talk, and the chat panel, on one session hosted by Voqal with your publishable key. Themes. Role scoping. Safe dynamic params. The React Router and Next.js adapters.
  • Not included: actions beyond navigation (Usher doesn’t fill forms, click buttons, or change data), tabs and modals that have no URL, and a dashboard for editing your map. The map and knowledge base live in your code.
  • The packages are at 0.1.0-beta.0 on the beta npm tag. The API can change between beta releases, so pin an exact version and read the release notes before you upgrade.

Next steps

© 2026 VoqalVoqal SDK & engine documentation