Skip to main content

Quickstart Guide

Get up and running with UG Labs SDK in minutes. This guide will walk you through creating a simple conversational AI application.

Prerequisites

Install the SDK

npm install ug-js-sdk

Or using yarn:

yarn add ug-js-sdk

Get Your API Key

Get your API key from the UG Labs Console

Basic Example

Here's a simple example that creates a conversation and sends a text message:

import { ConversationManager, ConversationConfig } from 'ug-js-sdk';

// Initialize the conversation manager
const config: ConversationConfig = {
apiUrl: 'wss://pug.stg.uglabs.app',
apiKey: 'your-api-key',
federatedId: 'user-123',
prompt: 'You are a helpful assistant.',

hooks: {
onStateChange: (state) => console.log('State:', state),
onTextMessage: (event) => console.log('Assistant:', event.text),
onError: (error) => console.error('Error:', error.message),
},
};

const conversation = new ConversationManager(config);

// Start the conversation
async function start() {
try {
// Initialize connection (establishes WebSocket, requests mic if needed)
await conversation.initialize();

// Send a text message
await conversation.sendText('Hello! How are you?');

} catch (error) {
console.error('Failed to start conversation:', error);
}
}

start();

Step-by-Step Explanation

1. Import and Configure

import { ConversationManager, ConversationConfig } from 'ug-js-sdk';

const config: ConversationConfig = {
apiUrl: 'wss://pug.stg.uglabs.app',
apiKey: 'your-api-key',
federatedId: 'user-123', // Unique user ID for conversation continuity
prompt: 'You are a friendly assistant.',

hooks: {
onTextMessage: (event) => console.log('Assistant:', event.text),
},
};

The ConversationManager is the main class that handles all interactions with the UG Labs API. Configuration is passed directly to the constructor.

2. Set Up Event Hooks

hooks: {
onStateChange: (state) => console.log('State:', state),
onTextMessage: (event) => console.log('Assistant:', event.text),
onDataMessage: (event) => console.log('Data:', event.data),
onError: (error) => console.error('Error:', error.message),
}

Event hooks receive real-time updates from the conversation:

  • onTextMessage: Streaming text chunks from the assistant
  • onDataMessage: Structured data from utilities (classifiers, extractors)
  • onStateChange: Conversation state transitions
  • onError: Error notifications

3. Initialize and Interact

const conversation = new ConversationManager(config);

// Connect to the API
await conversation.initialize();

// Send text messages
await conversation.sendText('Hello! How are you?');

First, create the manager with your config, then call initialize() to establish the WebSocket connection.

Adding Voice Interaction

To enable voice input and output:

const config: ConversationConfig = {
apiUrl: 'wss://pug.stg.uglabs.app',
apiKey: 'your-api-key',
federatedId: 'user-123',
prompt: 'You are a helpful voice assistant.',

// Enable audio capabilities
inputCapabilities: { audio: true, text: true },
capabilities: { audio: true, subtitles: true },

// Optional: Configure voice
voiceProfile: {
provider: 'elevenlabs',
voice_id: 'your-voice-id',
speed: 1.0,
},

hooks: {
onStateChange: (state) => console.log('State:', state),
onTextMessage: (event) => console.log('Assistant:', event.text),
},
};

const conversation = new ConversationManager(config);
await conversation.initialize();

// Start listening for voice input (requires user gesture in browser)
await conversation.startListening();

// Later, stop listening
await conversation.stopListening();

Using Utilities

Add structured outputs with classification or extraction utilities:

const config: ConversationConfig = {
apiUrl: 'wss://pug.stg.uglabs.app',
apiKey: 'your-api-key',
federatedId: 'user-123',
prompt: 'You are a sentiment analysis assistant.',

// Step 1: Define utilities
utilities: {
sentiment: {
type: 'classify',
classification_question: 'What is the sentiment: {{user_input}}',
answers: ['positive', 'negative', 'neutral'],
},
},

// Step 2: Activate utilities (REQUIRED!)
onOutputUtilities: ['sentiment'],

hooks: {
// Step 3: Handle utility results
onDataMessage: (event) => {
console.log('Sentiment:', event.data.sentiment);
},
},
};

