Tools
Tools extend agent capabilities by allowing them to interact with external systems, perform calculations, manipulate data, and more.
What are Tools?
Tools are functions that agents can call to perform specific tasks. They are defined with:
- A unique name and description
- Input schema validation using Zod
- An execution function that returns results
Built-in Tools
AgentSea includes 10+ powerful built-in tools ready to use:
🧮 Calculator
Perform mathematical calculations with support for basic arithmetic
🌐 HTTP Request
Make HTTP requests to external APIs with retry logic
📁 File Read
Read file contents from the filesystem
✏️ File Write
Write data to files on the filesystem
📋 File List
List files and directories in a path
📊 Text Summary
Extract word count, emails, URLs, and numbers from text
🔤 String Transform
Transform strings (uppercase, lowercase, titlecase, reverse, trim, slug)
📅 Date Time
Get current date/time and format dates
🎨 Figma
Interact with Figma files, nodes, images, and comments via API
⚡ n8n
Execute and manage n8n workflows and webhooks for automation
Using Built-in Tools
Import and register tools with your agent:
import {
Agent,
AnthropicProvider,
ToolRegistry,
calculatorTool,
httpRequestTool,
fileReadTool,
textSummaryTool,
} from '@lov3kaizen/agentsea-core';
import type { Tool, ToolCall, ToolContext } from '@lov3kaizen/agentsea-types';
// Create tool registry
const toolRegistry = new ToolRegistry();
// Register tools
toolRegistry.register(calculatorTool);
toolRegistry.register(httpRequestTool);
toolRegistry.register(fileReadTool);
toolRegistry.register(textSummaryTool);
// Create agent with tools
const agent = new Agent(
{
name: 'tool-agent',
model: 'claude-sonnet-4-20250514',
provider: 'anthropic',
tools: [calculatorTool, httpRequestTool, fileReadTool, textSummaryTool],
},
new AnthropicProvider(),
toolRegistry,
);
// Agent will automatically use tools when needed
const response = await agent.execute(
'Calculate 42 * 58 and fetch weather data from https://api.weather.com',
context,
);Creating Custom Tools
Create your own tools to extend agent capabilities:
import { Tool } from '@lov3kaizen/agentsea-core';
import { z } from 'zod';
// Define tool
export const databaseQueryTool: Tool = {
name: 'database_query',
description: 'Execute SQL queries on the database',
inputSchema: z.object({
query: z.string().describe('SQL query to execute'),
params: z.array(z.any()).optional().describe('Query parameters'),
}),
execute: async (input) => {
const { query, params = [] } = input;
try {
// Your database logic here
const results = await db.query(query, params);
return {
success: true,
data: results,
message: `Query executed successfully. ${results.length} rows returned.`,
};
} catch (error) {
return {
success: false,
error: error.message,
};
}
},
};
// Register with agent
toolRegistry.register(databaseQueryTool);Tool Schema Validation
Tools use Zod schemas for input validation. Here are common patterns:
import { z } from 'zod';
// String with constraints
const nameSchema = z.object({
name: z.string().min(1).max(100).describe('User name'),
});
// Numbers with ranges
const ageSchema = z.object({
age: z.number().int().min(0).max(120).describe('User age'),
});
// Enums
const statusSchema = z.object({
status: z.enum(['active', 'inactive', 'pending']).describe('Status'),
});
// Optional fields
const updateSchema = z.object({
id: z.string().describe('User ID'),
email: z.string().email().optional().describe('New email'),
phone: z.string().optional().describe('New phone number'),
});
// Arrays
const bulkSchema = z.object({
ids: z.array(z.string()).describe('User IDs to process'),
});
// Nested objects
const addressSchema = z.object({
user: z.object({
name: z.string(),
address: z.object({
street: z.string(),
city: z.string(),
zip: z.string(),
}),
}),
});Async Tools
Tools can be async and perform long-running operations:
export const imageGenerationTool: Tool = {
name: 'generate_image',
description: 'Generate an image using DALL-E',
inputSchema: z.object({
prompt: z.string().describe('Image description'),
size: z.enum(['256x256', '512x512', '1024x1024']).default('512x512'),
}),
execute: async (input) => {
const { prompt, size } = input;
// Call image generation API
const response = await fetch('https://api.openai.com/v1/images/generations', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt,
size,
n: 1,
}),
});
const data = await response.json();
return {
success: true,
imageUrl: data.data[0].url,
message: 'Image generated successfully',
};
},
};Error Handling
Always handle errors gracefully in tools:
export const apiCallTool: Tool = {
name: 'api_call',
description: 'Make an API call',
inputSchema: z.object({
endpoint: z.string().url(),
}),
execute: async (input) => {
try {
const response = await fetch(input.endpoint, {
timeout: 5000, // 5 second timeout
});
if (!response.ok) {
return {
success: false,
error: `HTTP error ${response.status}: ${response.statusText}`,
};
}
const data = await response.json();
return {
success: true,
data,
};
} catch (error) {
if (error.name === 'AbortError') {
return {
success: false,
error: 'Request timed out',
};
}
return {
success: false,
error: error.message,
};
}
},
};MCP Tools
Use MCP (Model Context Protocol) to automatically import tools from external servers:
import { MCPRegistry } from '@lov3kaizen/agentsea-core';
// Create MCP registry
const mcpRegistry = new MCPRegistry();
// Connect to MCP servers
await mcpRegistry.addServer({
name: 'filesystem',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/home/user'],
transport: 'stdio',
});
await mcpRegistry.addServer({
name: 'github',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-github'],
transport: 'stdio',
env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN },
});
// Get all MCP tools (automatically converted)
const mcpTools = mcpRegistry.getTools();
// Register with tool registry
toolRegistry.registerMany(mcpTools);
// Agent now has access to filesystem and GitHub tools
const agent = new Agent(
{
name: 'mcp-agent',
model: 'claude-sonnet-4-20250514',
provider: 'anthropic',
tools: mcpTools,
},
provider,
toolRegistry,
);Tool Registry
Manage tools efficiently with the tool registry:
import { ToolRegistry } from '@lov3kaizen/agentsea-core';
const toolRegistry = new ToolRegistry();
// Register single tool
toolRegistry.register(calculatorTool);
// Register multiple tools
toolRegistry.registerMany([
httpRequestTool,
fileReadTool,
textSummaryTool,
]);
// Get tool by name
const calculator = toolRegistry.get('calculator');
// Check if tool exists
const exists = toolRegistry.has('calculator');
// List all tools
const allTools = toolRegistry.list();
// Unregister tool
toolRegistry.unregister('calculator');Isomorphic Tool Management
The isomorphic tool system provides a clean separation between tool definitions and their implementations, allowing you to:
- Define tools with full input/output type safety
- Create server-side implementations for backend operations
- Create client-side implementations for browser operations
- Share tool definitions between environments
Tool Definition
Create a tool definition that can be implemented for different environments:
import { toolDefinition } from '@lov3kaizen/agentsea-core';
import { z } from 'zod';
// Define the tool with input/output schemas
const getUserDef = toolDefinition({
name: 'get_user',
description: 'Get user information from the database',
inputSchema: z.object({
userId: z.string().describe('The user ID to look up'),
}),
outputSchema: z.object({
name: z.string(),
email: z.string().email(),
createdAt: z.string(),
}),
});
// Server implementation - direct database access
const getUserServer = getUserDef.server(async ({ userId }, context) => {
const user = await db.users.findUnique({ where: { id: userId } });
return {
name: user.name,
email: user.email,
createdAt: user.createdAt.toISOString(),
};
});
// Client implementation - fetch from API
const getUserClient = getUserDef.client(async ({ userId }) => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
});
// Use with agent
const agent = new Agent({
tools: [getUserServer.toTool()],
// ...
});Quick Helpers
For simpler cases, use the quick helper functions to create tools in one step:
import { serverTool, clientTool, hybridTool } from '@lov3kaizen/agentsea-core';
import { z } from 'zod';
// Server-only tool
const calculateTool = serverTool({
name: 'calculate',
description: 'Perform arithmetic operations',
inputSchema: z.object({
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
a: z.number(),
b: z.number(),
}),
outputSchema: z.object({ result: z.number() }),
execute: async ({ operation, a, b }) => {
switch (operation) {
case 'add': return { result: a + b };
case 'subtract': return { result: a - b };
case 'multiply': return { result: a * b };
case 'divide': return { result: a / b };
}
},
});
// Client-only tool (runs in browser)
const showNotification = clientTool({
name: 'show_notification',
description: 'Show a browser notification',
inputSchema: z.object({
title: z.string(),
body: z.string(),
}),
outputSchema: z.object({ shown: z.boolean() }),
execute: ({ title, body }) => {
new Notification(title, { body });
return { shown: true };
},
});
// Hybrid tool with both implementations
const userTool = hybridTool({
name: 'get_user',
description: 'Get user information',
inputSchema: z.object({ userId: z.string() }),
outputSchema: z.object({ name: z.string(), email: z.string() }),
server: async ({ userId }) => {
return await db.users.findUnique({ where: { id: userId } });
},
client: async ({ userId }) => {
const res = await fetch(`/api/users/${userId}`);
return res.json();
},
});Built-in Isomorphic Tools
AgentSea includes isomorphic versions of built-in tools with both server and client implementations:
import {
calculatorDef,
calculatorServer,
calculatorClient,
} from '@lov3kaizen/agentsea-core';
// Use the definition to create custom implementations
const customCalc = calculatorDef.server(async ({ operation, a, b }) => {
// Custom server logic with logging
console.log(`Calculating: ${a} ${operation} ${b}`);
// ... implementation
});
// Or use pre-built implementations
const tools = [calculatorServer.toTool()];
// Execute directly
const result = await calculatorServer.execute(
{ operation: 'add', a: 5, b: 3 },
context
);
// { result: 8 }Type Safety
Extract input and output types from tool definitions for full type safety:
import type { ToolInput, ToolOutput } from '@lov3kaizen/agentsea-core';
// Extract types from tool
type CalcInput = ToolInput<typeof calculatorDef>;
// { operation: 'add' | 'subtract' | 'multiply' | 'divide'; a: number; b: number }
type CalcOutput = ToolOutput<typeof calculatorDef>;
// { result: number }
// Use in your code
function runCalculation(input: CalcInput): Promise<CalcOutput> {
return calculatorServer.execute(input, context);
}Converting to Legacy Tools
Convert isomorphic tools to the legacy Tool interface for compatibility:
import { toLegacyTool, toLegacyTools } from '@lov3kaizen/agentsea-core';
// Convert single tool
const legacyCalc = toLegacyTool(calculatorServer);
// Convert multiple tools
const legacyTools = toLegacyTools([
calculatorServer,
getUserServer,
customTool,
]);
// Use with existing code
toolRegistry.registerMany(legacyTools);Best Practices
- Descriptive Names: Use clear, descriptive tool names (e.g.,
database_querynotdb) - Detailed Descriptions: Provide comprehensive descriptions so agents know when to use each tool
- Validation: Always validate inputs with Zod schemas
- Error Handling: Return structured error objects, never throw exceptions
- Timeouts: Set reasonable timeouts for external API calls
- Idempotency: Make tools idempotent when possible
- Side Effects: Document any side effects in the description
- Rate Limiting: Implement rate limiting for expensive operations
- Use Output Schemas: Define output schemas for better type safety and validation
- Environment Separation: Use isomorphic tools to keep server and client logic separate