useLayercodeAgent Hook
TheuseLayercodeAgent hook provides a simple way to connect your React app to a Layercode agent, handling audio streaming, playback, and real-time communication.
connect() to start the session; call disconnect() to cleanly close it when the component unmounts or you no longer need the agent connection.
Hook Options
The ID of your Layercode agent.
Your backend endpoint that authorizes a client session and returns a
client_session_key and conversation_id.The conversation ID to resume a previous conversation (optional).
Any metadata included here will be passed along to your backend with all Layercode webhooks for this session.
Whether the browser microphone should be initialized immediately. Defaults to
true. Set to false to keep the SDK in text-only mode until you explicitly enable audio input.Whether agent audio should start playing immediately. Defaults to
true. Set to false to suppress speaker playback until you explicitly enable it (the agent connection still runs in the background).Whether microphone and speaker amplitude monitoring should run. Defaults to
true. Disable this when you start with audioInput: false to avoid unnecessary audio processing. When disabled, amplitude readings remain 0.Callback fired whenever the audio input state toggles. Receives a boolean (
true when the mic is active).Callback fired whenever the audio output state toggles. Receives a boolean (
true when the agent audio is audible).Callback when the connection is established. Receives
{ conversationId: string | null; config?: AgentConfig }.
Use config to inspect the effective agent configuration returned from authorizeSessionEndpoint.Callback when the connection is closed.
Callback when an error occurs. Receives an
Error object.Callback for custom data messages from the server (see
response.data events from your backend).Callback when VAD detects that the user started or stopped speaking. Receives a boolean.
Callback when the agent starts or stops speaking. Receives a boolean.
Callback when
mute()/unmute() are invoked. Receives a boolean for the new muted state.Return Values
TheuseLayercodeAgent hook returns an object with the following properties:
State
The connection status. One of
"initializing", "disconnected", "connecting", "connected", or "error". The hook begins in "initializing" before the client reports a lifecycle status.Real-time amplitude of the user’s microphone input (0-1). Useful for animating UI when the user is speaking.
Real-time amplitude of the agent’s audio output (0-1). Useful for animating UI when the agent is speaking.
Current audio input state.
false means the SDK has not requested microphone access.Current audio output state.
false means agent audio playback is muted locally.Whether the user is currently detected as speaking by VAD.
Whether the agent is currently speaking (based on active audio playback).
Whether the local microphone stream is muted.
The conversation ID the hook is currently connected to, or
null when none is active. Useful for resuming or persisting sessions.Turn-taking (Push-to-Talk)
Layercode supports both automatic and push-to-talk turn-taking. For push-to-talk, use these methods to signal when the user starts and stops speaking: Automatic versus push-to-talk behavior is configured on the backend viaAgentConfig.transcription.trigger and AgentConfig.transcription.can_interrupt. Push-to-talk skips the VAD model because you drive turn boundaries manually.
triggerUserTurnStarted(): void Signals that the user has started speaking (for push-to-talk mode). Interrupts any agent audio
playback.
triggerUserTurnFinished(): void Signals that the user has finished speaking (for push-to-talk mode).
Audio Input Controls
setAudioInput(next: boolean | ((prev: boolean) => boolean)): void Enables or disables microphone capture without recreating the client. Use this to defer the browser permission prompt until the user switches into voice mode.
Agent Audio Output Controls
setAudioOutput(next: boolean | ((prev: boolean) => boolean)): void Enables or disables local playback of agent audio without disconnecting from the session.
Need to hide agent audio temporarily (for example, when playing other media in your UI)? TogglesetAudioOutput(false)while the session stays active, and re-enable withsetAudioOutput(true)once you want to hear the agent again. Combine this with theaudioOutputstate or theonAudioOutputChangedcallback to drive your UI controls.
Audio / Mic Controls
mute(): void Stops sending microphone audio to the server while keeping the connection active.
unmute(): void Resumes sending microphone audio after a local mute.
Text messages
Use this method when the user submits a chat-style message instead of speaking.sendClientResponseText(text: string): void Sends a
client.response.text to the server and interrupts any agent audio playback. The server emits user.transcript and manages turn boundaries; the client does not send trigger.turn.end here.sendClientResponseData(payload: Record<string, any>): void Sends a JSON-serializable
payload to your agent backend without affecting the current turn. The data surfaces as a data webhook event. See docs page: Send JSON data from the client.Notes & Best Practices
- The hook manages microphone access, audio streaming, and playback automatically.
- Start text-first experiences with
audioInput: falseand callsetAudioInput(true)when the user explicitly opts into voice. Pair this withenableAmplitudeMonitoring: falseto skip microphone metering until voice is enabled. - The
metadataoption allows you to set custom data which is then passed to your backend webhooks for this session (useful for user/session tracking). - The
conversationIdcan be used to resume a previous conversation, or omitted to start a new one. The hook will reportnulluntil it connects.
Authorizing Sessions
To connect a client (browser) to your Layercode voice agent, you must first authorize the session. The SDK will automatically send a POST request to the path (or url if your backend is on a different domain) passed in theauthorizeSessionEndpoint option. In this endpoint, you will need to call the Layercode REST API to generate a client_session_key and conversation_id (if it’s a new conversation).
If your backend is on a different domain, set
authorizeSessionEndpoint to the full URL (e.g., https://your-backend.com/api/authorize).client_session_key to the frontend.
This also allows you to authenticate your user, and set any additional metadata that you want passed to your backend webhook.
How it works:
-
Frontend:
The SDK automatically sends a POST request to your
authorizeSessionEndpointwith a request body. -
Your Backend:
Your backend receives this request, then makes a POST request to the Layercode REST API
/v1/agents/web/authorize_sessionendpoint, including yourLAYERCODE_API_KEYas a Bearer token in the headers. -
Layercode:
Layercode responds with a
client_session_key(and aconversation_id), which your backend returns to the frontend. -
Frontend:
The SDK uses the
client_session_keyto establish a secure WebSocket connection to Layercode.
Custom Authorization
useLayercodeAgent exposes the same authorizeSessionRequest option as the vanilla SDK. Provide this function to inject custom headers, cookies, or a different HTTP client when calling your backend.
authorizeSessionRequest is not supplied, the hook defaults to a standard fetch call that POSTs the JSON body to authorizeSessionEndpoint using Content-Type: application/json.
Request payload
The SDK sends these fields in the authorization request body:agent_id– ID of the agent to connect.metadata– metadata supplied when creating the hook.sdk_version– version string of the React SDK (for example,"2.2.1").conversation_id– present only when reconnecting to an existing conversation.
Response payload
Your endpoint must respond with JSON containing these fields:response
Troubleshooting
AudioWorklet InvalidStateError on first connect
If the browser complains thatAudioWorklet does not have a valid AudioWorkletGlobalScope, the initial connect() probably ran before the user interacted with the page. Browsers block new AudioContext instances (and therefore audioWorklet.addModule()) until they detect a click, tap, or key press.
To resolve it:
- Trigger the first
connect()from a user gesture—e.g., a “Start voice agent” button that awaitsconnect(). - Keep
disconnect()inside an effect cleanup so teardown still runs automatically. - Expect the issue mostly during rapid development reloads or in React Strict Mode, where components mount twice. In production, users typically gesture before launching the agent, so reconnects after the initial gesture are safe.