Call configure once, wherever your app boots. Verb reads the adapter at the moment a tool is called rather than at start-up, so running late is harmless. Running EARLY is not: the script tag is defer, so code below it in the document still runs before it, and window.Verb is undefined at that point. Wait for it.
"Wherever your app boots" means the same file that already carries the Verb script tag, the one every route in your app renders through, right after that tag. Concretely, by stack:
- Next.js App Router:
app/layout.tsx - Next.js Pages Router:
pages/_document.tsx - Vite or Create React App:
index.html - Vue or Nuxt: your root component, or
nuxt.config.ts'sapp.head.script - Anything else: the shared template or layout every route already goes through
wherever your app boots, once
function setUpVerb() {
window.Verb.configure({
execute: async (tool, args) => {
switch (tool) {
case "cancel_order":
return await supabase.rpc("cancel_order", { p_order_id: args.order_id });
// one case per adapter tool, from the code block already in verb.md
default:
throw new Error(`Unknown tool: ${tool}`);
}
},
});
}
// Both: the event covers a cold load, the check covers a warm cache where
// the script was already there before this ran.
if (window.Verb) setUpVerb();
else window.addEventListener("verb:ready", setUpVerb);Pass execute and getSessionToken in the same call if you have both, or in two calls: configure merges what you give it, so a later call adding identity will not discard the adapter you set here.
One case per adapter tool, matching the tool names in your verb.md. The code block in each tool's section is what belongs in its case.
Keep it a literal switch even when it gets long, and expect it to get long: thirty tools is a function of a couple of hundred lines. That will trip a maximum function length rule in a strict lint config. Suppress the rule for this function rather than splitting it up or replacing it with a lookup. The switch is your allowlist, and anything that resolves a tool name dynamically lets any string the model produces reach your authenticated client, which is the one thing this shape exists to prevent.