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:
- Ana introduces herself.
- Ana asks for the visitor’s name.
- The host passes the answer to
receive(). - Ana uses that name in the next phrase.
- 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-USexplicitly; - 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.
| Event | Detail |
|---|---|
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().