Overview
Routes are the navigable destinations in your app that the voice agent can understand and navigate to. They map natural language to app paths.
Route Structure
A route is defined by the NavaiRoute type:
type NavaiRoute = {
name: string; // Canonical name the agent uses
path: string; // App route path (e.g., "/profile")
description: string; // What this route is for
synonyms: string[]; // Alternative names the agent understands
};
Basic Configuration
Web Apps
Create src/ai/routes.ts:
import type { NavaiRoute } from "@navai/voice-frontend";
export const NAVAI_ROUTE_ITEMS: NavaiRoute[] = [
{
name: "inicio",
path: "/",
description: "Landing page with instructions and status",
synonyms: ["home", "principal", "start"]
},
{
name: "perfil",
path: "/profile",
description: "User profile area",
synonyms: ["profile", "mi perfil", "account"]
},
{
name: "ajustes",
path: "/settings",
description: "Preferences and app settings",
synonyms: ["settings", "configuracion", "configuration", "config"]
},
{
name: "ayuda",
path: "/help",
description: "Help and troubleshooting page",
synonyms: ["help", "soporte", "support"]
}
];
This example is from apps/playground-web/src/ai/routes.ts:1-29 in the NAVAI source.
Mobile Apps
Create src/ai/routes.ts:
import type { NavaiRoute } from "@navai/voice-mobile";
export const NAVAI_ROUTE_ITEMS: NavaiRoute[] = [
{
name: "inicio",
path: "/",
description: "Pantalla principal del playground mobile",
synonyms: ["home", "principal", "start"]
},
{
name: "perfil",
path: "/profile",
description: "Pantalla de perfil",
synonyms: ["profile", "mi perfil", "account"]
},
{
name: "ajustes",
path: "/settings",
description: "Pantalla de configuracion",
synonyms: ["settings", "configuracion", "preferencias", "config"]
},
{
name: "actividad",
path: "/activity",
description: "Pantalla de actividad reciente",
synonyms: ["activity", "historial", "reciente", "activity feed"]
},
{
name: "facturacion",
path: "/billing",
description: "Pantalla de facturacion y pagos",
synonyms: ["billing", "pagos", "suscripcion", "cobros"]
},
{
name: "ayuda",
path: "/help",
description: "Pantalla de ayuda y soporte",
synonyms: ["help", "soporte", "support"]
}
];
Field Guide
name
Required. The canonical name the agent uses internally.
Best practices:
- Use lowercase
- Use the primary language of your app
- Keep it concise (1-2 words)
- Make it unique across all routes
Examples:
"inicio", "perfil", "ajustes"
"home", "profile", "settings"
path
Required. The route path in your app.
Format:
- Must start with
/
- Use standard URL path conventions
- Match your router configuration
Examples:
"/" - Home
"/profile" - Profile
"/settings/account" - Nested route
"/user/:id" - Dynamic route (if supported by your router)
Dynamic paths like /user/:id require additional handling in your navigate function.
description
Required. A clear explanation of what this route is for.
Best practices:
- Be specific and descriptive
- Use natural language
- Mention key features or content
Examples:
"Landing page with instructions and status"
"User profile area"
"Preferences and app settings"
synonyms
Required. Alternative names the agent can match.
Best practices:
- Include translations (if multilingual)
- Include common variations
- Include abbreviations
- Include related terms
Examples:
// Multilingual
synonyms: ["home", "inicio", "principal", "start"]
// Variations
synonyms: ["settings", "configuracion", "configuration", "config", "preferences"]
// Related terms
synonyms: ["help", "ayuda", "soporte", "support", "faq"]
Route Resolution
The navigate_to tool uses resolveNavaiRoute to match natural language to paths:
import { resolveNavaiRoute } from "@navai/voice-frontend";
const routes = NAVAI_ROUTE_ITEMS;
const userInput = "llevame a configuracion";
const path = resolveNavaiRoute(userInput, routes);
// Returns: "/settings"
Matching logic:
- Exact match on
name: User says “ajustes” → matches route with name: "ajustes"
- Exact match on
synonyms: User says “settings” → matches route with synonyms: ["settings"]
- Partial match: User says “configuracion” → matches route with
synonyms: ["configuracion"]
- Fuzzy match: Agent uses natural language understanding to find best match
If multiple routes match equally well, the first one in the array wins. Order routes by priority.
Advanced Patterns
Nested Routes
export const NAVAI_ROUTE_ITEMS: NavaiRoute[] = [
{
name: "settings",
path: "/settings",
description: "Settings hub",
synonyms: ["ajustes", "config"]
},
{
name: "settings account",
path: "/settings/account",
description: "Account settings",
synonyms: ["ajustes de cuenta", "account config"]
},
{
name: "settings privacy",
path: "/settings/privacy",
description: "Privacy settings",
synonyms: ["privacidad", "privacy config"]
}
];
Usage:
- “llevame a ajustes” →
/settings
- “abre ajustes de cuenta” →
/settings/account
- “configuracion de privacidad” →
/settings/privacy
Dynamic Routes
For routes with parameters, you may need custom handling:
export const NAVAI_ROUTE_ITEMS: NavaiRoute[] = [
{
name: "user profile",
path: "/user/:id",
description: "View a user profile",
synonyms: ["perfil de usuario", "ver usuario"]
}
];
Custom navigate function:
const navigate = (input: string) => {
// Handle dynamic routes
if (input.startsWith("/user/")) {
router.navigate(input);
return;
}
// Resolve standard routes
const path = resolveNavaiRoute(input, NAVAI_ROUTE_ITEMS);
if (path) {
router.navigate(path);
}
};
Conditional Routes
Filter routes based on user permissions or state:
const allRoutes: NavaiRoute[] = [
{
name: "admin",
path: "/admin",
description: "Admin panel",
synonyms: ["administracion", "panel de control"]
},
// ... other routes
];
const userRoutes = user.isAdmin
? allRoutes
: allRoutes.filter(route => route.name !== "admin");
const agent = useWebVoiceAgent({
defaultRoutes: userRoutes,
// ...
});
Custom Routes File
By default, NAVAI looks for routes at src/ai/routes.ts. To use a custom path:
Environment Variable
NAVAI_ROUTES_FILE=src/config/voice-routes.ts
Programmatic Configuration
const agent = useWebVoiceAgent({
env: {
NAVAI_ROUTES_FILE: "src/config/voice-routes.ts"
}
});
Integration with Routers
React Router
import { useNavigate } from "react-router-dom";
import { useWebVoiceAgent } from "@navai/voice-frontend";
const navigate = useNavigate();
const agent = useWebVoiceAgent({
navigate, // React Router's navigate function
// ...
});
React Navigation (React Native)
import { useNavigation } from "@react-navigation/native";
const navigation = useNavigation();
const navigate = (path: string) => {
// Map paths to screen names
const screenMap = {
"/": "Home",
"/profile": "Profile",
"/settings": "Settings"
};
const screenName = screenMap[path];
if (screenName) {
navigation.navigate(screenName);
}
};
const agent = useMobileVoiceAgent({
navigate,
// ...
});
Expo Router
import { router } from "expo-router";
const navigate = (path: string) => {
router.push(path);
};
const agent = useMobileVoiceAgent({
navigate,
// ...
});
Multilingual Support
Include translations in synonyms:
export const NAVAI_ROUTE_ITEMS: NavaiRoute[] = [
{
name: "home",
path: "/",
description: "Landing page / Página principal",
synonyms: [
// English
"home", "main", "start", "landing",
// Spanish
"inicio", "principal", "comienzo",
// French
"accueil", "début"
]
}
];
Configure the agent’s language via OPENAI_REALTIME_LANGUAGE in backend .env.
Debugging Route Resolution
Test route resolution manually:
import { resolveNavaiRoute } from "@navai/voice-frontend";
import { NAVAI_ROUTE_ITEMS } from "./ai/routes";
const testInputs = [
"llevame a inicio",
"abre configuracion",
"help",
"perfil de usuario"
];
testInputs.forEach(input => {
const path = resolveNavaiRoute(input, NAVAI_ROUTE_ITEMS);
console.log(`"${input}" → ${path ?? "(no match)"}`);
});
Best Practices
Use descriptive names
Make name and description clear and specific
Include comprehensive synonyms
Add translations, variations, and common misspellings
Order by priority
Put most important/common routes first in the array
Keep paths consistent
Match your router configuration exactly
Test with real voice input
Try various phrasings to ensure good matches
Troubleshooting
Agent navigates to wrong route
Cause: Ambiguous synonyms or overlapping route names
Solution: Make synonyms more specific and unique
Agent says “route not found”
Cause: User input doesn’t match any route
Solution: Add more synonyms or check route configuration
Dynamic routes don’t work
Cause: resolveNavaiRoute can’t handle parameters
Solution: Implement custom logic in your navigate function
Next Steps