> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nearai/ironclaw/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools Module

> Extensible tool system for agent capabilities and external integrations

## Overview

The tools module provides an extensible system for agent capabilities. Tools can:

* Call external APIs
* Interact with the marketplace
* Execute sandboxed code (via WASM)
* Delegate tasks to other services
* Build new software and tools dynamically

Tools execute in different domains (orchestrator vs. container) with safety controls, rate limiting, and approval requirements.

## Core Types

### Tool Trait

The main trait that all tools must implement.

```rust theme={null}
#[async_trait]
pub trait Tool: Send + Sync {
    fn name(&self) -> &str;
    fn description(&self) -> &str;
    fn parameters_schema(&self) -> serde_json::Value;
    
    async fn execute(
        &self,
        params: serde_json::Value,
        ctx: &JobContext,
    ) -> Result<ToolOutput, ToolError>;
    
    fn estimated_cost(&self, params: &serde_json::Value) -> Option<Decimal> {
        None
    }
    
    fn approval_requirement(&self, params: &serde_json::Value) -> ApprovalRequirement {
        ApprovalRequirement::Never
    }
    
    fn domain(&self) -> ToolDomain {
        ToolDomain::Orchestrator
    }
    
    fn rate_limit_config(&self) -> Option<ToolRateLimitConfig> {
        None
    }
}
```

#### Methods

<ResponseField name="name" type="fn(&self) -> &str">
  Return the tool name (must be unique in registry)
</ResponseField>

<ResponseField name="description" type="fn(&self) -> &str">
  Human-readable description of what the tool does
</ResponseField>

<ResponseField name="parameters_schema" type="fn(&self) -> serde_json::Value">
  JSON Schema defining the tool's parameters
</ResponseField>

<ResponseField name="execute" type="async fn(&self, params: Value, ctx: &JobContext) -> Result<ToolOutput>">
  Execute the tool with given parameters and context
</ResponseField>

<ResponseField name="estimated_cost" type="fn(&self, params: &Value) -> Option<Decimal>">
  Estimate the cost of running this tool (optional)
</ResponseField>

<ResponseField name="approval_requirement" type="fn(&self, params: &Value) -> ApprovalRequirement">
  Whether this invocation requires approval
</ResponseField>

<ResponseField name="domain" type="fn(&self) -> ToolDomain">
  Where this tool should execute (Orchestrator or Container)
</ResponseField>

<ResponseField name="rate_limit_config" type="fn(&self) -> Option<ToolRateLimitConfig>">
  Rate limiting configuration for this tool
</ResponseField>

#### Example

```rust theme={null}
use ironclaw::tools::{Tool, ToolOutput, ToolError};
use async_trait::async_trait;

struct EchoTool;

#[async_trait]
impl Tool for EchoTool {
    fn name(&self) -> &str {
        "echo"
    }
    
    fn description(&self) -> &str {
        "Echo back the input message"
    }
    
    fn parameters_schema(&self) -> serde_json::Value {
        serde_json::json!({
            "type": "object",
            "properties": {
                "message": {
                    "type": "string",
                    "description": "Message to echo"
                }
            },
            "required": ["message"]
        })
    }
    
    async fn execute(
        &self,
        params: serde_json::Value,
        _ctx: &JobContext,
    ) -> Result<ToolOutput, ToolError> {
        let message = params["message"].as_str()
            .ok_or_else(|| ToolError::InvalidParameters(
                "message must be a string".to_string()
            ))?;
        
        Ok(ToolOutput::text(message, Duration::from_millis(1)))
    }
}
```

### ToolRegistry

Manages the collection of available tools.

<ResponseField name="new" type="fn() -> Self">
  Create a new empty tool registry
</ResponseField>

<ResponseField name="register" type="fn(&mut self, tool: Arc<dyn Tool>) -> Result<()>">
  Register a tool in the registry (fails if name already exists)
</ResponseField>

