Examples & Demos
This page provides complete example implementations for both JavaScript and Unity SDKs.
GitHub Example Repositories
Complete Working Examples on GitHub
We maintain ready-to-run example projects with full source code on GitHub.
JavaScript Examples
Repository: uglabs/ug-js-sdk
The JavaScript SDK repository includes working examples demonstrating:
- Basic text conversations
- Voice-enabled chat
- Image generation
- Custom utilities (classify and extract)
- React integration examples
- Event handling patterns
Unity Examples
Repository: uglabs/ug-demos-unity
Complete Unity demo projects showcasing:
- Interactive NPC conversations
- Voice-controlled game mechanics
- Avatar integration
- Event-driven gameplay
- UI/UX best practices for Unity
Basic Chat Example (JavaScript)
This example demonstrates a simple text-based conversation with the UG Labs API.
Overview
In this example, you'll learn how to:
- Connect to the WebSocket API
- Authenticate with an API key
- Configure the conversation
- Send and receive text messages
- Handle streaming responses
Using the SDK
Installation
npm install ug-js-sdk
Complete Example
import { ConversationManager } from 'ug-js-sdk';
// Initialize conversation
const conversation = new ConversationManager({
apiKey: 'your-api-key',
federatedId: 'user-123' // Optional unique user identifier
});
// Set up event listeners
conversation.on('text-event', (event) => {
console.log('Assistant:', event.text);
if (event.done) {
console.log('Response complete');
}
});
conversation.on('error', (error) => {
console.error('Error:', error);
});
// Start conversation
async function startChat() {
try {
// Connect and authenticate
await conversation.start();
// Configure the assistant
await conversation.setConfiguration({
prompt: 'You are a friendly and helpful assistant.',
temperature: 0.7
});
// Send messages
await conversation.sendText('Hello! What can you help me with?');
// You can send follow-up messages
setTimeout(async () => {
await conversation.sendText('Tell me a fun fact about space.');
}, 5000);
} catch (error) {
console.error('Failed to start conversation:', error);
}
}
startChat();
Using the WebSocket API Directly
If you prefer to use the WebSocket API directly without the SDK:
// Step 1: Get access token
const authResponse = await fetch('https://pug.stg.uglabs.app/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: 'your-api-key',
federated_id: 'user-123'
})
});
const { access_token } = await authResponse.json();
// Step 2: Connect to WebSocket
const ws = new WebSocket('wss://pug.stg.uglabs.app/interact');
ws.onopen = () => {
console.log('WebSocket connected');
// Step 3: Authenticate
ws.send(JSON.stringify({
kind: 'authenticate',
uid: crypto.randomUUID(),
access_token: access_token
}));
};
// Step 4: Handle messages
let isAuthenticated = false;
let isConfigured = false;
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.kind === 'authenticated') {
console.log('Authenticated successfully');
isAuthenticated = true;
// Step 5: Set configuration
ws.send(JSON.stringify({
kind: 'set_configuration',
uid: crypto.randomUUID(),
prompt: 'You are a friendly and helpful assistant.'
}));
}
if (message.kind === 'configured') {
console.log('Configuration set');
isConfigured = true;
// Step 6: Send first message
ws.send(JSON.stringify({
kind: 'interact',
uid: crypto.randomUUID(),
text: 'Hello! What can you help me with?',
audio_output: false
}));
}
if (message.kind === 'text') {
// Step 7: Receive response
console.log('Assistant:', message.text);
if (message.done) {
console.log('Response complete');
}
}
if (message.kind === 'error') {
console.error('Error:', message.error);
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('WebSocket closed');
};
React Example
Here's how to build a simple chat interface in React:
import React, { useState, useEffect, useRef } from 'react';
import { ConversationManager } from 'ug-js-sdk';
function ChatInterface() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [isConnected, setIsConnected] = useState(false);
const conversationRef = useRef(null);
const messagesEndRef = useRef(null);
useEffect(() => {
// Initialize conversation
const conversation = new ConversationManager({
apiKey: 'your-api-key'
});
conversationRef.current = conversation;
// Set up event listeners
conversation.on('text-event', (event) => {
setMessages(prev => {
const last = prev[prev.length - 1];
if (last && last.role === 'assistant' && !last.complete) {
// Append to existing assistant message
return [
...prev.slice(0, -1),
{
...last,
content: last.content + event.text,
complete: event.done
}
];
} else {
// New assistant message
return [...prev, {
role: 'assistant',
content: event.text,
complete: event.done
}];
}
});
});
// Start conversation
conversation.start().then(() => {
return conversation.setConfiguration({
prompt: 'You are a helpful assistant.'
});
}).then(() => {
setIsConnected(true);
});
// Cleanup
return () => {
conversation.stop();
};
}, []);
// Auto-scroll to bottom
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
const handleSend = async () => {
if (!input.trim() || !isConnected) return;
// Add user message
setMessages(prev => [...prev, {
role: 'user',
content: input,
complete: true
}]);
// Send to API
await conversationRef.current.sendText(input);
// Clear input
setInput('');
};
const handleKeyPress = (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSend();
}
};
return (
<div className="chat-container">
<div className="messages">
{messages.map((msg, i) => (
<div key={i} className={`message ${msg.role}`}>
<strong>{msg.role === 'user' ? 'You' : 'Assistant'}:</strong>
<p>{msg.content}</p>
</div>
))}
<div ref={messagesEndRef} />
</div>
<div className="input-area">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
disabled={!isConnected}
/>
<button onClick={handleSend} disabled={!isConnected}>
Send
</button>
</div>
{!isConnected && <div className="status">Connecting...</div>}
</div>
);
}
export default ChatInterface;
Try It Yourself
Use the Interactive API Tester to:
- Connect with your API key
- Try the "Basic Chat" example scenario
- Experiment with different prompts and messages
Key Takeaways
- Always authenticate before setting configuration
- Configuration must be set before interaction
- Text responses are streamed in chunks
- Use the
donefield to know when a response is complete - Handle errors appropriately