How to Add Tools to Aitana

This comprehensive guide walks you through adding new tools to the Aitana platform, from initial planning through testing and deployment.

Overview

Adding tools to Aitana involves several components:

  • Backend: Python tool implementation and orchestration
  • Frontend: React components for tool configuration and UI
  • Configuration: Tag-based access control and permissions
  • Documentation: Comprehensive testing and documentation

Prerequisites

Before adding a new tool, ensure you have:

  • Development environment set up (see CLAUDE.md)
  • Understanding of the existing tool architecture
  • Familiarity with the codebase structure

Step-by-Step Workflow

1. Plan Your Tool

Define the tool’s purpose:

  • What specific functionality will it provide?
  • Who will use it (which user roles/tags)?
  • What inputs/outputs does it need?
  • Are there any security considerations?

Check existing tools: Review the Tool Orchestrator System to see if similar functionality already exists.

2. Backend Implementation

2.1 Create the Tool Module

Create a new Python file in /backend/tools/:

# backend/tools/your_new_tool.py
from typing import Dict, Any, Optional
import asyncio
from .base_tool import BaseTool  # If using base class pattern

class YourNewTool(BaseTool):
    """
    Brief description of what your tool does.
    """
    
    async def execute(self, **kwargs) -> Dict[str, Any]:
        """
        Main execution logic for your tool.
        
        Args:
            **kwargs: Tool-specific parameters
            
        Returns:
            Dict containing tool execution results
        """
        # Implementation here
        pass
    
    def validate_inputs(self, **kwargs) -> bool:
        """
        Validate input parameters before execution.
        """
        # Validation logic here
        pass

2.2 Register with Tool Orchestrator

Update /backend/tools/tool_orchestrator.py to include your new tool:

from .your_new_tool import YourNewTool

# Add to available tools
AVAILABLE_TOOLS = {
    # ... existing tools
    'your_new_tool': YourNewTool,
}

Reference: See the complete Tool Orchestrator System documentation for detailed integration patterns.

3. Frontend Integration

3.1 Update ToolSelector Component

Add your tool to the ToolSelector in /src/components/tools/ToolSelector.tsx:

// Add to available tools list
const availableTools = [
  // ... existing tools
  {
    id: 'your_new_tool',
    name: 'Your New Tool',
    description: 'Brief description of functionality',
    category: 'utility', // or appropriate category
    icon: YourToolIcon,
    component: YourToolDemo // Optional demo component
  }
];

3.2 Create Configuration Component (Optional)

If your tool needs custom configuration, create a component in /src/components/tools/:

// src/components/tools/YourNewToolConfig.tsx
interface YourNewToolConfigProps {
  config: any;
  onChange: (config: any) => void;
  readOnly?: boolean;
}

export const YourNewToolConfig: React.FC<YourNewToolConfigProps> = ({
  config,
  onChange,
  readOnly = false
}) => {
  // Configuration UI here
};

Reference: See ToolSelector Component for detailed patterns.

4. Tool Confirmation Integration

If your tool requires user confirmation before execution:

4.1 Backend Confirmation Setup

# In your tool's execute method
if requires_confirmation:
    return {
        "requires_confirmation": True,
        "confirmation_message": "Do you want to execute this action?",
        "tool_name": "your_new_tool",
        "parameters": kwargs
    }

4.2 Frontend Confirmation Handling

The Tool Confirmation Flow will automatically handle confirmation UI if your tool returns the appropriate response format.

References:

5. Tag-Based Access Control

Configure which users can access your tool using the tag system:

5.1 Define Tool Tags

In your tool configuration, specify required tags:

// In tool definition
tags: ['admin', 'power_user'], // Users need these tags to access the tool
restrictedConfig: {
  // Fields that require specific tags to modify
  advancedOptions: ['admin']
}

5.2 Backend Tag Validation

Ensure your backend tool respects tag-based permissions:

async def execute(self, user_tags: List[str], **kwargs):
    if not self.has_required_tags(user_tags):
        raise PermissionError("Insufficient permissions")
    # Tool logic here

References:

6. UI Components Integration

6.1 Tools Toggle Section

Your tool will automatically appear in the Tools Toggle Section once registered.

6.2 Tool Configuration Dialog

If using custom configuration, integrate with the ToolConfigurator:

// In ToolConfigurator component
const configComponents = {
  // ... existing configs
  your_new_tool: YourNewToolConfig
};

7. Testing Your Tool

7.1 Backend Tests

Create tests in /backend/tests/tools/:

