Skip to main content

What are Tools?

Tools are the primary mechanism for extending your AI agents with custom functionality. They allow agents to interact with external systems, perform computations, access databases, make API calls, and execute virtually any operation you can code. In ADK-TS, tools are based on the BaseTool class and follow a standard pattern that makes them:
  • Type-safe - Full TypeScript support with automatic schema generation
  • Provider-agnostic - Work with any LLM provider (OpenAI, Anthropic, Google)
  • Declarative - Define what the tool does, and ADK handles the integration
  • Composable - Combine multiple tools to create powerful agent behaviors

Tool Architecture

Every tool in ADK-TS consists of three core components:
1

Declaration

A JSON Schema that describes the tool’s parameters, allowing the LLM to understand how to call it.
2

Execution

The actual logic that runs when the agent invokes the tool, implemented in the runAsync() method.
3

Context

Access to session state, memory, artifacts, and other runtime information via ToolContext.

Tool Types

ADK-TS provides several approaches to creating and using tools:

Built-in Tools

Pre-built tools for common operations:
  • Default Tools - File operations (Read, Write, Edit, Glob, Grep), web access (WebFetch, WebSearch), bash execution
  • Common Tools - HTTP requests, user interaction, memory management, agent delegation
  • Memory Tools - Write, recall, and manage conversation memory
import { ReadTool, HttpRequestTool, RecallMemoryTool } from '@iqai/adk';

const tools = [
  new ReadTool(),
  new HttpRequestTool(),
  new RecallMemoryTool()
];

Custom Tools with createTool()

The easiest way to create tools with automatic schema generation from Zod:
import { createTool } from '@iqai/adk';
import { z } from 'zod';

const weatherTool = createTool({
  name: 'get_weather',
  description: 'Get current weather for a location',
  schema: z.object({
    location: z.string().describe('City name'),
    units: z.enum(['celsius', 'fahrenheit']).default('celsius')
  }),
  fn: async ({ location, units }) => {
    // Implementation
    return { temperature: 72, conditions: 'sunny' };
  }
});

Function Tools

Wrap existing TypeScript functions automatically:
import { FunctionTool } from '@iqai/adk';

/**
 * Calculate the sum of two numbers
 * @param a First number
 * @param b Second number
 */
function add(a: number, b: number) {
  return { result: a + b };
}

const addTool = new FunctionTool(add);

MCP Tools

Integrate external tools via the Model Context Protocol:
import { McpCoinGecko, McpToolset } from '@iqai/adk';

// Use built-in MCP server
const coinGeckoToolset = McpCoinGecko();
const cryptoTools = await coinGeckoToolset.getTools();

// Custom MCP server
const customToolset = new McpToolset({
  name: 'Custom Server',
  transport: {
    mode: 'stdio',
    command: 'npx',
    args: ['-y', '@my/mcp-server']
  }
});
const customTools = await customToolset.getTools();

Custom BaseTool Classes

Extend BaseTool for complete control:
import { BaseTool, ToolContext, Type } from '@iqai/adk';

class CustomTool extends BaseTool {
  constructor() {
    super({
      name: 'custom_tool',
      description: 'My custom tool',
      isLongRunning: false,
      shouldRetryOnFailure: true,
      maxRetryAttempts: 3
    });
  }

  getDeclaration() {
    return {
      name: this.name,
      description: this.description,
      parameters: {
        type: Type.OBJECT,
        properties: {
          input: { type: Type.STRING, description: 'Input data' }
        },
        required: ['input']
      }
    };
  }

  async runAsync(args: { input: string }, context: ToolContext) {
    // Access session state
    const count = context.state.get('count', 0);
    context.state.set('count', count + 1);
    
    // Implementation
    return { output: `Processed: ${args.input}` };
  }
}

Tool Context

Every tool receives a ToolContext object that provides:
  • State Management - context.state.get() and context.state.set()
  • Memory Access - context.memoryService and context.searchMemory()
  • Session Info - context.session with user ID, app name, session ID
  • Artifact Management - context.listArtifacts() for file attachments
  • Event Actions - context.actions for triggering UI updates
const tool = createTool({
  name: 'save_preference',
  description: 'Save user preferences',
  schema: z.object({
    key: z.string(),
    value: z.string()
  }),
  fn: async ({ key, value }, context) => {
    // Access session state
    context.state.set(key, value);
    
    // Search memory
    const memories = await context.searchMemory(key);
    
    // Get session info
    const userId = context.session.userId;
    
    return { success: true, userId };
  }
});

Using Tools with Agents

Add tools to agents using the withTools() method:
import { AgentBuilder } from '@iqai/adk';

const agent = new AgentBuilder()
  .withName('assistant')
  .withModel('gpt-4')
  .withTools([weatherTool, addTool, customTool])
  .withInstruction('You are a helpful assistant with access to various tools')
  .buildLlm();

const response = await agent.ask('What is the weather in London?');

Error Handling and Retries

Tools support automatic retry logic for transient failures:
const reliableTool = createTool({
  name: 'api_call',
  description: 'Call external API with retry logic',
  shouldRetryOnFailure: true,
  maxRetryAttempts: 3,
  schema: z.object({ endpoint: z.string() }),
  fn: async ({ endpoint }) => {
    // This will retry up to 3 times with exponential backoff
    const response = await fetch(endpoint);
    return await response.json();
  }
});
Tools can also validate arguments against their schema:
class ValidatedTool extends BaseTool {
  validateArguments(args: Record<string, any>): boolean {
    // Custom validation logic
    return super.validateArguments(args);
  }
}

Best Practices

Security: Always validate and sanitize tool inputs. Never execute arbitrary code without proper sandboxing.
  1. Use Descriptive Names - Tool and parameter names should be clear and self-documenting
  2. Provide Rich Descriptions - Help the LLM understand when and how to use the tool
  3. Return Structured Data - Return objects with clear fields rather than plain strings
  4. Handle Errors Gracefully - Return error objects instead of throwing exceptions
  5. Use Zod Descriptions - Add .describe() to schema fields for better LLM understanding
  6. Keep Tools Focused - One tool should do one thing well
  7. Leverage Context - Use session state and memory for stateful operations

Next Steps

Creating Tools

Learn how to create custom tools with createTool() and BaseTool

Built-in Tools

Explore the complete library of built-in tools

Function Tools

Wrap existing functions as tools automatically

MCP Integration

Connect to external MCP servers for expanded capabilities

Build docs developers (and LLMs) love