Function tools allow you to wrap existing TypeScript functions and make them available to agents with minimal boilerplate. ADK-TS automatically generates function declarations from your function signatures and JSDoc comments.
The FunctionTool class wraps any TypeScript function:
import { FunctionTool } from '@iqai/adk';/** * Calculate the sum of two numbers * @param a First number to add * @param b Second number to add */function add(a: number, b: number) { return { result: a + b };}const addTool = new FunctionTool(add);// Use with an agentconst agent = new AgentBuilder() .withTools([addTool]) .buildLlm();
/** * Greet a user by name * @param name The user's name * @param formal Whether to use formal greeting */function greet(name: string, formal: boolean = false) { const greeting = formal ? 'Good day' : 'Hello'; return { message: `${greeting}, ${name}!` };}const greetTool = new FunctionTool(greet);
Async functions are automatically detected and handled:
/** * Fetch user data from an API * @param userId The user's ID */async function fetchUser(userId: string) { const response = await fetch(`https://api.example.com/users/${userId}`); const data = await response.json(); return { user: data };}const fetchUserTool = new FunctionTool(fetchUser);
Functions can access the ToolContext by including it as a parameter:
import type { ToolContext } from '@iqai/adk';/** * Save a user preference * @param key Preference key * @param value Preference value */function savePreference( key: string, value: string, toolContext: ToolContext // Special parameter name) { // Access session state toolContext.state.set(key, value); // Get session info const userId = toolContext.session.userId; return { success: true, userId, saved: { [key]: value } };}const savePrefTool = new FunctionTool(savePreference);
Parameters named toolContext or context are automatically recognized and excluded from the function declaration sent to the LLM.
Function tools extract information from JSDoc comments:
/** * Calculate the area of a rectangle * * This function computes the area by multiplying width and height. * Both parameters must be positive numbers. * * @param width The width of the rectangle in meters * @param height The height of the rectangle in meters * @returns Object containing the calculated area */function calculateArea(width: number, height: number) { if (width <= 0 || height <= 0) { return { error: 'Width and height must be positive' }; } return { area: width * height, unit: 'square meters' };}const areaTool = new FunctionTool(calculateArea);
The JSDoc description becomes the tool description that helps the LLM understand when to use the tool.
Function tools validate mandatory arguments and handle errors:
function divide(a: number, b: number) { if (b === 0) { return { error: 'Cannot divide by zero' }; } return { result: a / b };}const divideTool = new FunctionTool(divide);// If LLM forgets a parameter:// Result: { error: "Invoking 'divide()' failed as the following mandatory input parameters are not present: b" }
/** * Format a date string * @param date Date to format * @param format Output format (default: 'YYYY-MM-DD') * @param timezone Timezone (default: 'UTC') */function formatDate( date: string, format: string = 'YYYY-MM-DD', timezone: string = 'UTC') { // Only 'date' is mandatory // 'format' and 'timezone' are optional return { formatted: date, // Simplified example format, timezone };}const dateTool = new FunctionTool(formatDate);
// Good: Clear, detailed documentation/** * Send an email notification to a user * * This function sends a templated email using the configured email service. * It validates the email address and handles delivery failures gracefully. * * @param recipient Email address of the recipient * @param subject Email subject line * @param template Template name to use (welcome, notification, alert) * @param data Data to populate the template */async function sendEmail( recipient: string, subject: string, template: string, data: Record<string, any>) { /* ... */ }// Avoid: Minimal or missing documentationfunction send(r: string, s: string, t: string, d: any) { /* ... */ }