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.
| Parameter | Type | Description |
|---|---|---|
config | EstuaryConfig | Client 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.
| Parameter | Type | Description |
|---|---|---|
serverUrl | string | Base URL of the Estuary server |
shareId | string | The 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.
| Parameter | Type | Default | Description |
|---|---|---|---|
text | string | -- | The message text |
textOnly | boolean | true | If 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.
| Parameter | Type | Default | Description |
|---|---|---|---|
text | string | -- | The line to speak. Empty/whitespace strings are ignored. |
textOnly | boolean | false | If 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.
| Parameter | Type | Description |
|---|---|---|
messageId | string (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 (requireslivekit-client)'auto'(default) -- Uses LiveKit if available, otherwise WebSocket
Returns: Promise<void>
Throws:
EstuaryErrorwith codeNOT_CONNECTEDif not connectedEstuaryErrorwith codeVOICE_ALREADY_ACTIVEif voice is already startedEstuaryErrorwith codeVOICE_NOT_SUPPORTEDif no transport is availableEstuaryErrorwith codeMICROPHONE_DENIEDif 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.
| Parameter | Type | Description |
|---|---|---|
imageBase64 | string | Base64-encoded image data |
mimeType | string | Image MIME type (e.g., 'image/jpeg') |
requestId | string (optional) | Request ID (if responding to a cameraCaptureRequest) |
text | string (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.
| Parameter | Type | Description |
|---|---|---|
preferences | object | Preferences to update |
preferences.enableVisionAcknowledgment | boolean (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
AudioPlayerwhen 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).
| Parameter | Type | Description |
|---|---|---|
messageId | string (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.
| Parameter | Type | Description |
|---|---|---|
characterId | string (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) => { /* ... */ });