Browser client

@voicethere/client connects web and Node runtimes to VoiceThere voice sessions over WebRTC. Use local mode against a runner on your machine, or cloud mode with credentials from the session API.

Install

npm install @voicethere/client

Package matrix: npm packages.

Local mode (developer runner)

Point at a signaling WebSocket on localhost while you develop an agent against a local session worker:

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));

Cloud mode (hosted VoiceThere)

Create a client API key in the dashboard (vthc_…) — safe to embed in browser apps. Start a session via the session API, then pass credentials to the client:

const res = await fetch("https://sessions.voicethere.io/v1/sessions", {
  method: "POST",
  headers: {
    Authorization: "Bearer vthc_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ project_id: "<project-uuid>" }),
});

const credentials = await res.json();

const client = await connectVoiceSession({
  mode: "cloud",
  credentials: {
    sessionId: credentials.session_id,
    joinToken: credentials.join_token,
    signalingUrl: credentials.signaling_url,
    roomId: credentials.room_id,
    iceServers: credentials.ice_servers,
  },
});

Deploy your agent first — see Quickstart. For production sites, add your page origin on the project Browser CORS origins Access panel so browsers can call the sessions API.

Browser imports

import {
  connectVoiceSession,
  connectChatSession,
} from "@voicethere/client/browser";

connectChatSession adds DataChannel text chat alongside voice when your project supports both.

Embed widget

import { createVoiceThereWidget } from "@voicethere/client/embed";

Floating chat launcher for quick demos without building a full UI.

Nested iframes and permissions

When you embed the widget inside another page, set allow="microphone; autoplay" on every ancestor iframe. Browsers block the microphone prompt when a nested iframe lacks Permissions Policy — users often see no dialog at all.

Microphone denied but session connected

Voice sessions can still connect with a silent outbound track when getUserMedia is denied or unavailable. Inbound agent audio does not require a live microphone. The widget shows an amber notice with Request microphone so users can grant access when the browser allows it.

Autoplay and sound

If the browser blocks autoplay, tap Enable sound in the widget after connect (user gesture unlocks the hidden <audio> element).

Voice vs data-only

Use mode: "voice" (or voice+data) for microphone and agent audio. mode: "chat" is data-channel only — no mic capture and no inbound TTS playback path.

Session errors

Handle onSessionError for agent crashes, idle timeout, and recoverable restarts. Error codes are documented in Session errors.

Node / headless

import { createNodeWebRtcRuntime } from "@voicethere/client/node";

Pass the runtime into connectVoiceSession when WebRTC is not provided by the browser (automated E2E, load tests).

Related

← All documentation