Tools are the building blocks that give your Axicov agents their capabilities. Each tool provides specific functionality that your agent can use to accomplish tasks, access data, or interact with external systems.
Tool Structure
Every tool in Axicov follows a consistent structure:
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";
import { Agent, Tools } from "axicov-sdk";
export const myToolRegistry = async (agent: Agent) => {
const tools: any = [];
const schema: Tools = {};
// 1. Define the tool schema
schema.myToolKey = {
name: "myToolName",
description: "What my tool does for the agent",
schema: z.object({
parameter1: z.string().describe("Description of this parameter"),
parameter2: z.number().optional().describe("Optional numeric parameter"),
}),
requiresApproval: false, // Whether this tool requires approval before use
};
// 2. Create the tool instance
const myTool = new DynamicStructuredTool({
name: schema.myToolKey.name,
description: schema.myToolKey.description,
schema: schema.myToolKey.schema,
func: async ({ parameter1, parameter2 }) => {
// 3. Implement the tool's functionality
console.log(`Tool executing with: ${parameter1}, ${parameter2}`);
// 4. Access agent's params or runtimeParams if needed
const userData = agent.params.userData;
agent.runtimeParams.lastToolUsed = "myToolName";
// 5. Return the result
return `Processed ${parameter1} successfully`;
},
});
// Add the tool to the tools array
tools.push(myTool);
// Return both the tools array and schema
return {
tools,
schema,
};
};
Tool Registry System
Axicov uses a registry system to organize and manage tools:
Core Registry vs All Registry
When initializing an agent, you provide two types of registries:
clients: The external platforms on which the agent will operate
allRegistry: Additional tools that you can selectively include
await agent.initialize({
toolNumbers: [0, 2], // Only include tools at index 0 and 2 from allRegistry
clients: [blockchainClients],
allRegistry: [
weatherToolRegistry, // index 0
calculatorToolRegistry, // index 1
webSearchToolRegistry, // index 2
],
});
Tool Selection
The toolNumbers array lets you selectively include tools from the allRegistry by their index. This allows you to create different agent configurations without modifying the registries themselves.
Creating Effective Tools
Best Practices
Clear Descriptions: Write clear, concise descriptions for both tools and parameters
Parameter Validation: Use Zod to validate parameter types and provide helpful error messages
Error Handling: Implement proper error handling within your tool functions
Logging: Include appropriate logging for debugging purposes
Parameter Management: Use agent.params for persistent data and agent.runtimeParams for session data
Parameter Schema with Zod
Zod provides a powerful way to define and validate the parameters for your tools:
schema: z.object({
// Required string parameter
query: z.string().describe("The search query to execute"),
// Optional number parameter with default
limit: z.number().default(10).describe("Maximum number of results"),
// Enum parameter for specific options
sortBy: z.enum(["relevance", "date", "popularity"])
.describe("How to sort the results"),
// Boolean parameter
includeImages: z.boolean().describe("Whether to include images in results"),
// Nested object
filters: z.object({
minDate: z.string().optional().describe("Minimum date (YYYY-MM-DD)"),
maxDate: z.string().optional().describe("Maximum date (YYYY-MM-DD)"),
}).optional().describe("Optional filters to apply")
})
Example (Calculator Tool)
export const calculatorToolRegistry = async (agent: Agent) => {
const tools: any = [];
const schema: Tools = {};
schema.calculator = {
name: "calculate",
description: "Perform mathematical calculations",
schema: z.object({
expression: z.string().describe("The mathematical expression to evaluate"),
}),
requiresApproval: false,
};
const calculatorTool = new DynamicStructuredTool({
name: schema.calculator.name,
description: schema.calculator.description,
schema: schema.calculator.schema,
func: async ({ expression }) => {
try {
// Simple evaluation for demonstration
// In production, use a safe evaluation library
const result = eval(expression);
// Store calculation in runtime parameters
if (!agent.runtimeParams.calculations) {
agent.runtimeParams.calculations = [];
}
agent.runtimeParams.calculations.push({
expression,
result,
timestamp: Date.now()
});
return `Result: ${result}`;
} catch (error) {
return "Invalid expression. Please check your input.";
}
},
});
tools.push(calculatorTool);
return { tools, schema };
};