Agent Tools
Create and manage custom tools for AI agents to extend their capabilities.Tool Interface
Copy
Ask AI
interface AgentTool {
name: string;
description: string;
parameters?: JSONSchema;
execute: (params?: any) => Promise<any> | any;
}
Properties
Unique identifier for the tool
Clear description of what the tool does (used by AI to decide when to use it)
JSON Schema defining the expected parameters
Function that performs the tool’s operation
Built-in Tool Categories
System Tools
Copy
Ask AI
const timeTools = [
{
name: 'getCurrentTime',
description: 'Get the current date and time',
execute: () => new Date().toISOString()
},
{
name: 'formatDate',
description: 'Format a date string in a specific format',
parameters: {
type: 'object',
properties: {
date: { type: 'string', description: 'Date to format (ISO string)' },
format: { type: 'string', description: 'Format pattern', default: 'YYYY-MM-DD' }
},
required: ['date']
},
execute: ({ date, format = 'YYYY-MM-DD' }) => {
const d = new Date(date);
// Implement date formatting logic
return d.toLocaleDateString();
}
},
{
name: 'calculateTimeDifference',
description: 'Calculate the difference between two dates',
parameters: {
type: 'object',
properties: {
startDate: { type: 'string', description: 'Start date (ISO string)' },
endDate: { type: 'string', description: 'End date (ISO string)' },
unit: { type: 'string', enum: ['days', 'hours', 'minutes'], default: 'days' }
},
required: ['startDate', 'endDate']
},
execute: ({ startDate, endDate, unit = 'days' }) => {
const start = new Date(startDate);
const end = new Date(endDate);
const diff = end.getTime() - start.getTime();
switch (unit) {
case 'days': return Math.floor(diff / (1000 * 60 * 60 * 24));
case 'hours': return Math.floor(diff / (1000 * 60 * 60));
case 'minutes': return Math.floor(diff / (1000 * 60));
default: return diff;
}
}
}
];
File System Tools
Copy
Ask AI
const fileTools = [
{
name: 'readFile',
description: 'Read the contents of a file',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: 'File path to read' },
encoding: { type: 'string', description: 'File encoding', default: 'utf8' }
},
required: ['path']
},
execute: async ({ path, encoding = 'utf8' }) => {
const fs = require('fs').promises;
try {
return await fs.readFile(path, encoding);
} catch (error) {
throw new Error(`Failed to read file ${path}: ${error.message}`);
}
}
},
{
name: 'writeFile',
description: 'Write content to a file',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: 'File path to write' },
content: { type: 'string', description: 'Content to write' },
encoding: { type: 'string', description: 'File encoding', default: 'utf8' }
},
required: ['path', 'content']
},
execute: async ({ path, content, encoding = 'utf8' }) => {
const fs = require('fs').promises;
try {
await fs.writeFile(path, content, encoding);
return `Successfully wrote ${content.length} characters to ${path}`;
} catch (error) {
throw new Error(`Failed to write file ${path}: ${error.message}`);
}
}
},
{
name: 'listDirectory',
description: 'List files and directories in a path',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: 'Directory path to list', default: '.' },
includeHidden: { type: 'boolean', description: 'Include hidden files', default: false }
}
},
execute: async ({ path = '.', includeHidden = false }) => {
const fs = require('fs').promises;
try {
const items = await fs.readdir(path, { withFileTypes: true });
return items
.filter(item => includeHidden || !item.name.startsWith('.'))
.map(item => ({
name: item.name,
type: item.isDirectory() ? 'directory' : 'file',
path: `${path}/${item.name}`
}));
} catch (error) {
throw new Error(`Failed to list directory ${path}: ${error.message}`);
}
}
}
];
Web and API Tools
Copy
Ask AI
const httpTools = [
{
name: 'httpRequest',
description: 'Make an HTTP request to an API or website',
parameters: {
type: 'object',
properties: {
url: { type: 'string', description: 'URL to request' },
method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], default: 'GET' },
headers: { type: 'object', description: 'Request headers' },
body: { type: 'string', description: 'Request body (JSON string)' },
timeout: { type: 'number', description: 'Request timeout in ms', default: 10000 }
},
required: ['url']
},
execute: async ({ url, method = 'GET', headers = {}, body, timeout = 10000 }) => {
const fetch = require('node-fetch');
const options = {
method,
headers: {
'Content-Type': 'application/json',
...headers
},
timeout
};
if (body && ['POST', 'PUT', 'PATCH'].includes(method)) {
options.body = typeof body === 'string' ? body : JSON.stringify(body);
}
try {
const response = await fetch(url, options);
const data = await response.json();
return {
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries(response.headers.entries()),
data
};
} catch (error) {
throw new Error(`HTTP request failed: ${error.message}`);
}
}
},
{
name: 'downloadFile',
description: 'Download a file from a URL',
parameters: {
type: 'object',
properties: {
url: { type: 'string', description: 'URL of the file to download' },
outputPath: { type: 'string', description: 'Local path to save the file' }
},
required: ['url', 'outputPath']
},
execute: async ({ url, outputPath }) => {
const fetch = require('node-fetch');
const fs = require('fs');
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const fileStream = fs.createWriteStream(outputPath);
response.body.pipe(fileStream);
return new Promise((resolve, reject) => {
fileStream.on('finish', () => {
resolve(`File downloaded successfully to ${outputPath}`);
});
fileStream.on('error', reject);
});
} catch (error) {
throw new Error(`Download failed: ${error.message}`);
}
}
}
];
Data Processing Tools
Copy
Ask AI
const jsonTools = [
{
name: 'parseJSON',
description: 'Parse a JSON string and extract data',
parameters: {
type: 'object',
properties: {
jsonString: { type: 'string', description: 'JSON string to parse' },
path: { type: 'string', description: 'JSONPath to extract specific data' }
},
required: ['jsonString']
},
execute: ({ jsonString, path }) => {
try {
const data = JSON.parse(jsonString);
if (path) {
// Simple path extraction (implement JSONPath library for complex paths)
const pathParts = path.split('.');
let result = data;
for (const part of pathParts) {
result = result[part];
if (result === undefined) break;
}
return result;
}
return data;
} catch (error) {
throw new Error(`Failed to parse JSON: ${error.message}`);
}
}
},
{
name: 'validateJSON',
description: 'Validate JSON against a schema',
parameters: {
type: 'object',
properties: {
jsonString: { type: 'string', description: 'JSON string to validate' },
schema: { type: 'object', description: 'JSON Schema to validate against' }
},
required: ['jsonString', 'schema']
},
execute: ({ jsonString, schema }) => {
try {
const data = JSON.parse(jsonString);
// Implement JSON schema validation
// This is a simplified version - use ajv library for full validation
return { valid: true, data };
} catch (error) {
return { valid: false, error: error.message };
}
}
}
];
Custom Tool Development
Tool Template
Copy
Ask AI
function createCustomTool(name: string, description: string, implementation: Function) {
return {
name,
description,
parameters: {
type: 'object',
properties: {
// Define your parameters here
},
required: []
},
execute: async (params) => {
try {
return await implementation(params);
} catch (error) {
throw new Error(`Tool ${name} failed: ${error.message}`);
}
}
};
}
// Example usage
const customTool = createCustomTool(
'processUserData',
'Process user data according to business rules',
async ({ userData, rules }) => {
// Implementation here
return processedData;
}
);
Tool Validation
Copy
Ask AI
function validateTool(tool: AgentTool): boolean {
if (!tool.name || typeof tool.name !== 'string') {
throw new Error('Tool must have a valid name');
}
if (!tool.description || typeof tool.description !== 'string') {
throw new Error('Tool must have a description');
}
if (typeof tool.execute !== 'function') {
throw new Error('Tool must have an execute function');
}
// Validate parameters schema if provided
if (tool.parameters) {
// Add JSON Schema validation here
}
return true;
}
Tool Registry
Copy
Ask AI
class ToolRegistry {
private tools = new Map<string, AgentTool>();
register(tool: AgentTool) {
validateTool(tool);
if (this.tools.has(tool.name)) {
throw new Error(`Tool ${tool.name} already registered`);
}
this.tools.set(tool.name, tool);
}
get(name: string): AgentTool | undefined {
return this.tools.get(name);
}
getAll(): AgentTool[] {
return Array.from(this.tools.values());
}
getByCategory(category: string): AgentTool[] {
return this.getAll().filter(tool =>
tool.description.toLowerCase().includes(category.toLowerCase())
);
}
}
// Usage
const registry = new ToolRegistry();
registry.register(timeTools[0]);
registry.register(mathTools[0]);
const agent = new Agent({
name: 'Multi-Tool Agent',
description: 'Agent with registered tools',
tools: registry.getAll(),
chat,
memory
});
Tool Security
Safe Execution
Copy
Ask AI
function createSecureTool(tool: AgentTool): AgentTool {
return {
...tool,
execute: async (params) => {
// Input validation
if (tool.parameters) {
validateParameters(params, tool.parameters);
}
// Rate limiting
await checkRateLimit(tool.name);
// Execution with timeout
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Tool execution timeout')), 30000);
});
try {
const result = await Promise.race([
tool.execute(params),
timeoutPromise
]);
// Log execution
console.log(`Tool ${tool.name} executed successfully`);
return result;
} catch (error) {
console.error(`Tool ${tool.name} failed:`, error.message);
throw error;
}
}
};
}
Parameter Sanitization
Copy
Ask AI
function sanitizeParameters(params: any, schema: any): any {
// Implement parameter sanitization based on schema
const sanitized = { ...params };
// Remove dangerous properties
delete sanitized.__proto__;
delete sanitized.constructor;
// Type coercion and validation
if (schema.properties) {
for (const [key, propSchema] of Object.entries(schema.properties)) {
if (sanitized[key] !== undefined) {
sanitized[key] = coerceType(sanitized[key], propSchema.type);
}
}
}
return sanitized;
}
Best Practices
Tool Design
- Single Responsibility: Each tool should have one clear purpose
- Clear Descriptions: Write descriptions that help the AI understand when to use the tool
- Proper Parameters: Use JSON Schema to define clear parameter requirements
- Error Handling: Implement comprehensive error handling
- Async Support: Use async/await for I/O operations
Performance
- Caching: Cache expensive operations when possible
- Timeouts: Set appropriate timeouts for long-running operations
- Resource Management: Clean up resources properly
- Batch Operations: Support batch processing when applicable
Security
- Input Validation: Always validate and sanitize inputs
- Rate Limiting: Implement rate limiting for resource-intensive tools
- Access Control: Restrict access to sensitive operations
- Audit Logging: Log tool usage for security monitoring