# backend/tests/tools/test_your_new_tool.py
import pytest
from tools.your_new_tool import YourNewTool

class TestYourNewTool:
    async def test_execute_success(self):
        tool = YourNewTool()
        result = await tool.execute(param1="value1")
        assert result["status"] == "success"
    
    async def test_validation_failure(self):
        tool = YourNewTool()
        with pytest.raises(ValueError):
            await tool.execute(invalid_param="invalid")

7.2 Frontend Tests

Create tests in /src/components/tools/__tests__/:

// src/components/tools/__tests__/YourNewTool.test.tsx
import { render, screen } from '@testing-library/react';
import { YourNewToolConfig } from '../YourNewToolConfig';

describe('YourNewToolConfig', () => {
  it('should render configuration options', () => {
    render(<YourNewToolConfig config= onChange={() => {}} />);
    expect(screen.getByText('Tool Configuration')).toBeInTheDocument();
  });
});

References:

8. Documentation

8.1 Tool-Specific Documentation

Create documentation for your tool in /docs/features/:

# YOUR_NEW_TOOL.md

## Overview
Description of what your tool does.

## Configuration
How to configure the tool.

## Usage Examples
Examples of using the tool.

## Troubleshooting
Common issues and solutions.

8.2 Update Documentation Index

Add your documentation to /docs/README.md:

- **[Your New Tool](./features/YOUR_NEW_TOOL.md)** - Tool-specific guide

9. Quality Checks

Before submitting your tool:

# Run quality checks
npm run quality:check

# Run specific tests
npm test src/components/tools/__tests__/YourNewTool.test.tsx
cd backend && python -m pytest tests/tools/test_your_new_tool.py -v

10. Deployment Considerations

10.1 Environment Variables

If your tool requires new environment variables:

For Backend Variables (Cloud Run):

For Frontend Variables (NEXT_PUBLIC_*):

Local Development:

  1. Add to .env.local.example:
    NEXT_PUBLIC_YOUR_TOOL_API_KEY=your-api-key
    NEXT_PUBLIC_YOUR_TOOL_CONFIG=configuration-value
    

Production Deployment:

  1. Add to GCP Secret Manager under FIREBASE_ENV secret:
    # Download current secrets
    gcloud secrets versions access latest --secret=FIREBASE_ENV --project YOUR_PROJECT_ID > .env.local
       
    # Add your new variables to .env.local
    echo "NEXT_PUBLIC_YOUR_TOOL_API_KEY=your-api-key" >> .env.local
       
    # Upload back to Secret Manager
    gcloud secrets versions add FIREBASE_ENV --data-file=.env.local --project YOUR_PROJECT_ID
       
    # Redeploy frontend to pick up new secrets
    

The get-firebase-config.sh script automatically downloads these during Cloud Build deployment.

10.2 Dependencies

If adding new Python packages:

cd backend
uv add your-new-package

If adding new npm packages:

npm install your-new-package

Common Patterns and Best Practices

Error Handling

# Backend
try:
    result = await your_tool_logic()
    return {"status": "success", "data": result}
except SpecificError as e:
    return {"status": "error", "message": str(e)}
except Exception as e:
    logger.error(f"Unexpected error in your_tool: {e}")
    return {"status": "error", "message": "Internal error"}

Async Operations

# Use async/await for I/O operations
async def fetch_external_data(url: str):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.json()

Configuration Validation

// Frontend configuration validation
const validateConfig = (config: any): string[] => {
  const errors: string[] = [];
  if (!config.requiredField) {
    errors.push("Required field is missing");
  }
  return errors;
};

Troubleshooting

Common Issues

  1. Tool not appearing in UI: Check ToolSelector registration
  2. Permission errors: Verify tag-based access control setup
  3. Configuration not saving: Check ToolContext integration
  4. Backend errors: Review Tool Orchestrator logs

Getting Help

  • Review existing tool implementations in /backend/tools/
  • Check the Tool Confirmation Bug Fix guide
  • Create a GitHub issue with @claude for specific questions

Core Architecture

Frontend Components

Access Control

Testing & Quality

Development Setup

Examples

For examples of existing tool implementations, examine:

  • /backend/tools/google_search.py - External API integration
  • /backend/tools/code_execution.py - Complex processing tool
  • /backend/tools/ai_search.py - AI-powered tool
  • /src/components/tools/ToolSelector.tsx - Frontend integration patterns

This comprehensive guide should help you successfully add new tools to the Aitana platform while following established patterns and best practices.