Skip to content

Creating a Custom Tool Repository for AgentLabUI

Trevor Grant edited this page Jun 2, 2025 · 1 revision

This guide explains how to create your own Git repository containing custom tools based on the Gofannon framework, which can then be loaded and used within AgentLabUI.

Introduction

AgentLabUI allows you to extend its functionality by loading custom tools from external Git repositories. These tools must be built using the Gofannon BaseTool structure. By providing a tool_manifest.json file in your repository, AgentLabUI can discover, display, and integrate your custom tools into the agent creation process.

Prerequisites

Before you start, ensure you have:

  • A Python environment (Python 3.8+ recommended).
  • Git installed on your system.
  • Basic understanding of Python classes and modules.
  • Familiarity with the Gofannon BaseTool concept is helpful. A Gofannon tool typically has a definition property (describing the tool for LLMs) and an fn method (the actual Python code to execute).
  • A Git hosting account (e.g., GitHub, GitLab) where you can host your public tool repository.

Steps to Create Your Custom Tool Repository

Step 1: Initialize Your Git Repository

  1. Create a new directory for your tool repository:
    mkdir my-gofannon-tools  
    cd my-gofannon-tools  
  2. Initialize it as a Git repository:
    git init  
  3. (Optional) Create a .gitignore file to exclude common Python artifacts:
    __pycache__/  
    *.pyc  
    .env  
    venv/  
    

Step 2: Create Your Tool Module(s)

You can organize your tools in a single Python file or a package structure.

  • Single File Example: Create my_tools.py in the root of your repository.
  • Package Example:
    my-gofannon-tools/  
    ├── my_tool_package/  
    │   ├── __init__.py  
    │   └── specific_tool.py  
    └── tool_manifest.json  
    

Step 3: Define Your Custom Tools

Each custom tool should be a Python class inheriting from gofannon.base.BaseTool.

  1. Import BaseTool:
    If you have Gofannon installed locally for development, you can import it. If not, you'll need to ensure your tool class structure is compatible. For AgentLabUI's ADK deployment, the key is that your tool class can be instantiated and has an export_to_adk() method (which BaseTool from Gofannon provides) or is directly an ADK-compatible tool.

    If Gofannon is not directly in your Python path for local development, you can define a compatible base structure. However, to leverage Gofannon's mixins (like AdkMixin), your tool should ideally inherit from gofannon.base.BaseTool. When AgentLabUI deploys an agent using your tool, it installs the gofannon package alongside your custom tool repo.

  2. Create your tool class:

    # In your my_tools.py or my_tool_package/specific_tool.py  
    
    from gofannon.base import BaseTool  
    # You do NOT need @FunctionRegistry.register for tools in external repos  
    # consumed by AgentLabUI, as the manifest.json is the discovery mechanism.  
    
    class MyCustomWebServiceTool(BaseTool):  
        def __init__(self, name="my_custom_web_service", api_key=None): # 'name' from manifest, api_key from setup_parameters  
            super().__init__()  
            self.name = name # Name from manifest or default  
            self.api_key = api_key # Received from ToolSelector dialog if configured in manifest  
            if not self.api_key:  
                self.logger.warning(f"{self.name}: API key not provided during instantiation.")  
                # You might raise an error or handle gracefully depending on the tool's needs  
    
        @property  
        def definition(self):  
            """  
            This definition is used by Gofannon's AdkMixin to export  
            the tool to a format ADK can understand. It should describe  
            the tool for an LLM.  
            """  
            return {  
                "type": "function",  
                "function": {  
                    "name": self.name, # Should match the ID in tool_manifest.json  
                    "description": "Fetches data from my custom web service.",  
                    "parameters": {  
                        "type": "object",  
                        "properties": {  
                            "endpoint": {  
                                "type": "string",  
                                "description": "The specific API endpoint to call (e.g., '/users')."  
                            },  
                            "query_params": {  
                                "type": "object",  
                                "description": "A dictionary of query parameters for the API call."  
                            }  
                        },  
                        "required": ["endpoint"]  
                    }  
                }  
            }  
    
        def fn(self, endpoint: str, query_params: dict = None):  
            """  
            The actual logic of your tool.  
            """  
            if not self.api_key:  
                return {"error": "API key is missing. Cannot execute tool."}  
    
            # Example: Make an API call  
            # import requests  
            # headers = {"Authorization": f"Bearer {self.api_key}"}  
            # response = requests.get(f"https://api.example.com{endpoint}", params=query_params, headers=headers)  
            # response.raise_for_status()  
            # return response.json()  
    
            self.logger.info(f"Executing {self.name} for endpoint: {endpoint} with API key {'*' * len(self.api_key) if self.api_key else 'N/A'}")  
            return {"message": f"Data fetched from {endpoint}", "params": query_params, "api_key_used_length": len(self.api_key) if self.api_key else 0}  

    Key points for your tool class:

    • It must inherit (directly or indirectly) from gofannon.base.BaseTool.
    • The __init__ method can accept arguments. If your tool requires configuration like API keys, define them as setup_parameters in your tool_manifest.json (see Step 4). These will be passed as keyword arguments to __init__ when AgentLabUI instantiates the tool.
    • The definition property must return a dictionary in the OpenAI function calling format. This describes your tool to the Language Model. The name in function.name should ideally match the id you assign in tool_manifest.json.
    • The fn method contains the Python code that executes your tool's logic. Its parameters should match those defined in the properties of your definition.

Step 4: Create tool_manifest.json

This is the most crucial file for AgentLabUI to discover your tools. Create a file named tool_manifest.json at the root of your repository.

The file structure should be:

