Skip to main content

useWebVoiceAgent Hook

The useWebVoiceAgent hook is the primary interface for integrating voice navigation into React web applications. It manages the OpenAI Realtime session lifecycle and provides connection state management.

Import

import { useWebVoiceAgent } from '@navai/voice-frontend';

Type Signature

type UseWebVoiceAgentOptions = {
  navigate: (path: string) => void;
  moduleLoaders: NavaiFunctionModuleLoaders;
  defaultRoutes: NavaiRoute[];
  env?: Record<string, string | undefined>;
  apiBaseUrl?: string;
  routesFile?: string;
  functionsFolders?: string;
  modelOverride?: string;
  defaultRoutesFile?: string;
  defaultFunctionsFolder?: string;
};

type UseWebVoiceAgentResult = {
  status: "idle" | "connecting" | "connected" | "error";
  error: string | null;
  isConnecting: boolean;
  isConnected: boolean;
  start: () => Promise<void>;
  stop: () => void;
};

function useWebVoiceAgent(options: UseWebVoiceAgentOptions): UseWebVoiceAgentResult;

Basic Usage

import { useWebVoiceAgent } from '@navai/voice-frontend';
import { useNavigate } from 'react-router-dom';

const ROUTES = [
  { name: 'home', path: '/', description: 'Home page' },
  { name: 'settings', path: '/settings', description: 'Settings page' }
];

function VoiceControl() {
  const navigate = useNavigate();
  const { start, stop, isConnected, isConnecting, error } = useWebVoiceAgent({
    navigate,
    defaultRoutes: ROUTES,
    moduleLoaders: {}
  });

  return (
    <div>
      <button onClick={start} disabled={isConnecting || isConnected}>
        Start Voice
      </button>
      <button onClick={stop} disabled={!isConnected}>
        Stop Voice
      </button>
      {isConnecting && <p>Connecting...</p>}
      {error && <p>Error: {error}</p>}
    </div>
  );
}

Options

Required Options

navigate
(path: string) => void
required
Navigation function from your router (e.g., React Router’s useNavigate()). Called when the agent resolves a voice navigation command.
moduleLoaders
NavaiFunctionModuleLoaders
required
Object mapping module paths to dynamic import functions. Used to load frontend functions.
const moduleLoaders = {
  'src/ai/functions/greet.ts': () => import('./ai/functions/greet')
};
defaultRoutes
NavaiRoute[]
required
Array of route definitions that the voice agent can navigate to.
const routes = [
  {
    name: 'profile',
    path: '/profile',
    description: 'User profile page',
    synonyms: ['perfil', 'account']
  }
];

Optional Options

