Quickstart
End-to-end examples for both session flows, including a 3-primitive stream-mode loop.
Two end-to-end examples: stream mode (deterministic, scripted) and full agent mode (LLM-driven).
Stream mode — the 3-primitive loop
joinRoom → onUserTranscript → assistantSpeak. That’s the whole loop for a scripted deterministic voice experience.
import { joinRoom } from '@juspay/breeze-buddy-client-sdk';
// 1. Your backend provisions a Daily room (with execution_mode: DAILY_STREAM)
// and hands you { roomUrl, token }. Join it:
const session = await joinRoom({ roomUrl, token });
// 2. Listen to what the user says:
session.on('transcript', (entry) => {
if (entry.role === 'user' && entry.isComplete) {
console.log('user said:', entry.text);
// Decide what the assistant should say next…
}
});
// 3. Make the assistant speak — deterministically, bypasses the LLM:
await session.assistantSpeak('Hello! How can I help you today?');
// Later
await session.close(); Why stream mode?
In
'stream' execution mode (wire DAILY_STREAM), the backend pipeline is STT → TTS with no LLM in the middle. session.assistantSpeak(text) sends text directly to TTS — useful for compliance disclosures, IVR prompts, agent handoff, and any case where the assistant must say exactly what you tell it to, unchanged.Full agent mode — LLM-driven conversation
Let the SDK handle lead creation + WebRTC connect, and let the backend’s LLM drive the conversation.
import { BuddyClient } from '@juspay/breeze-buddy-client-sdk';
const client = new BuddyClient({
auth: { token: 'your-jwt-token' },
resellerId: 'my-reseller',
merchantId: 'my-merchant'
});
const session = await client.startSession({
templateId: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
payload: { customer_name: 'John', phone: '555-0100' },
executionMode: 'production', // 'production' | 'test' | 'stream'
on: {
connected: () => showCallUI(),
transcript: (entry) => renderBubble(entry),
disconnected: () => showEndedScreen(),
error: (msg) => showError(msg)
}
}); With await using (ES2024)
Modern engines support await using for automatic resource cleanup:
{
await using session = await joinRoom({ roomUrl, token });
session.on('transcript', (e) => {
if (e.role === 'user') console.log(e.text);
});
await session.assistantSpeak('Hello.');
// session.close() runs automatically when the block exits
} Minimal React shell
import { useEffect, useRef, useState } from 'react';
import { joinRoom, type Session } from '@juspay/breeze-buddy-client-sdk';
function VoiceCall({ roomUrl, token }: { roomUrl: string; token: string }) {
const sessionRef = useRef<Session | null>(null);
const [transcripts, setTranscripts] = useState<string[]>([]);
useEffect(() => {
let cancelled = false;
(async () => {
const session = await joinRoom({ roomUrl, token });
if (cancelled) return void session.close();
sessionRef.current = session;
session.on('transcript', (entry) => {
if (entry.role === 'user' && entry.isComplete) {
setTranscripts((prev) => [...prev, entry.text]);
}
});
})();
return () => {
cancelled = true;
sessionRef.current?.close();
};
}, [roomUrl, token]);
return (
<div>
<button onClick={() => sessionRef.current?.assistantSpeak('Please hold.')}>
Say hold
</button>
{transcripts.map((t, i) => <div key={i}>{t}</div>)}
</div>
);
} Was this helpful?