@voicethere/client

@voicethere/client connects web and Node runtimes to VoiceThere sessions over WebRTC. Current npm cut: 0.8.3. Requires Node.js 22+ for the Node entry. Source: voicethere/client. Wire protocol: @node-webrtc-rust/signaling.

This page is the package map. Browser connect, iframe permissions, and autoplay live in Browser client. Widget designer and CDN JSON live in Embed widget.

Install

npm install @voicethere/client

Use a client API key (vthc_…) in browsers — create one in the dashboard or voicethere api-keys create --kind client. Do not embed org/project vth_ keys.

Entry points

ImportFor
@voicethere/clientconnectVoiceSession — local or cloud, shared by Node scripts and simple browsers.
@voicethere/client/browserstartSession, connectBrowserSession, mic UI helpers, captions.
@voicethere/client/embedFloating widget launcher. CDN script is a built copy of this entry.
@voicethere/client/nodeHeadless createNodeWebRtcRuntime for automated tests (needs optional peer @node-webrtc-rust/sdk + ws).

Local vs cloud

ModeWhenSignaling
localAgent runner on your machinews://127.0.0.1:8080/ws
cloudHosted VoiceThere sessionwss://signaling…/ws?token=join token from the sessions API
import { connectVoiceSession } from "@voicethere/client";

const client = await connectVoiceSession({
  mode: "local",
  signalingUrl: "ws://127.0.0.1:8080/ws",
  sessionId: "local-dev",
});

client.on("peer-joined", (peerId) => console.log("peer", peerId));

Browser session

import {
  startSession,
  connectBrowserSession,
} from "@voicethere/client/browser";

const provision = await startSession({
  apiBase: "https://sessions.voicethere.io/v1",
  projectId,
  headers: { Authorization: `Bearer ${apiKey}` },
  onSessionError: (event) => console.error(event.code, event.message),
});

if (provision.ok) {
  await connectBrowserSession({
    mode: "voice",
    credentials: provision.credentials,
    customerContext: { userId: "u_123" },
    onSessionError: (event) => console.error(event.code, event.message),
  });
}

Production sessions host: https://sessions.voicethere.io/v1. Each browser tab must call startSession() once — one orchestrator session id per client. Do not share join credentials across tabs. Allowed origins: Browser CORS.

peerId

When talking to a VoiceThere runner (or any server using VoiceAgentSessionHost):

  • Omit peerId — the SDK generates client-<random> (recommended).
  • Or pass an id that starts with client-.
  • Bare labels such as user-1 join signaling but never receive a WebRTC offer.

Reuse the same peerId for reconnectPolicy: "same-session".

Reconnect and billing

ActionWhat happens
Dashboard Reconnect or widget Connect after hangupstartSession() → new orchestrator session, new billing period once WebRTC connects
Unintentional dropDefault reconnectPolicy: "same-session" re-joins with the same credentials and peerId
session.reconnect()Same session — re-opens signaling only
session.disconnect() / disconnectAsync()client_disconnected
session.sendCloseSignal()client_close_signal

Billing starts when the runner reports a billable WebRTC leg (voice: connected peer connection + open control channel + agent; data-only: PC + data channel). Provision alone does not bill. Pass reconnectPolicy: "new-session" to disable automatic same-session retry. Idle timeout ends a quiet session with idle_timeout.

Session errors

Pass onSessionError to startSession and connectBrowserSession for provisioning failures, WebRTC errors, and runner session_error events. Legacy { type: "agent_error" } payloads map to AGENT_CHILD_CRASHED. Catalog: Session errors.

Register setRootConnectionErrorHandler once for process-wide signaling/WebRTC logging without attaching .on("error") on every connection.

Embed widget

Import from @voicethere/client/embed. CDN JSON (VoiceThereWidgetConfigV1) and inline options support preset, position, theme (including chat bubble fonts and colors), and customCss. widget.updateConfig({ … }) restyles without remounting. Client 0.8.2+ loads published fields from the CDN URL in the Access embed snippet. streamSpokenText typewrites agent captions when the agent calls speakAndChat({ stream: true }).

CSS hooks: .vt-widget, .vt-widget-launcher, .vt-widget-panel, message --incoming / --outgoing bubbles. Variables include --vt-color-primary, --vt-font-ui, --vt-panel-width. Export constants: WIDGET_CSS_CLASSES, WIDGET_CSS_VARIABLES.

← All documentation