Overview
Function runtime APIs handle discovery, loading, and execution of backend tools. Functions are discovered by scanning configured folders, then transformed into normalized tool definitions that can be executed safely.
loadNavaiFunctions
Function Signature
async function loadNavaiFunctions (
functionModuleLoaders : NavaiFunctionModuleLoaders
) : Promise < NavaiFunctionsRegistry >
Source: packages/voice-backend/src/functions.ts:278
Description
Imports modules from the provided loaders, extracts all callable exports, and transforms them into normalized function definitions. Handles functions, classes, and objects with callable members. Returns a registry with name-indexed and ordered function definitions plus any warnings.
Parameters
functionModuleLoaders
NavaiFunctionModuleLoaders
required
Record mapping file paths to async module loader functions Type Definition: type NavaiFunctionModuleLoaders = Record < string , () => Promise < unknown >>
Example: {
"src/ai/functions-modules/weather.ts" : () => import ( "./weather.ts" ),
"src/ai/functions-modules/calendar.ts" : () => import ( "./calendar.ts" )
}
Return Value
NavaiFunctionsRegistry
Promise<NavaiFunctionsRegistry>
byName
Map<string, NavaiFunctionDefinition>
required
Map of function names to definitions for O(1) lookup
ordered
NavaiFunctionDefinition[]
required
Array of all function definitions in discovery order
Array of warning messages from loading process
The loader transforms different export types:
1. Exported Function
// src/ai/functions-modules/weather.ts
export default function getWeather ( location : string ) {
return { temp: 72 , location };
}
Result: One tool named get_weather
2. Exported Class
// src/ai/functions-modules/calendar.ts
export class Calendar {
getEvents () { return []; }
createEvent ( title : string ) { return { title }; }
}
Result: Two tools:
calendar_get_events
calendar_create_event
3. Exported Object
// src/ai/functions-modules/utils.ts
export const tools = {
add : ( a : number , b : number ) => a + b ,
multiply : ( a : number , b : number ) => a * b
};
Result: Two tools:
Name Normalization
Function names are normalized to snake_case:
Convert camelCase to snake_case: getWeather → get_weather
Remove unsafe characters
Lowercase all letters
On collision, append suffix: get_weather_2, get_weather_3
A warning is emitted whenever a rename occurs due to collision.
Argument Resolution
When executing a function, arguments are resolved in this order:
if ( payload . args || payload . arguments ) {
args = payload . args || payload . arguments
} else if ( payload . value ) {
args = [ payload . value ]
} else if ( Object . keys ( payload ). length > 0 ) {
args = [ payload ]
}
// If function expects one more arg than provided, append context
if ( callable . length > args . length ) {
args . push ( context )
}
Usage Example
import { loadNavaiFunctions } from "@navai/voice-backend" ;
import { pathToFileURL } from "node:url" ;
const loaders = {
"src/ai/functions-modules/weather.ts" : () =>
import ( pathToFileURL ( "/abs/path/to/weather.ts" ). href )
};
const registry = await loadNavaiFunctions ( loaders );
console . log ( registry . ordered . length ); // 1
console . log ( registry . byName . get ( "get_weather" ));
// {
// name: "get_weather",
// description: "Call exported function default.",
// source: "src/ai/functions-modules/weather.ts#default",
// run: async (payload, context) => { ... }
// }
const result = await registry . byName . get ( "get_weather" ) ! . run (
{ args: [ "San Francisco" ] },
{ req: {} }
);
console . log ( result ); // { temp: 72, location: "San Francisco" }
resolveNavaiBackendRuntimeConfig
Function Signature
async function resolveNavaiBackendRuntimeConfig (
options ?: ResolveNavaiBackendRuntimeConfigOptions
) : Promise < ResolveNavaiBackendRuntimeConfigResult >
Source: packages/voice-backend/src/runtime.ts:35
Description
Scans the filesystem for function modules based on configured patterns and returns module loaders ready for loadNavaiFunctions. Handles environment variables, glob patterns, and fallback logic.
Parameters
options
ResolveNavaiBackendRuntimeConfigOptions
Runtime configuration options env
Record<string, string | undefined>
default: "process.env"
Environment variables object
Comma-separated list of folders/patterns. Overrides NAVAI_FUNCTIONS_FOLDERS env var
defaultFunctionsFolder
string
default: "src/ai/functions-modules"
Fallback folder if no matches found
baseDir
string
default: "process.cwd()"
Base directory for scanning. Can be overridden by NAVAI_FUNCTIONS_BASE_DIR env var
File extensions to include
Glob patterns to exclude from scan. Files ending in .d.ts are always excluded
Return Value
ResolveNavaiBackendRuntimeConfigResult
Promise<ResolveNavaiBackendRuntimeConfigResult>
functionModuleLoaders
NavaiFunctionModuleLoaders
required
Record of file paths to module loader functions
Array of warning messages from scanning process
Pattern Matching
Supported pattern formats:
Pattern Behavior Example folderMatch all files in folder src/ai/functions-modulesfolder/...Match all files recursively src/ai/functions-modules/...glob/**/patternMatch using wildcards src/features/*/toolspath/to/file.tsMatch specific file src/ai/functions-modules/secret.tspattern1,...Match multiple patterns src/ai/functions-modules,src/tools
Fallback Logic
if ( configured patterns match nothing && patterns were configured ) {
warnings . push ( `NAVAI_FUNCTIONS_FOLDERS did not match any module...` )
// Fall back to defaultFunctionsFolder
}
Path Normalization
All paths are normalized:
Backslashes converted to forward slashes
Leading slashes and ./ removed
If path doesn’t start with src/, it’s prefixed automatically
Usage Example
import { resolveNavaiBackendRuntimeConfig } from "@navai/voice-backend" ;
const config = await resolveNavaiBackendRuntimeConfig ({
baseDir: process . cwd (),
functionsFolders: "src/ai/functions-modules,..." ,
includeExtensions: [ "ts" , "js" ],
exclude: [ "**/node_modules/**" , "**/*.test.ts" ]
});
console . log ( Object . keys ( config . functionModuleLoaders ));
// [
// "src/ai/functions-modules/weather.ts",
// "src/ai/functions-modules/calendar.ts"
// ]
console . log ( config . warnings );
// []
Function Execution Context
When functions are executed via POST /navai/functions/execute, they receive:
payload
NavaiFunctionPayload
required
Function arguments and metadata Type Definition: type NavaiFunctionPayload = Record < string , unknown >
Common Properties:
args or arguments: Array of arguments
value: Single value argument
constructorArgs: For class constructors
methodArgs: For class methods
Any other properties passed as first argument
context
NavaiFunctionContext
required
Execution context including Express request Type Definition: type NavaiFunctionContext = Record < string , unknown >
Properties:
req: Express Request object from the execution endpoint
Example Function with Context
// src/ai/functions-modules/auth.ts
export function getCurrentUser ( context : { req : Request }) {
const userId = context . req . headers [ 'x-user-id' ];
return { userId };
}
Execution:
POST /navai/functions/execute
{
"function_name" : "get_current_user" ,
"payload" : {}
}
The function receives context.req from the Express request.
Warnings
The runtime emits warnings for:
Warning Cause Ignored {path}: module has no exports.Empty module Ignored {path}: module has no callable exports.No functions/classes Ignored {path}#{export}: class has no callable instance methods.Empty class Ignored {path}#{export}: exported object has no callable members.Object with no functions Renamed duplicated function "{old}" to "{new}".Name collision Failed to load {path}: {error}Import/syntax error NAVAI_FUNCTIONS_FOLDERS did not match any module...No pattern matches
Warnings do not stop execution. They are returned in the registry and route responses for debugging.
Complete Example
import {
resolveNavaiBackendRuntimeConfig ,
loadNavaiFunctions
} from "@navai/voice-backend" ;
// Step 1: Resolve runtime config
const runtimeConfig = await resolveNavaiBackendRuntimeConfig ({
env: process . env ,
baseDir: process . cwd (),
functionsFolders: "src/ai/functions-modules"
});
if ( runtimeConfig . warnings . length > 0 ) {
console . warn ( "Runtime warnings:" , runtimeConfig . warnings );
}
// Step 2: Load functions
const registry = await loadNavaiFunctions (
runtimeConfig . functionModuleLoaders
);
if ( registry . warnings . length > 0 ) {
console . warn ( "Registry warnings:" , registry . warnings );
}
console . log ( `Loaded ${ registry . ordered . length } functions:` );
for ( const fn of registry . ordered ) {
console . log ( `- ${ fn . name } : ${ fn . description } ` );
}
// Step 3: Execute a function
const weatherFn = registry . byName . get ( "get_weather" );
if ( weatherFn ) {
const result = await weatherFn . run (
{ args: [ "San Francisco" ] },
{ req: {} }
);
console . log ( "Weather result:" , result );
}