env
Record<string, string | undefined>
Environment variables object. Useful for passing runtime configuration.
env: {
  NAVAI_API_URL: 'https://api.example.com',
  NAVAI_ROUTES_FILE: 'src/custom-routes.ts'
}
apiBaseUrl
string
default:"http://localhost:3000"
Base URL for the NAVAI backend API. Overrides NAVAI_API_URL from env.
routesFile
string
default:"src/ai/routes.ts"
Path to custom routes module. Resolved at runtime if found in moduleLoaders.
functionsFolders
string
default:"src/ai/functions-modules"
Comma-separated paths or globs for function modules. Supports wildcards:
  • src/ai/functions-modules - exact folder
  • src/ai/functions-modules/... - recursive
  • src/*/functions - glob pattern
modelOverride
string
Override the OpenAI Realtime model. Can also be set via NAVAI_REALTIME_MODEL env var.
modelOverride: 'gpt-4o-realtime-preview-2024-12-17'
defaultRoutesFile
string
default:"src/ai/routes.ts"
Default path used for route file resolution.
defaultFunctionsFolder
string
default:"src/ai/functions-modules"
Default path used for function discovery.

Return Values

status
'idle' | 'connecting' | 'connected' | 'error'
Current connection state of the voice agent.
error
string | null
Error message if status is ‘error’, otherwise null.
isConnecting
boolean
Convenience boolean: status === 'connecting'
isConnected
boolean
Convenience boolean: status === 'connected'
start
() => Promise<void>
Async function to start the voice session. Performs the following:
  1. Resolves runtime configuration (routes, functions)
  2. Requests client secret from backend API
  3. Lists backend functions
  4. Builds the RealtimeAgent with tools
  5. Connects to OpenAI Realtime API
Sets status to ‘error’ and populates error message on failure.
stop
() => void
Synchronously closes the voice session and resets status to ‘idle’.

Connection Lifecycle

1

Idle State

Initial state. Call start() to begin connection.
2

Connecting State

The hook:
  • Resolves runtime config (routes, functions)
  • Fetches client secret from backend
  • Lists available backend functions
  • Builds RealtimeAgent with navigation and function tools
  • Connects to OpenAI Realtime API
3

Connected State

Voice agent is active and listening. User can speak navigation commands and function calls.
4

Error State

Connection failed. Check the error field for details. Call start() to retry.
5

Stopped

Call stop() to close the session and return to idle state.

Complete Example

import { useWebVoiceAgent } from '@navai/voice-frontend';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';

// Define routes
const APP_ROUTES = [
  {
    name: 'home',
    path: '/',
    description: 'Home page',
    synonyms: ['inicio', 'main']
  },
  {
    name: 'dashboard',
    path: '/dashboard',
    description: 'Analytics dashboard'
  },
  {
    name: 'settings',
    path: '/settings',
    description: 'User settings',
    synonyms: ['preferences', 'config']
  }
];

// Module loaders for functions
const moduleLoaders = {
  'src/ai/functions/greet.ts': () => import('./ai/functions/greet'),
  'src/ai/functions/search.ts': () => import('./ai/functions/search')
};

function VoiceNavigationButton() {
  const navigate = useNavigate();
  const [showDebug, setShowDebug] = useState(false);
  
  const {
    start,
    stop,
    status,
    isConnecting,
    isConnected,
    error
  } = useWebVoiceAgent({
    navigate,
    defaultRoutes: APP_ROUTES,
    moduleLoaders,
    apiBaseUrl: process.env.REACT_APP_NAVAI_API_URL,
    env: {
      NAVAI_REALTIME_MODEL: process.env.REACT_APP_REALTIME_MODEL
    }
  });

  const handleToggle = () => {
    if (isConnected) {
      stop();
    } else {
      start();
    }
  };

  return (
    <div className="voice-control">
      <button
        onClick={handleToggle}
        disabled={isConnecting}
        className={isConnected ? 'active' : ''}
      >
        {isConnecting && 'Connecting...'}
        {isConnected && '🎤 Listening'}
        {status === 'idle' && '🎤 Start Voice'}
        {status === 'error' && '⚠️ Retry'}
      </button>
      
      <button onClick={() => setShowDebug(!showDebug)}>
        Debug
      </button>
      
      {showDebug && (
        <div className="debug-panel">
          <p>Status: {status}</p>
          {error && <p className="error">Error: {error}</p>}
        </div>
      )}
    </div>
  );
}

export default VoiceNavigationButton;

Error Handling

The hook handles errors during connection and returns them in the error field:
const { start, error, status } = useWebVoiceAgent(options);

useEffect(() => {
  if (status === 'error') {
    console.error('Voice agent error:', error);
    // Optionally retry after delay
    setTimeout(() => start(), 5000);
  }
}, [status, error, start]);

Cleanup

The hook automatically cleans up on unmount:
// Internal implementation (for reference)
useEffect(() => {
  return () => {
    stop(); // Closes session on component unmount
  };
}, [stop]);

Warnings

The hook emits warnings to the console for configuration issues:
  • Route file not found (falls back to defaultRoutes)
  • Function folder doesn’t match any modules
  • Backend function name conflicts
  • Invalid function names
  • Function loading errors
Warnings are informational and don’t prevent the agent from working. Check the console during development to ensure your configuration is correct.

Build docs developers (and LLMs) love