Skip to main content

EstuaryClient

The main class for interacting with the Estuary platform. Manages the WebSocket connection, voice sessions, and provides access to the memory API.

import { EstuaryClient } from '@estuary-ai/sdk';

const client = new EstuaryClient(config);

Constructor

new EstuaryClient(config)

Creates a new client instance. Either apiKey or sessionToken must be provided in the config.

ParameterTypeDescription
configEstuaryConfigClient configuration

Throws: EstuaryError with code AUTH_FAILED if neither apiKey nor sessionToken is provided.

const client = new EstuaryClient({
serverUrl: 'https://api.estuary-ai.com',
apiKey: 'est_your_api_key',
characterId: 'your-character-uuid',
playerId: 'user-123',
});

Static Methods

EstuaryClient.openShare(serverUrl, shareId)

Opens a permanent share link. Calls the backend's share endpoint to mint a fresh session token and resolve character metadata. Use the returned fields to construct an EstuaryClient with sessionToken auth.

ParameterTypeDescription
serverUrlstringBase URL of the Estuary server
shareIdstringThe share link identifier

Returns: Promise<ShareOpenResponse>

Throws: EstuaryError with code REST_ERROR if the share open request fails.

import { EstuaryClient } from '@estuary-ai/sdk';

const share = await EstuaryClient.openShare(
'https://api.estuary-ai.com',
'share-abc-123',
);

const client = new EstuaryClient({
serverUrl: share.serverUrl,
sessionToken: share.sessionToken,
characterId: share.characterId,
playerId: share.playerId,
});

await client.connect();

See ShareOpenResponse for the full response shape.


Connection

connect()

Connects to the Estuary server and authenticates with the configured apiKey (or sessionToken). Returns a promise that resolves with session info on success.

Returns: Promise<SessionInfo>

Throws: EstuaryError with code CONNECTION_FAILED or AUTH_FAILED

const session = await client.connect();
console.log('Session ID:', session.sessionId);

disconnect()

Disconnects from the server. Stops any active voice session, clears audio playback, and cleans up resources. Awaits stopVoice() internally, so it returns a promise.

Returns: Promise<void>

await client.disconnect();

isConnected

Whether the client is currently connected and authenticated.

Type: boolean (read-only)

if (client.isConnected) {
client.sendText('Hello!');
}

connectionState

The current connection state.

Type: ConnectionState (read-only)

console.log(client.connectionState); // 'connected', 'connecting', etc.

Text

sendText(text, textOnly?)

Sends a text message to the character.

ParameterTypeDefaultDescription
textstring--The message text
textOnlybooleantrueIf true, suppresses voice response (text only). Pass false to receive voice audio.

Throws: EstuaryError with code NOT_CONNECTED

client.sendText('Hello!'); // text only (default)
client.sendText('Tell me a story', false); // also stream voice audio

sayLine(text, textOnly?)

Scripts the character to say a specific prewritten line via TTS. Skips the LLM entirely -- the text is fed directly to TTS and saved to chat history as a normal assistant message. Any in-progress response is interrupted before the line is spoken.

ParameterTypeDefaultDescription
textstring--The line to speak. Empty/whitespace strings are ignored.
textOnlybooleanfalseIf true, only botResponse is emitted (no audio).

Throws: EstuaryError with code NOT_CONNECTED

client.sayLine('Welcome back, traveler.');
client.sayLine('System message', true); // text only, no TTS

The response uses the same botResponse and botVoice events as a normal reply; isInterjection will be false.

interrupt(messageId?)

Interrupts the current bot response and clears queued audio.

ParameterTypeDescription
messageIdstring (optional)Specific message to interrupt

Throws: EstuaryError with code NOT_CONNECTED

client.interrupt();
client.interrupt('msg-123');

Voice

startVoice()

Starts a voice session. Requests microphone permission and begins streaming audio to the server.

The voice transport used depends on the voiceTransport config option:

  • 'websocket' -- Streams PCM audio over WebSocket
  • 'livekit' -- Connects via LiveKit WebRTC (requires livekit-client)
  • 'auto' (default) -- Uses LiveKit if available, otherwise WebSocket