{  
  "tools": [  
    {  
      "id": "my_custom_web_service_v1",  
      "name": "Custom Web Service Caller",  
      "description": "Connects to our internal web service to fetch data.",  
      "module_path": "my_tools",  
      "class_name": "MyCustomWebServiceTool",  
      "setup_parameters": [  
        {  
          "name": "api_key",  
          "label": "API Key",  
          "type": "secret",  
          "description": "The API key for accessing the custom web service.",  
          "required": true,  
          "default_value": ""  
        }  
      ]  
    }  
    // Add more tool definitions here  
  ]  
}  

Manifest Fields:

  • tools: An array of tool objects.
  • Each tool object has:
    • id (string, required): A unique identifier for your tool. Used internally.
    • name (string, required): A human-readable name displayed in AgentLabUI.
    • description (string, required): A short description of what the tool does.
    • module_path (string, required): The Python import path to the module containing your tool class.
      • If your tool is in my_tools.py at the root, this is "my_tools".
      • If in my_tool_package/specific_tool.py, this would be "my_tool_package.specific_tool".
    • class_name (string, required): The name of your Python class for the tool.
    • setup_parameters (array, optional): Defines configuration parameters your tool's __init__ method needs. AgentLabUI will prompt the user for these. Each object in the array needs:
      • name (string): The keyword argument name in your tool's __init__.
      • label (string): Human-readable label for the UI.
      • type (string): Data type, e.g., "string", "secret" (for password fields), "number", "boolean".
      • description (string): Description shown in the UI.
      • required (boolean): If the parameter is mandatory.
      • default_value (any, optional): A default value for the parameter.

Step 5: (Optional) Add Dependencies

If your tools require external Python libraries (e.g., requests, beautifulsoup4), create a requirements.txt file at the root of your repository.

# requirements.txt  
requests==2.28.1  
# other_dependency==1.2.3  

When an agent using tools from this repository is deployed via AgentLabUI, the ADK deployment process will attempt to install these dependencies.

Step 6: Commit and Push to Git Hosting

  1. Add your files to Git:
    git add .  
  2. Commit your changes:
    git commit -m "Add custom web service tool and manifest"  
  3. Create a repository on a public Git hosting service (like GitHub).
  4. Add the remote and push:
    git remote add origin <your_repository_url.git>  
    git push -u origin main # Or your default branch name  

Make sure your repository is publicly accessible if you intend for AgentLabUI (and the underlying ADK deployment service) to clone it without authentication.

How AgentLabUI Consumes Your Repository

In AgentLabUI:

  1. When creating or editing an agent, go to the "Tools" section.
  2. Find the "Gofannon & Custom Tools" accordion and expand "Load Tools from Custom Git Repo".
  3. Enter the HTTPS URL of your Git repository (e.g., https://github.com/your-username/my-gofannon-tools.git).
  4. Click "Load Tools".
  5. AgentLabUI will attempt to fetch tool_manifest.json from the root of the repository at the default branch.
  6. If successful, your custom tools will appear in the selection list, grouped by their repository URL.
  7. If your tool has setup_parameters, AgentLabUI will prompt for these when you select the tool.

When you deploy an agent that uses a tool from your custom repository, the ADK deployment process will include your repository URL in the requirements. The build service will then clone your repository and install any dependencies from requirements.txt into the agent's runtime environment.

Example: Simple Adder Tool

1. Repository Structure:

my-adder-tool-repo/  
├── simple_calculator.py  
└── tool_manifest.json  

2. simple_calculator.py:

from gofannon.base import BaseTool  
  
class SimpleAdderTool(BaseTool):  
    def __init__(self, name="simple_adder"):  
        super().__init__()  
        # The 'name' parameter here will be overridden by the 'id' from the manifest  
        # when instantiated by AgentLabUI, or you can use the manifest 'name'  
        # for display. The ADK tool name will be derived from the definition.  
        self.name = name  
  
    @property  
    def definition(self):  
        return {  
            "type": "function",  
            "function": {  
                "name": "simple_adder_tool", # Should match id in manifest for clarity  
                "description": "Adds two numbers and returns the sum.",  
                "parameters": {  
                    "type": "object",  
                    "properties": {  
                        "number1": {"type": "number", "description": "The first number."},  
                        "number2": {"type": "number", "description": "The second number."}  
                    },  
                    "required": ["number1", "number2"]  
                }  
            }  
        }  
  
    def fn(self, number1: float, number2: float) -> float:  
        """Adds two numbers."""  
        self.logger.info(f"Adding {number1} and {number2}")  
        return number1 + number2  

3. tool_manifest.json:

{  
  "tools": [  
    {  
      "id": "simple_adder_tool",  
      "name": "Simple Adder",  
      "description": "A tool that adds two numbers.",  
      "module_path": "simple_calculator",  
      "class_name": "SimpleAdderTool"  
    }  
  ]  
}  

Best Practices

  • Clear Naming: Use clear and descriptive id, name, and description fields in your manifest.
  • Modularity: Keep tools focused on a single task.
  • Error Handling: Implement robust error handling within your tool's fn method.
  • Logging: Use self.logger (available from BaseTool) for logging within your tools.
  • Dependencies: Clearly list all dependencies in requirements.txt. Keep them minimal if possible.
  • Security: Be mindful of security implications, especially if your tools interact with external services or handle sensitive data. Use setup_parameters with type: "secret" for API keys.
  • Testing: Test your tools thoroughly locally before relying on them in AgentLabUI.
  • Versioning: Use Git tags to version releases of your tool repository.

By following these steps, you can effectively create and share your custom Gofannon tools for use within AgentLabUI, significantly enhancing its capabilities for your specific needs.