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
Every tool in ADK-TS consists of three core components:
Declaration
A JSON Schema that describes the tool’s parameters, allowing the LLM to understand how to call it.
Execution
The actual logic that runs when the agent invokes the tool, implemented in the runAsync() method.
Context
Access to session state, memory, artifacts, and other runtime information via ToolContext.
ADK-TS provides several approaches to creating and using 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 ()
];
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' };
}
});
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 );
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 ();
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 };
}
});
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.
Use Descriptive Names - Tool and parameter names should be clear and self-documenting
Provide Rich Descriptions - Help the LLM understand when and how to use the tool
Return Structured Data - Return objects with clear fields rather than plain strings
Handle Errors Gracefully - Return error objects instead of throwing exceptions
Use Zod Descriptions - Add .describe() to schema fields for better LLM understanding
Keep Tools Focused - One tool should do one thing well
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