Tools allow LLMs to execute functions and interact with external systems.
interface Tool {
name: string;
description: string;
parameters: Record<string, any>; // JSON Schema
handler: (args: Record<string, any>, context?: any) => Promise<any>;
}const weatherTool = {
name: 'get_weather',
description: 'Get weather information for a location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name (e.g., "San Francisco")',
},
units: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'Temperature units',
},
},
required: ['location'],
},
handler: async (args) => {
const { location, units = 'celsius' } = args;
// Fetch weather data
const data = await fetchWeather(location);
return {
temperature: data.temp,
condition: data.condition,
units,
};
},
};import { createServer } from '@hari7261/ainative-server-node';
const server = createServer(config);
server.registerTool(weatherTool);from ainative import Tool
async def weather_handler(args, context=None):
location = args["location"]
# Fetch weather
return {"temperature": 72, "condition": "Sunny"}
tool = Tool(
name="get_weather",
description="Get weather for a location",
parameters={
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
},
handler=weather_handler
)
server.register_tool(tool)// Call tool directly
const result = await fetch('http://localhost:3001/ai/tool', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
tool: 'get_weather',
args: { location: 'San Francisco' },
context: {},
}),
});
const data = await result.json();
console.log(data.result);Tools can be automatically called by the LLM:
// The LLM decides when to call tools
await app.sendMessage('What is the weather in Paris?');
// Behind the scenes:
// 1. LLM receives message and available tools
// 2. LLM decides to call get_weather tool
// 3. Tool is executed server-side
// 4. Result is sent back to LLM
// 5. LLM generates response using tool result{
name: 'get_time',
description: 'Get the current time',
parameters: {
type: 'object',
properties: {
timezone: { type: 'string' }
}
}
}{
name: 'calculate',
description: 'Perform a mathematical calculation',
parameters: {
type: 'object',
properties: {
expression: { type: 'string' }
},
required: ['expression']
}
}Access request context in handlers:
{
name: 'get_user_data',
handler: async (args, context) => {
const userId = context.userId;
return await db.users.find(userId);
}
}Tools can be long-running:
{
name: 'generate_image',
handler: async (args) => {
const imageUrl = await generateImage(args.prompt);
return { url: imageUrl };
}
}{
name: 'risky_operation',
handler: async (args) => {
try {
return await performOperation(args);
} catch (error) {
throw new Error(`Operation failed: ${error.message}`);
}
}
}// Client
const response = await fetch('http://localhost:3001/ai/tools');
const { tools } = await response.json();
console.log(tools);// Register tools at runtime
if (user.hasPermission('admin')) {
server.registerTool(adminTool);
}// Node.js
toolRegistry.unregister('tool_name');
# Python
server.tool_registry.unregister('tool_name')Always validate tool arguments:
{
handler: async (args) => {
if (!args.location || typeof args.location !== 'string') {
throw new Error('Invalid location');
}
// Sanitize
const location = args.location.trim();
return await fetchWeather(location);
}
}Check permissions before execution:
{
handler: async (args, context) => {
if (!context.user.hasPermission('weather:read')) {
throw new Error('Unauthorized');
}
return await fetchWeather(args.location);
}
}Implement rate limiting for expensive tools:
const rateLimiter = new Map();
{
handler: async (args, context) => {
const key = context.userId;
const now = Date.now();
const lastCall = rateLimiter.get(key) || 0;
if (now - lastCall < 1000) {
throw new Error('Rate limit exceeded');
}
rateLimiter.set(key, now);
return await expensiveOperation(args);
}
}import { ToolRegistry } from '@hari7261/ainative-server-node';
import { test } from 'vitest';
test('weather tool works', async () => {
const registry = new ToolRegistry();
registry.register(weatherTool);
const result = await registry.execute({
tool: 'get_weather',
args: { location: 'San Francisco' },
});
expect(result.success).toBe(true);
expect(result.result).toHaveProperty('temperature');
});