React SDK

React SDK

Add real-time voice interactions to your React app with hooks or a headless component.

Installation

npm install @itannix/react

Quick Start (Hook)

Use the useVoiceClient hook for full control over the voice client:

App.tsx
import { useState } from 'react';
import { useVoiceClient } from '@itannix/react';

function App() {
  const [messages, setMessages] = useState<{ role: string; text: string }[]>([]);

  const { status, connect, disconnect, sendFunctionResult } = useVoiceClient({
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    onTranscript: (transcript) => {
      setMessages(prev => [...prev, { role: 'user', text: transcript }]);
    },
    onAssistantMessage: (text, done) => {
      if (done) {
        setMessages(prev => [...prev, { role: 'assistant', text }]);
      }
    },
    onError: (error) => console.error('Voice error:', error)
  });

  return (
    <div>
      <p>Status: {status}</p>
      <button onClick={connect} disabled={status !== 'disconnected'}>
        Connect
      </button>
      <button onClick={disconnect} disabled={status === 'disconnected'}>
        Disconnect
      </button>
      {messages.map((msg, i) => (
        <p key={i}><strong>{msg.role}:</strong> {msg.text}</p>
      ))}
    </div>
  );
}

Quick Start (Component)

Alternatively, use the headless VoiceAssistant component with ref-based methods:

App.tsx
import { useRef, useState } from 'react';
import { VoiceAssistant, type VoiceAssistantRef } from '@itannix/react';

function App() {
  const assistantRef = useRef<VoiceAssistantRef>(null);
  const [status, setStatus] = useState('disconnected');
  const [messages, setMessages] = useState<{ role: string; text: string }[]>([]);

  return (
    <div>
      <VoiceAssistant
        ref={assistantRef}
        clientId="your-client-id"
        clientSecret="your-client-secret"
        onStatusChange={setStatus}
        onTranscript={(transcript) => {
          setMessages(prev => [...prev, { role: 'user', text: transcript }]);
        }}
        onAssistantMessage={(text, done) => {
          if (done) {
            setMessages(prev => [...prev, { role: 'assistant', text }]);
          }
        }}
      />

      <p>Status: {status}</p>
      <button 
        onClick={() => assistantRef.current?.connect()} 
        disabled={status !== 'disconnected'}
      >
        Connect
      </button>
      <button 
        onClick={() => assistantRef.current?.disconnect()} 
        disabled={status === 'disconnected'}
      >
        Disconnect
      </button>
      {messages.map((msg, i) => (
        <p key={i}><strong>{msg.role}:</strong> {msg.text}</p>
      ))}
    </div>
  );
}

Hook Options

OptionTypeRequiredDescription
clientIdstringYesYour ItanniX client ID from the dashboard
clientSecretstringYesYour client secret (32+ character random string)
serverUrlstringNoAPI server URL (default: 'https://api.itannix.com')
onTranscript(transcript: string) => voidNoCalled when user speech is transcribed
onAssistantMessage(text: string, done: boolean) => voidNoCalled for assistant responses. done=true indicates final message.
onFunctionCall(name, args, callId) => voidNoCalled when assistant invokes a function
onError(error: Error) => voidNoCalled on connection or runtime errors

Hook Return Values

status: ConnectionStatus

Current connection status: 'disconnected', 'connecting', or 'connected'.

connect(): Promise<void>

Establishes WebRTC connection. Requests microphone permission and starts streaming audio.

disconnect(): void

Closes the connection and stops all audio streams. Safe to call even if not connected.

sendFunctionResult(callId: string, result: object): void

Sends a function call result back to the assistant. Use the callId from onFunctionCall.

Handling Function Calls

When the assistant invokes a function, handle it and return the result:

Function Call Handler
const { sendFunctionResult } = useVoiceClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  onFunctionCall: async (name, args, callId) => {
    if (name === 'get_weather') {
      const weather = await fetchWeather(args.location as string);
      sendFunctionResult(callId, { 
        temperature: weather.temp,
        conditions: weather.conditions
      });
    }
  }
});

TypeScript Support

The SDK is written in TypeScript and exports all types:

import { 
  VoiceAssistant,
  VoiceClient,
  useVoiceClient,
  type ConnectionStatus,
  type FunctionCallEvent,
  type AssistantMessageEvent,
  type VoiceAssistantRef,
  type VoiceAssistantProps,
  type UseVoiceClientOptions,
  type UseVoiceClientReturn
} from '@itannix/react';

Next Steps