@fishaudio/agent-react wraps the Web SDK in idiomatic React: a useConversation hook for session control, an optional provider that shares one session across your component tree, a streaming chat-log hook, and a ready-made audio visualizer. The SDK handles microphone capture, audio playback, and transport internally. Authentication, events, client tools, and error semantics are the Web SDK’s; everything documented there applies here.
Web SDK reference
Every option, event, method, and error code.
Authenticated sessions
Create session tokens on your backend.
Public agents
Connect with just an agent id, no backend.
Install
AgentSession, FishAgentError, and their types), so app code can import everything from @fishaudio/agent-react.
Quick start
A minimal call UI: start a call, show what the agent is doing, mute, hang up. This example connects to a public agent by id.App.tsx
status, mode, and isSpeaking are React state, so your component re-renders as the conversation progresses. When the component unmounts, the session ends automatically.
Call
startSession from a user gesture (such as a click handler) so the
browser allows microphone capture and audio playback.Connect to a private agent
For agents that are not public, your backend creates the session with your API key (POST /v1/agent/sessions) and returns the response to the browser. Pass it to startSession unchanged.
startSession accepts the same options as AgentSession.start in the Web SDK, including clientTools. Session settings such as overrides and dynamicVariables apply when you connect with an agentId; with a sessionToken, your backend sets them in its session-creation request instead.
Next.js
The SDK only touches browser APIs when a session starts, so importing it in Server Components is safe, but any component that calls the hooks needs the"use client" directive. Create session tokens in a Route Handler so your API key stays on the server:
useConversation(defaults?)
Owns one session’s lifecycle and re-renders on its state changes. defaults is merged into every startSession(overrides?) call, with overrides winning per key. Put long-lived options such as clientTools, callbacks, or a public agentId in defaults, and per-call values such as a freshly fetched sessionToken in overrides. The latest render’s defaults are used, so inline objects are fine.
Returned value
For transcripts, tool-call events, and error handling, subscribe to events on
session or pass callbacks in defaults. See the Web SDK event reference.
Lifecycle details
-
Double-start safe. If a session is already live,
startSessionresolves with its id instead of starting a second one; two concurrent calls (a double-click) share one start. -
Hangup-during-start safe. Calling
endSessionwhile a start is still waiting on session creation, the microphone permission, or the realtime connection marks the conversation ended and waits for that start to settle; a late connection is closed before the hook exposes it. AstartSessionrequested during that cleanup waits, then creates a fresh session. If anotherendSessioncancels that queued restart, it rejects with an error whosenameis"AbortError". -
Failure resets. If
startSessionrejects (see Errors),statusreturns to"idle"and the hook is ready for another attempt: - Unmount ends the call. No leaked microphones after navigation. Keep the component mounted for the call’s duration; lift it up, or use the provider, if the page around it changes.
-
The message senders (
sendUserMessage,sendUserActivity,interrupt) are no-ops before the session connects; they do not queue.
Share one session across components
Wrap your tree inAgentSessionProvider when several components need the same conversation: call controls in the header, a transcript panel elsewhere. The provider hosts one useConversation(options), so its options prop takes the hook’s defaults.
App.tsx
useAgentSessionContext() instead of calling useConversation themselves. It returns the same fields, so the quick-start CallButton only needs its hook call swapped.
The session-consuming hooks and components (
useAgentMessages, useAudioLevels, <AgentAudioVisualizer />) all resolve their session the same way: pass one explicitly (useAgentMessages(session)) or omit the argument to use the surrounding provider’s. Passing null explicitly means “no session”; it does not fall back to the provider.
Chat log with useAgentMessages
useAgentMessages(session?) returns the conversation as a live list of ChatMessage entries in order, aggregated from the session’s transcript events so you do not have to reduce them yourself:
- A user turn appears as soon as transcription starts and its
textis refined in place; always re-render fromtext, never append. - An agent turn grows with each response delta and flips to
final: truewhen the turn completes. - Both directions update the existing entry (matched by
key), so list order and keys stay stable across renders. - A component mounted mid-session starts from
session.getTranscript(), so turns that streamed before it subscribed still appear, without duplicates. - The log resets when a new session starts. Persist it yourself (for example into app state on
disconnect) if you need history across calls. - Events dropped during a reconnection are not replayed, so the log may skip turns lost to an outage.
Voice and text chat panel
message event directly instead.
Audio levels and visualizer
useAudioLevels(session?, fps?) returns polled { input, output } levels in 0 to 1: input is the microphone, output is the agent’s voice. It samples 20 times per second by default; raise fps for snappier meters, lower it to reduce re-renders. Both are 0 before the session connects.
Microphone meter
<AgentAudioVisualizer /> renders animated canvas frequency bars driven by the agent’s output audio, a drop-in “the agent is talking” indicator. Inside an AgentSessionProvider it picks up the active session automatically; elsewhere, pass a session prop. The bars are colored by the canvas’s CSS color, so it themes like text.
For a fully custom visualization, build on
useAudioLevels or the session’s frequency-data methods from the Web SDK.
Going further
Web SDK
Full option, event, and method reference behind these hooks.
Client tools
Let the agent call functions in your app.
Authenticated sessions
Create session tokens server-side for private agents.
Dynamic variables
Personalize each session at start time.