<ResponseField name="get" type="fn(&self, name: &str) -> Option<Arc<dyn Tool>>">
  Get a tool by name
</ResponseField>

<ResponseField name="list" type="fn(&self) -> Vec<&str>">
  List all registered tool names
</ResponseField>

<ResponseField name="schemas" type="fn(&self) -> Vec<ToolDefinition>">
  Get all tool schemas for LLM function calling
</ResponseField>

#### Example

```rust theme={null}
use ironclaw::tools::ToolRegistry;

let mut registry = ToolRegistry::new();
registry.register(Arc::new(EchoTool))?;
registry.register(Arc::new(TimeTool))?;

// List all tools
for name in registry.list() {
    println!("Available: {}", name);
}

// Get a tool
if let Some(tool) = registry.get("echo") {
    let output = tool.execute(params, &ctx).await?;
}
```

### ToolOutput

Result returned by tool execution.

<ParamField path="result" type="serde_json::Value">
  The result data (JSON value)
</ParamField>

<ParamField path="cost" type="Option<Decimal>">
  Cost incurred (if any)
</ParamField>

<ParamField path="duration" type="Duration">
  Time taken to execute
</ParamField>

<ParamField path="raw" type="Option<String>">
  Raw output before sanitization (for debugging)
</ParamField>

#### Constructors

<ResponseField name="success" type="fn(result: Value, duration: Duration) -> Self">
  Create a successful output with JSON result
</ResponseField>

<ResponseField name="text" type="fn(text: impl Into<String>, duration: Duration) -> Self">
  Create a text output (convenience for string results)
</ResponseField>

<ResponseField name="with_cost" type="fn(self, cost: Decimal) -> Self">
  Add cost information to the output
</ResponseField>

<ResponseField name="with_raw" type="fn(self, raw: impl Into<String>) -> Self">
  Add raw output for debugging
</ResponseField>

#### Example

```rust theme={null}
use ironclaw::tools::ToolOutput;
use std::time::Duration;
use rust_decimal_macros::dec;

let output = ToolOutput::text("Hello, world!", Duration::from_millis(5))
    .with_cost(dec!(0.001));
```

### ToolError

Error types for tool execution.

<ResponseField name="InvalidParameters" type="String">
  Parameters don't match the schema or are invalid
</ResponseField>

<ResponseField name="ExecutionFailed" type="String">
  Tool execution failed with an error
</ResponseField>

<ResponseField name="Timeout" type="Duration">
  Tool execution exceeded timeout
</ResponseField>

<ResponseField name="NotAuthorized" type="String">
  User not authorized to use this tool
</ResponseField>

<ResponseField name="RateLimited" type="Option<Duration>">
  Rate limit exceeded, retry after duration
</ResponseField>

<ResponseField name="ExternalService" type="String">
  External service error (API, network, etc.)
</ResponseField>

<ResponseField name="Sandbox" type="String">
  Sandbox/WASM execution error
</ResponseField>

### ApprovalRequirement

Defines how much approval a tool invocation needs.

<ResponseField name="Never" type="()">
  No approval needed (safe, read-only tools)
</ResponseField>

<ResponseField name="UnlessAutoApproved" type="()">
  Needs approval unless user has auto-approved this tool
</ResponseField>

<ResponseField name="Always" type="()">
  Always requires explicit approval (destructive operations)
</ResponseField>

#### Example

```rust theme={null}
use ironclaw::tools::ApprovalRequirement;

impl Tool for FileDeleteTool {
    fn approval_requirement(&self, _params: &Value) -> ApprovalRequirement {
        ApprovalRequirement::Always  // Destructive operation
    }
}

impl Tool for FileReadTool {
    fn approval_requirement(&self, _params: &Value) -> ApprovalRequirement {
        ApprovalRequirement::Never  // Safe read-only
    }
}
```

### ToolDomain

Where a tool should execute.

