1. Clear Documentation

Provide clear documentation for each tool, including:

  • Purpose: What the tool does
  • Parameters: What parameters the tool accepts
  • Return Value: What the tool returns
  • Examples: Examples of how to use the tool

2. Input Validation

Validate all tool inputs to prevent errors and security issues:

function validateToolInput(toolName, args) {
  switch (toolName) {
    case 'get_weather':
      if (!args.location) {
        throw new Error('Location is required for get_weather tool');
      }
      if (args.unit && !['celsius', 'fahrenheit'].includes(args.unit)) {
        throw new Error('Unit must be either "celsius" or "fahrenheit"');
      }
      break;
    case 'search_database':
      if (!args.query) {
        throw new Error('Query is required for search_database tool');
      }
      if (args.limit && (!Number.isInteger(args.limit) || args.limit <= 0)) {
        throw new Error('Limit must be a positive integer');
      }
      break;
    default:
      throw new Error(`Unknown tool: ${toolName}`);
  }
}

3. Error Handling

Return meaningful error messages when tools fail:

async function executeToolCall(toolName, args) {
  try {
    // Validate the tool input
    validateToolInput(toolName, args);
    
    // Execute the tool
    if (toolFunctions[toolName]) {
      return await toolFunctions[toolName](args);
    } else {
      throw new Error(`Tool not implemented: ${toolName}`);
    }
  } catch (error) {
    // Return a structured error response
    return JSON.stringify({
      error: {
        message: error.message,
        type: 'tool_execution_error',
        code: error.code || 'unknown_error'
      }
    });
  }
}

4. Timeouts

Implement timeouts for tool execution to prevent blocking:

async function executeToolWithTimeout(toolName, args, timeout = 5000) {
  return Promise.race([
    executeToolCall(toolName, args),
    new Promise((_, reject) => {
      setTimeout(() => reject(new Error(`Tool execution timed out: ${toolName}`)), timeout);
    })
  ]);
}

5. Statelessness

Design tools to be stateless when possible:

// Avoid this (stateful)
let cachedData = null;

async function getDataTool(args) {
  if (cachedData) {
    return cachedData;
  }
  
  cachedData = await fetchData(args);
  return cachedData;
}

// Prefer this (stateless)
async function getDataTool(args) {
  // Use a cache service that's external to the tool
  const cacheKey = generateCacheKey(args);
  const cachedData = await cacheService.get(cacheKey);
  
  if (cachedData) {
    return cachedData;
  }
  
  const data = await fetchData(args);
  await cacheService.set(cacheKey, data);
  return data;
}

6. Security

Implement appropriate security measures for tool access:

function authorizeToolAccess(user, toolName) {
  // Check if the user has permission to use this tool
  const userPermissions = getUserPermissions(user);
  
  if (!userPermissions.tools.includes(toolName)) {
    throw new Error(`User does not have permission to use tool: ${toolName}`);
  }
}