@fishaudio/agent-client runs a live voice conversation with your agent from any web page: open the microphone, stream audio both ways, and react to typed events for transcripts, agent state, and tool calls. The SDK handles the realtime transport (WebRTC) internally — your code never touches connection plumbing.
Using React? @fishaudio/agent-react wraps this SDK in hooks and a provider.
Install
Start a session
AgentSession.start() creates the session, connects, and opens the microphone in one call. Authenticate one of two ways:
agentId— for public agents. The SDK creates the session directly from the browser; no backend needed.sessionToken— for private agents. Your backend callsPOST /v1/agent/sessionswith your API key and hands the JSON response to the browser; pass it through unchanged. See Authentication.
Options
Session lifecycle
A session moves through a fixed state machine, surfaced by thestatusChange event and the session.status property:
States
disconnect fires with a reason (also available as session.endReason):
Brief network drops don’t end the session: the SDK moves to
reconnecting and back to connected automatically, reusing the same session.
Events
The session is a typed event emitter — subscribe withsession.on(event, handler), remove with off, or use once.
Subscribe to events
Transcript semantics
Transcripts on both sides arrive as segments — one segment per utterance or response, identified bysegmentId:
- User segments: interim results replace the entire segment text (they never append). Render by upserting on
segmentId;final: truemarks the segment as finalized. - Agent segments: text streams in sync with audio playback — what you display matches what the user has actually heard. If the agent is interrupted, the segment finalizes containing only the words that were spoken.
- The
messageevent delivers only finalized messages from both sides, in order — use it when you want a simple transcript list without handling interim updates.
Agent modes
session.mode (and the modeChange event) tracks what the agent is doing, for driving an orb or status indicator:
session.isSpeaking is a convenience boolean for the speaking mode. Mode does not react to the user’s own speech — for instant “the mic hears you” feedback, poll getInputVolume() locally.
Send text
Users can type instead of talking, in the same session:Text input
Audio controls
Select specific devices at start with the
audio option (inputDeviceId / outputDeviceId).
Audio visualizer
Client tools
Register handlers for tools of typeclient declared on the agent — the agent calls them mid-conversation and your return value goes back to the model:
Register a client tool
Errors
Failures surface asFishAgentError — thrown from AgentSession.start() when the session can’t be created, emitted on the error event otherwise. Each carries a code, an optional statusCode (set on session-creation HTTP errors), and cause.
provider_error and internal_error carry only the category code — raw
provider or infrastructure details are never sent to the browser.Handle errors
End the session
Hang up
Going further
React SDK
Hooks, provider, and visualizer components on top of this SDK.
Authentication
Mint session tokens from your backend for private agents.
Public agents
Backend-free sessions with origin allow-lists and rate limits.
Wire protocol
The wire-level events underneath the SDK.