<ResponseField name="Orchestrator" type="()">
  Safe to run in the main agent process (pure functions, memory, job management)
</ResponseField>

<ResponseField name="Container" type="()">
  Must run inside a sandboxed container (filesystem, shell, code execution)
</ResponseField>

```rust theme={null}
use ironclaw::tools::ToolDomain;

impl Tool for MemoryWriteTool {
    fn domain(&self) -> ToolDomain {
        ToolDomain::Orchestrator  // Safe in main process
    }
}

impl Tool for ShellTool {
    fn domain(&self) -> ToolDomain {
        ToolDomain::Container  // Needs isolation
    }
}
```

### ToolRateLimitConfig

Rate limiting configuration for tools.

<ParamField path="requests_per_minute" type="u32" default="60">
  Maximum invocations per minute per user
</ParamField>

<ParamField path="requests_per_hour" type="u32" default="1000">
  Maximum invocations per hour per user
</ParamField>

<ResponseField name="new" type="fn(requests_per_minute: u32, requests_per_hour: u32) -> Self">
  Create a custom rate limit config
</ResponseField>

<ResponseField name="default" type="fn() -> Self">
  Default: 60/min, 1000/hour
</ResponseField>

```rust theme={null}
use ironclaw::tools::ToolRateLimitConfig;

impl Tool for HttpTool {
    fn rate_limit_config(&self) -> Option<ToolRateLimitConfig> {
        Some(ToolRateLimitConfig::new(30, 500))  // Conservative limits
    }
}
```

## Schema Validation

### validate\_tool\_schema

<ResponseField name="validate_tool_schema" type="fn(schema: &Value, params: &Value) -> Result<()>">
  Validate parameters against a JSON Schema. Returns error if validation fails.
</ResponseField>

```rust theme={null}
use ironclaw::tools::validate_tool_schema;

let schema = serde_json::json!({
    "type": "object",
    "properties": {
        "name": { "type": "string" },
        "age": { "type": "number" }
    },
    "required": ["name"]
});

let params = serde_json::json!({
    "name": "Alice",
    "age": 30
});

validate_tool_schema(&schema, &params)?;  // OK
```

## Rate Limiting

### RateLimiter

Per-user rate limiting for tool invocations.

<ResponseField name="new" type="fn() -> Self">
  Create a new rate limiter
</ResponseField>

<ResponseField name="check_and_increment" type="fn(&self, user_id: &str, tool_name: &str, config: &ToolRateLimitConfig) -> Result<(), Duration>">
  Check if request is allowed and increment counter. Returns error with retry-after duration if rate limited.
</ResponseField>

```rust theme={null}
use ironclaw::tools::RateLimiter;

let limiter = RateLimiter::new();
let config = ToolRateLimitConfig::default();

match limiter.check_and_increment("user_123", "http", &config) {
    Ok(()) => {
        // Proceed with tool execution
    }
    Err(retry_after) => {
        return Err(ToolError::RateLimited(Some(retry_after)));
    }
}
```

## Software Builder

Dynamically build and deploy new tools at runtime.

### SoftwareBuilder

Trait for building software from natural language specifications.

```rust theme={null}
#[async_trait]
pub trait SoftwareBuilder: Send + Sync {
    async fn build(
        &self,
        requirements: &BuildRequirement,
    ) -> Result<BuildResult, Box<dyn std::error::Error>>;
}
```

### LlmSoftwareBuilder

LLM-powered software builder that generates code from specs.

<ResponseField name="new" type="fn(llm: Arc<dyn LlmProvider>, config: BuilderConfig) -> Self">
  Create a new LLM-based software builder
</ResponseField>

<ResponseField name="build" type="async fn(&self, requirements: &BuildRequirement) -> Result<BuildResult>">
  Build software from requirements using LLM code generation
</ResponseField>

#### BuildRequirement

<ParamField path="name" type="String">
  Name of the software/tool to build
</ParamField>

<ParamField path="description" type="String">
  What the software should do
