Skip to content

Tools

Tools extend the capabilities of agents, allowing them to interact with the system and external resources.

Available Tools

File Operations

file_read

Read the contents of a file.

Parameters: - path (str, required): Path to the file - offset (int, optional): Line offset to start from (0-indexed) - limit (int, optional): Maximum lines to read

Example:

{
  "name": "file_read",
  "arguments": {
    "path": "README.md",
    "offset": 0,
    "limit": 50
  }
}

file_write

Write content to a file.

Parameters: - path (str, required): Path to the file - content (str, required): Content to write - append (bool, optional): Append instead of overwrite

Example:

{
  "name": "file_write",
  "arguments": {
    "path": "output.txt",
    "content": "Hello, World!",
    "append": false
  }
}

file_edit

Edit a file using search and replace.

Parameters: - path (str, required): Path to the file - old_string (str, required): Text to find - new_string (str, required): Text to replace with

Example:

{
  "name": "file_edit",
  "arguments": {
    "path": "config.py",
    "old_string": "DEBUG = True",
    "new_string": "DEBUG = False"
  }
}

System Operations

bash

Execute bash commands.

Parameters: - command (str, required): Command to execute - cwd (str, optional): Working directory - timeout (int, optional): Timeout in seconds

Example:

{
  "name": "bash",
  "arguments": {
    "command": "ls -la",
    "cwd": "/home/user/project"
  }
}

Security: - Dangerous commands are blocked - Cannot access files outside working directory - Timeout prevents hanging commands

Web Operations

Search the web using DuckDuckGo.

Parameters: - query (str, required): Search query - max_results (int, optional): Maximum results (default: 5) - region (str, optional): Region code (default: "wt-wt") - safesearch (str, optional): Safe search level

Example:

{
  "name": "web_search",
  "arguments": {
    "query": "Python asyncio best practices",
    "max_results": 3
  }
}

Using Tools

In Chat

Agents automatically use tools when needed:

You: Read the README.md file and tell me what this project does.

Agent: [Uses file_read tool]

This project is a CLI framework for autonomous AI agents...

Disable Tools

legionhercules chat --no-tools

Or in interactive mode:

/tools

Creating Custom Tools

Basic Tool Structure

from legionhercules.tools.base import Tool, ToolResult
from typing import Any

class MyTool(Tool):
    def __init__(self):
        super().__init__(
            name="my_tool",
            description="Description of what my tool does"
        )

    async def execute(self, param1: str, param2: int = 0) -> ToolResult:
        """Execute the tool.

        Args:
            param1: Description of param1
            param2: Description of param2
        """
        try:
            # Your tool logic here
            result = f"Processed {param1} with {param2}"

            return ToolResult(
                success=True,
                output=result,
                metadata={"param1": param1}
            )
        except Exception as e:
            return ToolResult(success=False, error=str(e))

    def get_schema(self) -> dict[str, Any]:
        """Define the JSON schema for tool parameters."""
        return {
            "type": "object",
            "properties": {
                "param1": {
                    "type": "string",
                    "description": "Description of param1"
                },
                "param2": {
                    "type": "integer",
                    "description": "Description of param2",
                    "default": 0
                }
            },
            "required": ["param1"]
        }

Registering Custom Tools

from legionhercules.tools.base import ToolRegistry

# Create registry
registry = ToolRegistry()

# Register tool
registry.register(MyTool())

# Use in agent
from legionhercules.core.agent import Agent, AgentConfig

config = AgentConfig(
    name="custom_agent",
    tools=["my_tool", "file_read"]
)

Tool Best Practices

1. Clear Descriptions

Write clear, specific descriptions:

# Good
description="Calculate the factorial of a number n"

# Bad
description="Does math stuff"

2. Validate Inputs

Always validate inputs and return helpful errors:

async def execute(self, number: int) -> ToolResult:
    if number < 0:
        return ToolResult(
            success=False,
            error="Number must be non-negative"
        )
    # ...

3. Security First

  • Validate file paths
  • Sanitize command inputs
  • Set reasonable timeouts
  • Limit resource usage

4. Meaningful Results

Return structured data when possible:

return ToolResult(
    success=True,
    output={"count": 42, "items": [...]},
    metadata={"query_time": 0.5}
)

Tool Registry

The ToolRegistry manages available tools:

from legionhercules.tools.base import ToolRegistry

# Create with default tools
registry = ToolRegistry.create_default_registry()

# List tools
tools = registry.list_tools()

# Get tool
tool = registry.get_tool("file_read")

# Check if tool exists
if registry.has_tool("bash"):
    print("Bash tool available")

# Get all tool schemas (for LLM)
schemas = registry.get_tool_schemas()

Error Handling

Tools should handle errors gracefully:

async def execute(self, path: str) -> ToolResult:
    try:
        # Attempt operation
        content = Path(path).read_text()
        return ToolResult(success=True, output=content)

    except FileNotFoundError:
        return ToolResult(
            success=False,
            error=f"File not found: {path}"
        )
    except PermissionError:
        return ToolResult(
            success=False,
            error=f"Permission denied: {path}"
        )
    except Exception as e:
        return ToolResult(
            success=False,
            error=f"Unexpected error: {str(e)}"
        )