# Tool Registry

The tool registry is the catalog of all capabilities available to the agent. It's responsible for defining, discovering, validating, and executing tools safely.

## Purpose

- **Discovery**: Tell the model what tools are available
- **Definition**: Provide schemas so the model knows how to call them
- **Validation**: Ensure tool calls are well-formed
- **Execution**: Run tools with proper error handling
- **Security**: Enforce permissions and sandboxing
- **Extensibility**: Support built-in tools and MCP servers

## Tool Definition Structure

Every tool needs a clear definition:

```typescript
interface Tool {
  name: string;           // Unique identifier (e.g., "read_file")
  description: string;    // Clear description for the model
  parameters: JSONSchema; // Input schema
  category: string;       // Grouping (filesystem, shell, search, etc.)
  requiresPermission: boolean;
  riskLevel: 'low' | 'medium' | 'high';
  execute: (args: any, context: ToolContext) => Promise<ToolResult>;
}
```

## Tool Schema Design

Good tool schemas help the model call tools correctly:

```json
{
  "name": "read_file",
  "description": "Read the contents of a file. Returns the file content as text.",
  "parameters": {
    "type": "object",
    "properties": {
      "path": {
        "type": "string",
        "description": "Absolute or relative path to the file"
      },
      "offset": {
        "type": "number",
        "description": "Line number to start from (1-based)"
      },
      "limit": {
        "type": "number", 
        "description": "Maximum number of lines to read"
      }
    },
    "required": ["path"]
  }
}
```

## Tool Categories

| Category | Examples | Risk Level | Notes |
|---|---|---|---|
| **Read** | read_file, glob, grep, search | Low | Generally safe, read-only |
| **Write/Edit** | write_file, edit, str_replace | Medium | Modify files, need care |
| **Execute** | bash, run_command | High | Shell access, most dangerous |
| **Navigate** | cd, list_dir | Low | Directory operations |
| **Git** | git_status, git_diff, git_commit | Medium-High | Version control changes |
| **Web** | webfetch, websearch | Medium | Network access |
| **Browser** | browser_navigate, browser_click | High | Full browser control |
| **MCP** | Dynamic from servers | Varies | Depends on server |

## Registry Implementation

```python
class ToolRegistry:
    def __init__(self):
        self.tools = {}
        self.categories = {}
    
    def register(self, tool: Tool):
        self.tools[tool.name] = tool
        self.categories.setdefault(tool.category, []).append(tool.name)
    
    def get(self, name: str) -> Tool | None:
        return self.tools.get(name)
    
    def get_schemas_for_model(self, allowed_tools=None) -> list:
        """Return tool schemas in model's expected format"""
        tools = self.tools.values()
        if allowed_tools:
            tools = [t for t in tools if t.name in allowed_tools]
        return [self._format_schema(t) for t in tools]
    
    async def execute(self, name: str, args: dict, context: ToolContext):
        tool = self.get(name)
        if not tool:
            raise ToolNotFoundError(name)
        # Validate args against schema
        validate(args, tool.parameters)
        # Check permissions
        await context.permission_checker.check(tool, args)
        # Execute with timeout
        return await asyncio.wait_for(tool.execute(args, context), timeout=300)
```

## Tool Context

Tools need access to harness capabilities:

```typescript
interface ToolContext {
  sessionId: string;
  workingDirectory: string;
  permissionChecker: PermissionChecker;
  sandbox: Sandbox;
  logger: Logger;
  abortSignal?: AbortSignal;
  userId?: string;
}
```

## Built-in Tool Examples

### Filesystem Tools
```python
@tool(name="read_file", category="filesystem", risk_level="low")
async def read_file(args, ctx):
    path = resolve_path(args["path"], ctx.workingDirectory)
    content = await ctx.sandbox.read_file(path)
    return {"content": content, "path": path}
```

### Shell Tool
```python
@tool(name="bash", category="shell", risk_level="high", requiresPermission=True)
async def bash(args, ctx):
    command = args["command"]
    # Permission check will handle approval
    result = await ctx.sandbox.execute_shell(command, timeout=args.get("timeout", 120))
    return {"stdout": result.stdout, "stderr": result.stderr, "exitCode": result.exitCode}
```

### Search Tools
```python
@tool(name="grep", category="search", risk_level="low")
async def grep(args, ctx):
    pattern = args["pattern"]
    path = args.get("path", ctx.workingDirectory)
    results = await ctx.sandbox.grep(pattern, path, args.get("include"))
    return {"matches": results}
```

## MCP Integration

The registry should also support tools from MCP servers:

```python
class MCPToolAdapter:
    def __init__(self, server_name: str, tool_def: MCPTool):
        self.server_name = server_name
        self.name = f"{server_name}__{tool_def.name}"  # Namespaced
        self.description = tool_def.description
        self.parameters = tool_def.inputSchema
    
    async def execute(self, args, ctx):
        return await ctx.mcp_client.call_tool(
            self.server_name, 
            self.original_name, 
            args
        )
```

## Best Practices

### Tool Design
1. **Clear descriptions** - Tell the model when to use the tool and what it does
2. **Minimal parameters** - Fewer required params = fewer mistakes
3. **Good defaults** - Make common cases easy
4. **Consistent naming** - Use verb_noun pattern (read_file, run_command)
5. **Return useful info** - Include enough context for next steps

### Registry Design
1. **Lazy loading** - Load MCP tools on demand
2. **Tool filtering** - Show only relevant tools based on context
3. **Validation** - Validate schemas at registration time
4. **Error messages** - Clear errors when tools fail or aren't found
5. **Namespacing** - Avoid collisions between built-in and MCP tools

### Security
1. **Permission gates** - High-risk tools need approval
2. **Input validation** - Sanitize paths, commands
3. **Path restrictions** - Don't allow escaping working directory
4. **Command filtering** - Block dangerous shell patterns
5. **Audit logging** - Log all tool executions

## Tool Result Format

Consistent result format helps the model understand outcomes:

```typescript
interface ToolResult {
  success: boolean;
  output?: any;      // Main result data
  error?: string;    // Error message if failed
  metadata?: {
    duration: number;
    truncated?: boolean;
    [key: string]: any;
  };
}
```

## Related Notes

- [[Permission-System.md]] — Security and approvals
- [[../../ToolUse/Function-Calling.md]] — Model tool calling
- [[../../ToolUse/MCP-Protocol.md]] — MCP integration
- [[../Execution/Error-Recovery.md]] — Handling tool failures
- [[../Integration/Filesystem-Integration.md]] — Filesystem tools

## Sources

* OpenAI Function Calling documentation  
* Anthropic Tool Use documentation  
* MCP Specification  
* LangChain Tools  
* OpenCode tool implementations  
