Skip to main content
@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

Requires React 18 or later. The package re-exports the Web SDK’s main exports (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.
See Authenticated sessions for the backend side. 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:
Start calls made from a user interaction are safe under React Strict Mode’s effect replay.

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, startSession resolves with its id instead of starting a second one; two concurrent calls (a double-click) share one start.
  • Hangup-during-start safe. Calling endSession while 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. A startSession requested during that cleanup waits, then creates a fresh session. If another endSession cancels that queued restart, it rejects with an error whose name is "AbortError".
  • Failure resets. If startSession rejects (see Errors), status returns 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 in AgentSessionProvider 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
Components inside the provider read the shared state with 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 text is refined in place; always re-render from text, never append.
  • An agent turn grows with each response delta and flips to final: true when 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
If you only want finalized messages in order, without streaming updates, subscribe to the session’s 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.