How to Create and Register Custom Toolkits with an Agent in AISuite

To create and register custom toolkits with an agent in AISuite, define Python functions decorated with @tool and ToolMetadata, bundle them into a toolkit class, and pass the instance to the agent's toolkits parameter during initialization.

AISuite (andrewyng/aisuite) separates toolkits (collections of low-level functions) from agents (the high-level orchestration layer that drives LLM interactions). Understanding how to create and register custom toolkits with an agent allows you to extend the framework with domain-specific capabilities like filesystem operations, mathematical computations, or external API calls.

Understanding the Toolkit Architecture

AISuite implements a clean separation between tools and agents. A toolkit is a plain Python module that exposes callable functions wrapped with the @tool decorator and described by a ToolMetadata object. When you instantiate an agent, you inject functionality by passing toolkit instances via the toolkits argument. The framework then aggregates these tools into a unified namespace available for LLM-driven tool calling.

Creating a Custom Toolkit Module

Project Structure and Required Imports

Create your toolkit as a Python module inside the aisuite/toolkits/ directory. Every custom toolkit depends on utilities from the core framework:

from aisuite.utils.tools import tool, ToolMetadata

All tool functions must reside in files accessible within the AISuite package structure, typically under aisuite/toolkits/, to ensure proper discovery and imports.

Defining Tool Functions with Metadata

Each function you expose must have a stable signature with JSON-serializable arguments. Wrap each function with the @tool decorator and attach a ToolMetadata instance specifying:

  • category – logical grouping (e.g., "filesystem", "math")
  • risk_level"low", "medium", or "high" (used for approval gating)
  • capabilities – a list of verbs describing what the tool performs
  • requires_approval – boolean flag to trigger user-approval flows
  • description – human-readable explanation of the function's purpose
from aisuite.utils.tools import tool, ToolMetadata

@tool
def read_project_file(path: str) -> str:
    """Read contents of a file at the given path."""
    with open(path, 'r') as f:
        return f.read()

# Attach metadata to the decorated function

read_project_file = tool(read_project_file, metadata=ToolMetadata(
    category="filesystem",
    risk_level="low",
    capabilities=["read"],
    description="Read text contents from a file path."
))

Building a Toolkit Class

While optional, wrapping your functions in a class allows you to store configuration state such as root paths, write permissions, or API credentials. The built-in FileToolkit in aisuite/toolkits/files.py demonstrates this pattern by encapsulating filesystem operations with instance-level configuration:

class FileToolkit:
    def __init__(self, root_path: str, allow_write: bool = False):
        self.root_path = root_path
        self.allow_write = allow_write
    
    # Methods decorated with @tool bind to the instance

Registering the Toolkit with an Agent

When constructing an agent (e.g., aisuite.Agent or compatible subclasses), pass your toolkit instance via the toolkits list parameter:

from aisuite.agent import Agent
from aisuite.toolkits.my_toolkit import MyToolkit

my_toolkit = MyToolkit(root="/my/project", allow_write=True)

agent = Agent(
    model="gpt-4o-mini",
    toolkits=[my_toolkit],
)

The agent automatically merges all tools from the supplied toolkits into a single namespace accessible to the LLM via function calling. If any tool has requires_approval=True, AISuite routes those calls through the user-approval flow before execution.

Complete Working Example

Here is a functional MathToolkit implementation that follows AISuite conventions:


# aisuite/toolkits/math_toolkit.py

from aisuite.utils.tools import tool, ToolMetadata

class MathToolkit:
    """A toolkit exposing basic arithmetic operations."""
    
    @tool
    def add(self, a: int, b: int) -> int:
        """Return the sum of a and b."""
        return a + b
    
    @tool
    def multiply(self, a: int, b: int) -> int:
        """Return the product of a and b."""
        return a * b

# Attach metadata after class definition

MathToolkit.add = tool(MathToolkit.add, metadata=ToolMetadata(
    category="math",
    risk_level="low",
    capabilities=["add"],
    description="Add two integers."
))

MathToolkit.multiply = tool(MathToolkit.multiply, metadata=ToolMetadata(
    category="math",
    risk_level="low",
    capabilities=["multiply"],
    description="Multiply two integers."
))

Register this toolkit during agent initialization:

from aisuite.agent import Agent
from aisuite.toolkits.math_toolkit import MathToolkit

math_toolkit = MathToolkit()
agent = Agent(model="gpt-4o-mini", toolkits=[math_toolkit])

# The LLM can now invoke add() and multiply() as tool calls

Key Source Files to Study

Study these reference implementations in the andrewyng/aisuite repository to understand production patterns:

  • aisuite/toolkits/files.py – Reference implementation of a fully-featured filesystem toolkit demonstrating list, read, write, and search operations with configuration state.
  • aisuite/toolkits/shell.py – Example of a command-execution toolkit that wraps subprocess calls with risk-level gating.
  • aisuite/utils/tools.py – Core @tool decorator implementation and ToolMetadata dataclass definitions used by all toolkits.
  • aisuite/agent.py – Agent constructor implementation showing how the toolkits parameter aggregates tool functions for LLM access.

Summary

  • Create a Python module under aisuite/toolkits/ containing your functions.
  • Decorate each callable with @tool and supply ToolMetadata defining category, risk level, and capabilities.
  • Bundle functions into a class when you need to store configuration or state between calls.
  • Register the toolkit by passing an instance to the agent's toolkits parameter; the framework handles discovery and approval routing automatically.

Frequently Asked Questions

What is the difference between the toolkits and tools parameters in AISuite?

The toolkits parameter accepts instances of toolkit classes (like FileToolkit or your custom class), while tools typically accepts individual function references. According to the AISuite source code, toolkits is the preferred pattern for production agents because it bundles configuration, metadata, and multiple related functions into a manageable unit.

How do I restrict tool execution with approval gates?

Set requires_approval=True in your ToolMetadata instance. When the agent attempts to invoke that tool, AISuite automatically pauses execution and routes the request through the user-approval flow defined in the framework. High-risk tools like shell commands in aisuite/toolkits/shell.py use this pattern to prevent accidental destructive operations.

Can I use plain functions without a class wrapper?

Yes. The @tool decorator works on standalone module-level functions. However, using a class wrapper (like FileToolkit) is recommended when your tools need access to instance variables such as root directories, API keys, or permission flags that should persist across multiple tool calls within the same agent session.

Where should I store my custom toolkit files?

Place custom toolkit modules inside the aisuite/toolkits/ directory to ensure they can import from aisuite.utils.tools and follow the package structure. While Python allows importing from other locations, keeping toolkits within the AISuite namespace maintains compatibility with the framework's discovery mechanisms and path expectations used by the agent constructor.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →