AxCrew

Creating Custom Functions

Learn how to create and use custom functions with your AxCrew agents

Function Registry

Functions (also known as tools) allow your agents to interact with external systems, process data, or perform specialized tasks. The FunctionRegistry is a central repository where all the functions that agents can use are registered.

Built-in Functions

AxCrew comes with a set of built-in functions that you can use right away:

import { AxCrew, AxCrewFunctions } from '@amitdeshmukh/ax-crew';
 
const crew = new AxCrew(config, AxCrewFunctions);

Creating Custom Functions

To create custom functions, you need to define them according to the AxFunction interface. There are two main approaches:

1. Function-based Approach

You can define a function directly:

import type { AxFunction } from '@ax-llm/ax';
import type { FunctionRegistryType } from '@amitdeshmukh/ax-crew';
 
const googleSearch: AxFunction = {
  name: 'GoogleSearch',
  description: 'Search Google for information',
  parameters: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'The search query' },
      numResults: { type: 'number', description: 'Number of results to return' }
    },
    required: ['query']
  },
  func: async ({ query, numResults = 5 }) => {
    // Implementation for Google search
    const results = await performGoogleSearch(query, numResults);
    return results;
  }
};
 
// Create a function registry
const myFunctions: FunctionRegistryType = {
  GoogleSearch: googleSearch
};
 
// Initialize AxCrew with custom functions
const crew = new AxCrew(config, myFunctions);

2. Class-based Approach with State Sharing

For more complex functions that need to share state with agents, the class-based approach is recommended:

import type { AxFunction } from '@ax-llm/ax';
import type { FunctionRegistryType, StateInstance } from '@amitdeshmukh/ax-crew';
 
class GoogleSearch {
  constructor(private state: StateInstance) {}
  
  toFunction(): AxFunction {
    return {
      name: 'GoogleSearch',
      description: 'Search Google for information',
      parameters: {
        type: 'object',
        properties: {
          query: { type: 'string', description: 'The search query' },
          numResults: { type: 'number', description: 'Number of results' }
        },
        required: ['query']
      },
      func: async ({ query, numResults = 5 }) => {
        // Access shared state
        const location = this.state.get('location');
        
        // Implementation using location from state
        const results = await performGoogleSearch(query, numResults, location);
        
        // Update state with search results
        this.state.set('lastSearchResults', results);
        
        return results;
      }
    };
  }
}
 
// Create a function registry
const myFunctions: FunctionRegistryType = {
  GoogleSearch
};
 
const crew = new AxCrew(config, myFunctions);

In this approach:

  • The function class receives the agent's state in its constructor
  • The toFunction() method returns an AxFunction object
  • The function can access and modify the shared state

Function Parameter Schema

The parameters field follows the JSON Schema format:

parameters: {
  type: 'object',
  properties: {
    param1: { type: 'string', description: 'Description of param1' },
    param2: { type: 'number', description: 'Description of param2' },
    param3: {
      type: 'array',
      items: { type: 'string' },
      description: 'An array of strings'
    }
  },
  required: ['param1']
}

Supported parameter types:

  • string: Text values
  • number: Numeric values
  • boolean: True/false values
  • array: Lists of values
  • object: Nested objects

Example: Creating an API Integration

Here's a complete example of creating a function that integrates with an external API:

import type { AxFunction } from '@ax-llm/ax';
import type { FunctionRegistryType, StateInstance } from '@amitdeshmukh/ax-crew';
 
class WeatherAPI {
  private apiKey: string;
  
  constructor(private state: StateInstance) {
    this.apiKey = process.env.WEATHER_API_KEY || '';
  }
  
  toFunction(): AxFunction {
    return {
      name: 'GetWeather',
      description: 'Get current weather for a location',
      parameters: {
        type: 'object',
        properties: {
          location: { type: 'string', description: 'City name' },
          units: { 
            type: 'string', 
            description: 'Units (metric/imperial)',
            enum: ['metric', 'imperial']
          }
        },
        required: ['location']
      },
      func: async ({ location, units = 'metric' }) => {
        try {
          const response = await fetch(
            `https://api.weatherapi.com/v1/current.json?key=${this.apiKey}&q=${encodeURIComponent(location)}`
          );
          
          const data = await response.json();
          
          // Store results in state
          this.state.set('lastWeatherQuery', {
            location,
            temperature: data.current.temp_c,
            condition: data.current.condition.text
          });
          
          return {
            location: data.location.name,
            temperature: units === 'metric' ? data.current.temp_c : data.current.temp_f,
            condition: data.current.condition.text
          };
        } catch (error) {
          return { error: 'Failed to fetch weather data' };
        }
      }
    };
  }
}
 
export const weatherFunctions: FunctionRegistryType = {
  GetWeather: WeatherAPI
};

Combining Multiple Functions

You can combine multiple function sets using object spread:

import { AxCrew, AxCrewFunctions } from '@amitdeshmukh/ax-crew';
import { weatherFunctions } from './weather-functions';
import { searchFunctions } from './search-functions';
 
// Combine built-in and custom functions
const allFunctions = {
  ...AxCrewFunctions,
  ...weatherFunctions,
  ...searchFunctions
};
 
const crew = new AxCrew(config, allFunctions);

Best Practices

  1. Clear Documentation: Provide detailed descriptions for your functions and parameters
  2. Error Handling: Implement robust error handling in your functions
  3. State Management: Use state to share data between functions and agents
  4. Security: Keep API keys and sensitive data in environment variables
  5. Validation: Validate inputs before processing
  6. Performance: Consider caching results for frequently used queries
  7. Timeout Handling: Implement timeouts for external API calls

On this page