Skip to main content

Overview

The buildNavaiAgent function creates a fully configured RealtimeAgent instance with navigation tools, function execution capabilities, and backend integration. It processes frontend and backend function definitions, generates appropriate tools, and compiles agent instructions.

Import

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

Signature

async function buildNavaiAgent(
  options: BuildNavaiAgentOptions
): Promise<BuildNavaiAgentResult>

Parameters

options
BuildNavaiAgentOptions
required
Configuration for building the agent.

Return Value

result
BuildNavaiAgentResult
Result object containing the agent and any warnings.

Agent Tools

The built agent includes the following tools:

Built-in Tools

  1. navigate_to - Navigate to allowed routes
  2. execute_app_function - Execute any registered frontend or backend function

Direct Function Tools

For each valid function, a direct alias tool is created (e.g., get_user_profile) that internally calls execute_app_function. Functions are excluded from direct tools if:
  • Name conflicts with reserved tools (navigate_to, execute_app_function)
  • Name contains invalid characters (must match /^[a-zA-Z0-9_-]{1,64}$/)

Function Execution

Frontend Functions

Frontend functions are loaded from module loaders and executed directly in the browser.
// Frontend function execution
const result = await frontendFunction.run(payload, { navigate });

Backend Functions

Backend functions are executed via HTTP request to the backend API.
// Backend function execution
const result = await executeBackendFunction({
  functionName: 'search_documents',
  payload: { query: 'invoice' }
});

Example Usage

import { buildNavaiAgent } from '@navai/voice-frontend';
import { RealtimeSession } from '@openai/agents/realtime';

// Build the agent
const { agent, warnings } = await buildNavaiAgent({
  navigate: (path) => router.push(path),
  routes: [
    {
      name: 'home',
      path: '/',
      description: 'Home page'
    },
    {
      name: 'profile',
      path: '/profile',
      description: 'User profile',
      synonyms: ['account', 'perfil']
    }
  ],
  functionModuleLoaders: {
    './functions/getUser.ts': () => import('./functions/getUser'),
    './functions/updateSettings.ts': () => import('./functions/updateSettings')
  },
  backendFunctions: [
    {
      name: 'search_database',
      description: 'Search the application database',
      source: 'backend'
    }
  ],
  executeBackendFunction: backendClient.executeFunction,
  agentName: 'My App Assistant',
  baseInstructions: 'You are a helpful assistant for managing user tasks.'
});

// Log any warnings
if (warnings.length > 0) {
  console.warn('Agent build warnings:', warnings);
}

// Create and connect session
const session = new RealtimeSession(agent);
await session.connect({ apiKey: ephemeralKey });

Agent Instructions

The agent receives generated instructions that include:
  1. Base instructions (customizable)
  2. List of allowed routes with descriptions and synonyms
  3. List of allowed functions with descriptions
  4. Execution rules:
    • Use navigate_to for navigation requests
    • Use execute_app_function or direct tools for function calls
    • Always include payload (use null when no arguments needed)
    • Use payload.args for function arguments
    • Use payload.constructorArgs and payload.methodArgs for class methods
    • Never invent routes or functions not in the list
    • Ask clarifying questions when unclear

Payload Structure

Functions receive payloads with specific structures:

Simple Function Call

{
  function_name: 'get_user_profile',
  payload: {
    args: [userId]  // Arguments array
  }
}

Class Method Call

{
  function_name: 'user_service_get_profile',
  payload: {
    constructorArgs: [apiClient],  // Constructor arguments
    methodArgs: [userId]            // Method arguments
  }
}

Object with Value

{
  function_name: 'process_data',
  payload: {
    value: data
  }
}

Conflict Resolution

Name Conflicts

  1. Frontend vs Backend: Frontend functions take precedence; backend functions with conflicting names are ignored with a warning
  2. Duplicate Names: Second occurrence is renamed with numeric suffix (e.g., get_user_2)
  3. Reserved Names: Functions named navigate_to or execute_app_function are only accessible via execute_app_function
  4. Invalid Names: Functions with invalid characters are only accessible via execute_app_function

Source Reference

Defined in: packages/voice-frontend/src/agent.ts:47

Build docs developers (and LLMs) love