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