</ParamField>

<ParamField path="language" type="Language">
  Target language (Rust, Python, JavaScript, etc.)
</ParamField>

<ParamField path="software_type" type="SoftwareType">
  Type (Tool, Library, Service, etc.)
</ParamField>

<ParamField path="dependencies" type="Vec<String>">
  Required dependencies
</ParamField>

<ParamField path="test_cases" type="Vec<TestCase>">
  Test cases to validate the implementation
</ParamField>

#### BuildResult

<ParamField path="source_code" type="String">
  Generated source code
</ParamField>

<ParamField path="metadata" type="BuildMetadata">
  Build information (language, version, etc.)
</ParamField>

<ParamField path="test_results" type="Vec<TestResult>">
  Results of running test cases
</ParamField>

<ParamField path="validation_errors" type="Vec<ValidationError>">
  Any validation errors found
</ParamField>

#### Example

```rust theme={null}
use ironclaw::tools::{LlmSoftwareBuilder, BuildRequirement, Language, SoftwareType};

let builder = LlmSoftwareBuilder::new(llm, BuilderConfig::default());

let req = BuildRequirement {
    name: "fibonacci".to_string(),
    description: "Calculate Fibonacci numbers".to_string(),
    language: Language::Rust,
    software_type: SoftwareType::Tool,
    dependencies: vec![],
    test_cases: vec![],
};

let result = builder.build(&req).await?;
println!("Generated code:\n{}", result.source_code);
```

## MCP (Model Context Protocol)

Integration with external MCP servers for tool discovery.

### McpClient

Client for connecting to MCP servers and loading tools.

<ResponseField name="connect" type="async fn(server_url: &str) -> Result<Self>">
  Connect to an MCP server
</ResponseField>

<ResponseField name="list_tools" type="async fn(&self) -> Result<Vec<ToolDefinition>>">
  List available tools from the MCP server
</ResponseField>

<ResponseField name="load_tool" type="async fn(&self, name: &str) -> Result<Arc<dyn Tool>>">
  Load a specific tool from the MCP server
</ResponseField>

```rust theme={null}
use ironclaw::tools::mcp::McpClient;

let client = McpClient::connect("http://localhost:3000").await?;
let tools = client.list_tools().await?;

for tool_def in tools {
    let tool = client.load_tool(&tool_def.name).await?;
    registry.register(tool)?;
}
```

## WASM Tools

Load and execute tools compiled to WebAssembly.

### WasmTool

A tool implementation that runs in a WASM sandbox.

<ResponseField name="load" type="async fn(wasm_bytes: &[u8]) -> Result<Self>">
  Load a WASM module as a tool
</ResponseField>

<ResponseField name="from_file" type="async fn(path: &Path) -> Result<Self>">
  Load a WASM module from a file
</ResponseField>

```rust theme={null}
use ironclaw::tools::wasm::WasmTool;

let wasm_bytes = std::fs::read("tools/custom.wasm")?;
let tool = WasmTool::load(&wasm_bytes).await?;

registry.register(Arc::new(tool))?;
```

## Built-in Tools

IronClaw includes several built-in tools in the `builtin` module:

* `EchoTool` - Echo back input (testing)
* `TimeTool` - Get current time
* `JsonTool` - Parse and manipulate JSON
* `HttpTool` - Make HTTP requests
* `MemoryReadTool` - Read from workspace
* `MemoryWriteTool` - Write to workspace
* `MemorySearchTool` - Search workspace
* `ShellTool` - Execute shell commands (container)
* `FileReadTool` - Read files (container)
* `FileWriteTool` - Write files (container)

See the source code for full details on each tool's parameters and behavior.

## Related Modules

<Card title="Agent Module" icon="robot" href="/api/agent">
  Agent orchestration and tool execution
</Card>

<Card title="Workspace Module" icon="folder" href="/api/workspace">
  Memory tools for persistent storage
</Card>
