Overview
Create custom tools that agents can use alongside built-in tools.Defining Tools
Copy
import { Agent, defineTool } from '@runtools/sdk';
const myDatabaseTool = defineTool({
name: 'query_database',
description: 'Query the application database',
parameters: {
type: 'object',
properties: {
sql: {
type: 'string',
description: 'SQL query to execute'
},
},
required: ['sql'],
},
execute: async ({ sql }) => {
const result = await myDb.query(sql);
return JSON.stringify(result.rows);
},
});
Using Custom Tools
Copy
const agent = new Agent({
apiKey: process.env.RUNTOOLS_API_KEY,
systemPrompt: 'You help users query their data...',
model: 'claude-opus-4-5',
tools: [
// Built-in tools
'bash',
'read_file',
'edit_file',
// Custom tools
myDatabaseTool,
],
});
const result = await agent.run('Show me all users created this month');
Tool Parameters
Copy
const weatherTool = defineTool({
name: 'get_weather',
description: 'Get current weather for a location',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'City name',
},
units: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'Temperature units',
default: 'celsius',
},
},
required: ['city'],
},
execute: async ({ city, units = 'celsius' }) => {
const weather = await fetchWeather(city, units);
return JSON.stringify(weather);
},
});
Async Tools
Copy
const slowApiTool = defineTool({
name: 'slow_api_call',
description: 'Call a slow external API',
parameters: {
type: 'object',
properties: {
endpoint: { type: 'string' },
},
required: ['endpoint'],
},
execute: async ({ endpoint }) => {
// Async operations are fully supported
const response = await fetch(endpoint);
const data = await response.json();
return JSON.stringify(data);
},
});
Error Handling
Copy
const riskyTool = defineTool({
name: 'risky_operation',
description: 'Perform a risky operation',
parameters: {
type: 'object',
properties: {
input: { type: 'string' },
},
required: ['input'],
},
execute: async ({ input }) => {
try {
const result = await riskyOperation(input);
return JSON.stringify({ success: true, result });
} catch (error) {
// Return error as result (agent will see it)
return JSON.stringify({
success: false,
error: error.message
});
}
},
});
Accessing Context
Copy
const contextAwareTool = defineTool({
name: 'user_lookup',
description: 'Look up information about the current user',
parameters: {
type: 'object',
properties: {},
},
execute: async (params, context) => {
// Access run context
const userId = context.params?.userId;
const user = await getUser(userId);
return JSON.stringify(user);
},
});
Composing Tools
Copy
const sendNotification = defineTool({
name: 'send_notification',
description: 'Send a notification to a user',
parameters: {
type: 'object',
properties: {
userId: { type: 'string' },
message: { type: 'string' },
channel: {
type: 'string',
enum: ['email', 'slack', 'sms']
},
},
required: ['userId', 'message', 'channel'],
},
execute: async ({ userId, message, channel }) => {
switch (channel) {
case 'email':
await sendEmail(userId, message);
break;
case 'slack':
await sendSlack(userId, message);
break;
case 'sms':
await sendSMS(userId, message);
break;
}
return JSON.stringify({ sent: true, channel });
},
});
Publishing Custom Tools
Share tools with your organization:Copy
// Create tool in marketplace (org-private)
const tool = await rt.myTools.create({
slug: 'my-internal-api',
name: 'Internal API Tool',
description: 'Query our internal API',
parameters: { ... },
code: `
export async function execute({ endpoint }) {
const res = await fetch(\`https://internal.mycompany.com\${endpoint}\`);
return await res.json();
}
`,
});
// Now usable by all agents in your org
const agent = new Agent({
tools: ['bash', 'my-internal-api'],
});
Tool Validation
Copy
const validatedTool = defineTool({
name: 'process_order',
description: 'Process a customer order',
parameters: {
type: 'object',
properties: {
orderId: {
type: 'string',
pattern: '^ORD-[0-9]+$',
},
action: {
type: 'string',
enum: ['approve', 'reject', 'hold'],
},
},
required: ['orderId', 'action'],
},
// Validation happens before execute
execute: async ({ orderId, action }) => {
// orderId is guaranteed to match pattern
// action is guaranteed to be one of the enum values
return processOrder(orderId, action);
},
});
Types
Copy
import type {
Tool,
ToolDefinition,
ToolParameters,
ToolContext,
} from '@runtools/sdk';
const tool: ToolDefinition = {
name: 'my_tool',
description: '...',
parameters: { ... },
execute: async (params, context) => { ... },
};