Skip to Content
OrbzGuidesVoice assistants

Voice and talk runtime

Orbz remains silent when an element connects. After the host configures a voice engine and explicitly calls startTalking(), the built-in flow is deterministic and keeps captured values only in the element’s runtime memory:

  1. Ana introduces herself.
  2. Ana asks for the visitor’s name.
  3. The host passes the answer to receive().
  4. Ana uses that name in the next phrase.
  5. A response step uses an intelligence provider when configured, or a local fallback otherwise.

startTalking() is the opt-in boundary and resets the runtime context. Orbz does not persist the conversation in cookies, local storage, IndexedDB, or a backend.

Built-in talk data

import { DEFAULT_TALK_FLOW, talk } from "@neongate-ai/orbz"; console.log(talk.welcoming.text); console.log(talk.askName.capture); console.log(DEFAULT_TALK_FLOW);

Continue the flow

import "@neongate-ai/orbz/browser"; import type { OrbzElement } from "@neongate-ai/orbz"; const orb = document.querySelector<OrbzElement>("orb-z"); await orb?.receive("Jonatas"); console.log(orb?.talkContext.fullName);

English browser speech

For browser-provided speech, configure WebSpeechAdapter. It:

  • requests en-US explicitly;
  • waits for the browser’s asynchronous voice list;
  • selects an English voice instead of accepting a Portuguese default;
  • prefers higher-quality Google, Microsoft, natural, neural, or configured voices when the browser exposes them.
import '@neongate-ai/orbz/browser' import { WebSpeechAdapter, type OrbzElement } from "@neongate-ai/orbz"; const orb = document.createElement("orb-z") as OrbzElement; orb.voiceEngine = new WebSpeechAdapter({ language: "en-US", preferredVoices: ["Google US English", "Microsoft Aria Online"] }); document.body.append(orb); const startVoiceButton = document.querySelector<HTMLButtonElement>("[data-start-voice]"); startVoiceButton?.addEventListener("click", async () => { await orb.startTalking(); });

The actual installed voices still belong to the visitor’s browser and operating system. WebSpeechAdapter improves selection; it cannot turn a system voice into an OpenAI voice.

OpenAI-quality speech

Use OpenAISpeechAdapter for OpenAI text-to-speech quality. Its defaults are gpt-4o-mini-tts, the marin voice, MP3 output, and natural American-English instructions.

import '@neongate-ai/orbz/browser' import { OpenAISpeechAdapter, type OrbzElement } from "@neongate-ai/orbz"; const orb = document.createElement("orb-z") as OrbzElement; orb.voiceEngine = new OpenAISpeechAdapter({ endpoint: "/api/orbz/speech" }); document.body.append(orb); const startVoiceButton = document.querySelector<HTMLButtonElement>("[data-start-voice]"); startVoiceButton?.addEventListener("click", async () => { await orb.startTalking(); });

The endpoint is owned by the implementing application. It receives an OpenAI-compatible JSON body containing input, instructions, model, response_format, and voice, and returns the generated audio response. Keep the OpenAI API key on that server endpoint; never put it in browser code or in the npm package.

Applications using generated speech should clearly disclose that the voice is AI-generated.

Explicit activation and browser policy

Render a native <button> with a clear label such as Start voice, then call startTalking() from its click handler. Connecting the orb, assigning a voice engine, or navigating to a page never starts audio.

If the browser still rejects the requested audio with NotAllowedError, Orbz dispatches orbz-talk-error with the original error and retries the requested flow after the next pointer, keyboard, or touch interaction. Reset controls should not remount the element merely to unlock speech.

Supply a custom flow

import '@neongate-ai/orbz/browser' import { talk, type OrbzElement, type OrbzTalkStep } from "@neongate-ai/orbz"; const flow = [ talk.welcoming, talk.askName, talk.help ] as const satisfies readonly OrbzTalkStep[]; const orb = document.createElement("orb-z") as OrbzElement; orb.talkFlow = flow; document.body.append(orb);

Assign voiceEngine, talkFlow, and intelligence before calling startTalking() so the explicit run uses them.

Optional intelligence

import type { OrbzElement, OrbzIntelligencePort } from "@neongate-ai/orbz"; const intelligence: OrbzIntelligencePort = { async respond(input, context) { return productAgent.respond({ context, input }); } }; orb.intelligence = intelligence;

Events and visual state

While audio is playing, Orbz temporarily uses the speaking visual state and then restores the prior state.

EventDetail
orbz-speaking-change{ speaking: boolean }
orbz-talk-error{ error: unknown }

Orbz does not capture a microphone. The host owns speech recognition, text input, permissions, transcripts, product logic, and calls to receive().

Last updated on