Code mode

The escape hatch for whatever a site map can't say. A page that declares its own actions never fetches a map at all — code mode takes precedence, entirely, on that page.

Declare actions

<script>
window.GerryConfig = {
  key: 'pk_…',
  actions: {
    filter_category: {
      description: 'Narrows the list to one category.',
      parameters: { category: { type: 'string', description: 'Category name' } },
      required: ['category'],
      handler: ({ category }) => { applyCategory(category); return `${count()} products left.`; },
    },
  },
  context: () => `${count()} products are listed.`,
};
</script>
<script src="https://katman-widget.vercel.app/gerry.js" defer></script>

Load order doesn't matter: if GerryConfig exists before the widget script runs, it starts itself immediately. Otherwise, call Gerry.init({ … }) on the gerry:ready event — the demo page does it this way. The older Katman, KatmanConfig, katman:ready and katman.js names still work as aliases for all of this.

Options

actionsWhat the assistant may do. Names lowercase with underscores; descriptions one or two sentences; parameters string | number | boolean. Up to 24 actions, 8 parameters each, 600 characters of description — bounds the product enforces, not the voice provider's (see Security & privacy, rule 8).
handlerSync or async. Returns a string (spoken as-is), { summary, data } (summary is spoken, data goes to the model for follow-up questions), nothing at all ("Done."), or throws ("I couldn't do that"). Summary capped at 600 characters, data at 12 KB.
contextWhat's on screen right now — called by the model's built-in page_context tool. Without it, the widget reads only the page's title, its path, and any element you marked with data-katman-context; nothing else, ever (SECURITY.md rule 5).
onStateconnecting | live | error | stopped, for your own UI to react to.
positionbottom-right (default) or bottom-left. Superseded by appearance.position when both are given.
nameThe name shown on the control before a session opens (default "Gerry"); the tenant's assistant name replaces it once connected. Superseded by appearance.label.
appearanceThis page's own look, any subset of the tenant's appearance object (see What Gerry shows on the page) — wins over the tenant's, exactly as language does.
languageThe visitor's language (en | tr | de), explicit and winning over <html lang> and the browser's own language list. Sent with the session request.
debugLogs the call's life to the console.

Headless: drawing your own UI

With ui: false there's no orb and no captions; the site draws its own and drives the call through the object Gerry.init returns. Audio still plays normally.

const gerry = Gerry.init({
  key: 'pk_…',
  ui: false,
  onState: (state) => { /* connecting | live | error | stopped */ },
  onCaption: (text, from) => { /* from: 'user' | 'assistant' */ },
  onSpeaking: (source, level) => { /* source: 'user' | 'assistant', level 0..1 */ },
});
gerry.start();   // also stop(), toggle(), state, destroy()

Gerry.init always returns this same object, whether or not ui is on: start(), stop(), toggle(), the current state, and destroy(), which removes the badge entirely.

What the server does with a handler: nothing

The server never runs an action itself, in code mode or in map mode. A tool call becomes a command for the page that declared it, and that page's own code is what runs it — see Security & privacy, rule 1. An action name the page didn't declare gets "there is no such tool" back, every time.

No-code is still map mode

<script src="…/gerry.js" data-key="pk_…" defer> with no GerryConfig at all is map mode — the tenant's site map if it has one, page_context alone if it doesn't. Declaring actions is what opts a page out of the map fetch entirely; the two modes are never mixed on the same page.

Reloads

If a handler reloads the page, the conversation tries to continue on the new page with the same token; audio may need one more click on the control to resume. The reliable path stays an in-page handler that never navigates.

Questions: hello@heygerry.io. These pages describe what is built today; nothing here is a promise about what is not.