Important: Utilities must be both defined in utilities AND activated in one of:

  • onOutputUtilities - Run after assistant response (recommended, lowest latency)
  • onInputUtilities - Run before prompt (blocking, adds latency)
  • onInputNonBlockingUtilities - Run in parallel with LLM

Complete React Example

Here's a complete example using React:

import React, { useEffect, useState, useRef } from 'react';
import { ConversationManager, ConversationConfig, ConversationState } from 'ug-js-sdk';

function ChatApp() {
const [messages, setMessages] = useState<{ role: string; content: string }[]>([]);
const [input, setInput] = useState('');
const [state, setState] = useState<ConversationState>('uninitialized');
const managerRef = useRef<ConversationManager | null>(null);

useEffect(() => {
const config: ConversationConfig = {
apiUrl: 'wss://pug.stg.uglabs.app',
apiKey: 'your-api-key',
federatedId: 'user-123',
prompt: 'You are a helpful assistant.',

// Text-only mode
inputCapabilities: { audio: false, text: true },
capabilities: { audio: false },

hooks: {
onStateChange: (newState) => setState(newState),
onTextMessage: (event) => {
setMessages(prev => {
// Append to last assistant message or create new one
const last = prev[prev.length - 1];
if (last?.role === 'assistant') {
return [
...prev.slice(0, -1),
{ role: 'assistant', content: last.content + event.text }
];
}
return [...prev, { role: 'assistant', content: event.text }];
});
},
onError: (error) => console.error('Error:', error.message),
},
};

const manager = new ConversationManager(config);
managerRef.current = manager;
manager.initialize();

// Cleanup on unmount
return () => {
manager.dispose();
};
}, []);

const sendMessage = async () => {
if (!input.trim() || !managerRef.current) return;

setMessages(prev => [...prev, { role: 'user', content: input }]);
await managerRef.current.sendText(input);
setInput('');
};

return (
<div>
<div>Status: {state}</div>
<div className="messages">
{messages.map((msg, i) => (
<div key={i} className={msg.role}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
disabled={state !== 'idle' && state !== 'listening'}
/>
<button onClick={sendMessage} disabled={state !== 'idle' && state !== 'listening'}>
Send
</button>
</div>
);
}

export default ChatApp;

Using configRef (Load Config from Backend)

Instead of defining prompt and utilities in code, you can load them from a deployed configuration:

const config: ConversationConfig = {
apiUrl: 'wss://pug.stg.uglabs.app',
apiKey: 'your-api-key',
federatedId: 'user-123',

// Load configuration from backend
// Created via console.stg.uglabs.app/playground → Deploy
configRef: 'char_abc123_v2',

hooks: {
onTextMessage: (event) => console.log(event.text),
},
};

When configRef is set, prompt, utilities, and voiceProfile are loaded from the backend.

Next Steps

Troubleshooting

Connection Issues

If you're having trouble connecting:

  1. Verify your API key is correct
  2. Check your network connection
  3. Ensure you're using HTTPS for voice features (WebSocket + mic require secure context)
  4. Check browser console for detailed error messages

Audio Not Working

If audio input/output isn't working:

  1. Grant microphone permissions when prompted
  2. Ensure your browser supports Web Audio API and MediaRecorder
  3. Try using headphones to avoid echo
  4. Check that inputCapabilities.audio is set to true
  5. Call startListening() after a user gesture (button click)

Utilities Not Returning Data

If utilities don't produce results:

  1. Verify utility is defined in utilities object
  2. Verify utility name is in onOutputUtilities array (most common issue!)
  3. Implement onDataMessage hook to receive results

WASM/ONNX Issues

For issues with voice activity detection (VAD) or ONNX model loading, see the WASM Setup Troubleshooting guide.