Returns: Promise<void>

Throws:

  • EstuaryError with code NOT_CONNECTED if not connected
  • EstuaryError with code VOICE_ALREADY_ACTIVE if voice is already started
  • EstuaryError with code VOICE_NOT_SUPPORTED if no transport is available
  • EstuaryError with code MICROPHONE_DENIED if microphone permission is denied
await client.startVoice();

stopVoice()

Stops the active voice session. Releases the microphone and cleans up the voice manager. No-op if voice is not active.

Returns: Promise<void>

await client.stopVoice();

toggleMute()

Toggles the microphone mute state.

Throws: EstuaryError with code VOICE_NOT_ACTIVE if no voice session is active

Returns: void

client.toggleMute();

isMuted

Whether the microphone is currently muted.

Type: boolean (read-only)

console.log('Muted:', client.isMuted);

isVoiceActive

Whether a voice session is currently active.

Type: boolean (read-only)

if (client.isVoiceActive) {
await client.stopVoice();
}

Camera

sendCameraImage(imageBase64, mimeType, requestId?, text?)

Sends a camera image for vision-language model processing.

ParameterTypeDescription
imageBase64stringBase64-encoded image data
mimeTypestringImage MIME type (e.g., 'image/jpeg')
requestIdstring (optional)Request ID (if responding to a cameraCaptureRequest)
textstring (optional)Text to accompany the image

Throws: EstuaryError with code NOT_CONNECTED

client.sendCameraImage(base64Data, 'image/jpeg', requestId, 'What is this?');

updatePreferences(preferences)

Updates session-level preferences.

ParameterTypeDescription
preferencesobjectPreferences to update
preferences.enableVisionAcknowledgmentboolean (optional)Whether the character acknowledges before analyzing images

Throws: EstuaryError with code NOT_CONNECTED

client.updatePreferences({ enableVisionAcknowledgment: false });

Audio

notifyAudioPlaybackComplete(messageId?)

Notifies the server that audio playback has completed for a message. This is called automatically:

  • WebSocket transport: by the built-in AudioPlayer when its drain callback fires.
  • LiveKit transport: when the bot's speaking state transitions from speaking to silent (via the LiveKit speaking-state callback).

You only need to call this manually if you implement a custom audio playback path (for example, intercepting botVoice events and rendering audio yourself).

ParameterTypeDescription
messageIdstring (optional)The message whose audio finished playing

Throws: EstuaryError with code NOT_CONNECTED

client.notifyAudioPlaybackComplete('msg-123');

Character

getCharacter(characterId?)

Fetches character details (3D model URL, avatar, tagline, etc.) from the REST API.

ParameterTypeDescription
characterIdstring (optional)Character to fetch. Defaults to the characterId configured on the client.

Returns: Promise<CharacterInfo> -- see CharacterInfo.

Throws: EstuaryError with code NOT_CONNECTED if the client was constructed with a sessionToken instead of an apiKey (REST is not available with session-token auth -- use a server-side proxy in that case).

const character = await client.getCharacter();
console.log('3D model URL:', character.modelUrl);

// Or explicitly fetch a different character
const other = await client.getCharacter('character-uuid-2');

Properties

memory

The memory API client for querying memories, knowledge graphs, and facts.

Type: MemoryClient (read-only)

Throws: EstuaryError with code NOT_CONNECTED when accessed if the client was constructed with a sessionToken (REST is not available with session-token auth).

const facts = await client.memory.getCoreFacts();

See Memory & Knowledge Graph for usage details.

session

The current session info. null if not connected.

Type: SessionInfo | null (read-only)

if (client.session) {
console.log('Conversation:', client.session.conversationId);
}

Event Methods

EstuaryClient extends TypedEventEmitter and provides typed event subscription:

on(event, listener)

Subscribe to an event. See Events and Types for the full event map.

client.on('botResponse', (response) => { /* ... */ });

off(event, listener)

Remove an event listener.

client.off('botResponse', handler);

once(event, listener)

Subscribe to an event for a single invocation.

client.once('connected', (session) => { /* ... */ });