> ## 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.

# Building Custom Tools

> Create tools using IronClaw's LLM-driven software builder

IronClaw includes a powerful software builder that can create tools, applications, and libraries using LLM-driven code generation.

**Location**: `src/tools/builder/`

## Overview

The software builder provides:

* **LLM-driven development**: Uses an agent loop similar to Codex for iterative development
* **Multiple software types**: WASM tools, CLI apps, libraries, scripts
* **Build loop**: Analyze → Scaffold → Implement → Build → Fix → Test → Validate → Package
* **Language support**: Rust, Python, JavaScript/TypeScript, Bash
* **WASM tool specialization**: Automatic WIT interface compliance and capability generation

## Architecture

```text theme={null}
┌─────────────────────────────────────────────────────────────────────────────┐
│                          Software Build Loop                                 │
│                                                                              │
│  1. Analyze requirement ─▶ Determine project type, language, structure      │
│  2. Generate scaffold   ─▶ Create initial project files                     │
│  3. Implement code      ─▶ Write the actual implementation                  │
│  4. Build/compile       ─▶ Run build commands (cargo, npm, etc.)            │
│  5. Fix errors          ─▶ Parse errors, modify code, retry                 │
│  6. Test                ─▶ Run tests, fix failures                          │
│  7. Validate            ─▶ For WASM tools, verify interface compliance      │
│  8. Package             ─▶ Produce final artifact                           │
└─────────────────────────────────────────────────────────────────────────────┘
```

**Location**: `src/tools/builder/mod.rs:11-24`

## Build Tool

### build\_software

**Location**: `src/tools/builder/core.rs`

Create software using LLM-driven iterative development.

```json theme={null}
{
  "requirement": "Create a WASM tool that checks GitHub PR status",
  "software_type": "wasm_tool",
  "language": "rust",
  "output_path": "/workspace/github-pr-tool",
  "test_cases": [
    {
      "description": "Check PR status",
      "input": {"owner": "rust-lang", "repo": "rust", "pr": 12345},
      "expected_output": "status: open"
    }
  ],
  "max_iterations": 10,
  "auto_install": true
}
```

**Parameters**:

| Parameter | Type | Description |
| - | - | - |
| `requirement` | string | Natural language description of what to build |
| `software_type` | enum | Type of software: `wasm_tool`, `cli_app`, `library`, `script` |
| `language` | enum | Programming language: `rust`, `python`, `javascript`, `typescript`, `bash` |
| `output_path` | string | Where to create the project |
| `test_cases` | array | Optional test cases to validate against |
| `max_iterations` | number | Max build/fix cycles (default: 5) |
| `auto_install` | boolean | Automatically install WASM tools after build |
| `context` | object | Additional context for code generation |

**Domain**: Container\
**Approval**: Always\
**Rate Limit**: 5/min, 20/hour

## Software Types

**Location**: `src/tools/builder/core.rs:28-45`

```rust theme={null}
pub enum SoftwareType {
    /// WASM tool for IronClaw (sandboxed)
    WasmTool,
    /// Command-line application
    CliApp,
    /// Reusable library
    Library,
    /// Single-file script
    Script,
}
```

### WASM Tool

Sandboxed tool that compiles to WebAssembly.

**Features**:

* Automatic WIT interface implementation
* Capability file generation
* Host function usage (log, http, workspace\_read)
* Integration with tool registry

**Template**: `src/tools/builder/templates.rs:WasmToolTemplate`

### CLI App

Standalone command-line application.

**Features**:

* Argument parsing (clap for Rust, argparse for Python)
* Error handling
* Help documentation
* Exit codes

### Library

Reusable library with public API.

**Features**:

* Module structure
* Public API design
* Documentation
* Example usage

### Script

Single-file executable script.

**Features**:

* Shebang line
* Inline dependencies (Rust scripts use `cargo-script`)
* Simple execution model

## Languages

**Location**: `src/tools/builder/core.rs:47-60`

```rust theme={null}
pub enum Language {
    Rust,
    Python,
    JavaScript,
    TypeScript,
    Bash,
}
```

### Rust

**Build system**: Cargo\
**WASM target**: `wasm32-wasip2`\
**Package manager**: crates.io

**Example Cargo.toml**:

```toml theme={null}
[package]
name = "my-tool"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wit-bindgen = "0.28"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
strip = true
```

### Python

**Package manager**: pip\
**Virtual env**: venv\
**Testing**: pytest

**Example requirements.txt**:

```
requests>=2.31.0
pydantic>=2.0.0
pytest>=7.4.0
```

### JavaScript/TypeScript

**Runtime**: Node.js\
**Package manager**: npm\
**Build tool**: esbuild, tsc

**Example package.json**:

```json theme={null}
{
  "name": "my-tool",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "axios": "^1.6.0"
  },
  "devDependencies": {
    "@types/node": "^20.10.0",
    "typescript": "^5.3.0"
  }
}
```

### Bash

**Interpreter**: bash\
**Testing**: bats-core

**Example script**:

```bash theme={null}
#!/usr/bin/env bash
set -euo pipefail

# Tool implementation
main() {
    local input="$1"
    echo "Processing: $input"
}

main "$@"
```

## Build Phases

**Location**: `src/tools/builder/core.rs:62-85`

```rust theme={null}
pub enum BuildPhase {
    /// Analyze requirements and determine project structure
    Analyzing,
    /// Generate project scaffold
    Scaffolding,
    /// Implement core functionality
    Implementing,
    /// Compile/build the project
    Building,
    /// Fix compilation errors
    FixingErrors { iteration: u32, error: String },
    /// Run tests
    Testing,
    /// Validate against requirements
    Validating,
    /// Package final artifact
    Packaging,
    /// Build complete
    Complete,
    /// Build failed
    Failed { reason: String },
}
```

Each phase produces a `BuildLog` entry with details and outputs.

## Templates

**Location**: `src/tools/builder/templates.rs`

### Template Engine

```rust theme={null}
pub struct TemplateEngine;

impl TemplateEngine {
    pub fn render_wasm_tool(
        name: &str,
        description: &str,
        requirement: &str,
    ) -> HashMap<String, String>;
    
    pub fn render_cli_app(
        name: &str,
        language: Language,
        description: &str,
    ) -> HashMap<String, String>;
    
    pub fn render_library(
        name: &str,
        language: Language,
        description: &str,
    ) -> HashMap<String, String>;
    
    pub fn render_script(
        name: &str,
        language: Language,
        description: &str,
    ) -> HashMap<String, String>;
}
```

### WASM Tool Template

**Files generated**:

* `Cargo.toml` - Rust project config
* `src/lib.rs` - Tool implementation with WIT bindings
* `<name>.capabilities.json` - Capability declarations
* `README.md` - Documentation
* `.gitignore` - Git ignore patterns

**Example lib.rs**:

```rust theme={null}
wit_bindgen::generate!({
    world: "sandboxed-tool",
    path: "../../wit/tool.wit",
});

use serde::{Deserialize, Serialize};

struct MyTool;

#[derive(Deserialize)]
struct Params {
    // Parameters based on requirement
}

#[derive(Serialize)]
struct Output {
    // Output based on requirement
}

impl exports::near::agent::tool::Guest for MyTool {
    fn name() -> String {
        "my_tool".to_string()
    }

    fn description() -> String {
        "Tool description".to_string()
    }

    fn parameters_schema() -> String {
        // JSON Schema generated from Params
        serde_json::json!({
            "type": "object",
            "properties": {},
            "required": []
        }).to_string()
    }

    fn execute(params_json: String) -> Result<String, String> {
        // Implementation
        Ok(serde_json::json!({"status": "success"}).to_string())
    }
}

export!(MyTool);
```

## Testing Framework

**Location**: `src/tools/builder/testing.rs`

```rust theme={null}
pub struct TestCase {
    pub description: String,
    pub input: serde_json::Value,
    pub expected_output: Option<String>,
    pub expected_error: Option<String>,
}

pub struct TestSuite {
    pub cases: Vec<TestCase>,
}

pub struct TestHarness;

impl TestHarness {
    pub async fn run_tests(
        software_type: SoftwareType,
        project_path: &Path,
        suite: &TestSuite,
    ) -> Vec<TestResult>;
}

pub struct TestResult {
    pub case: TestCase,
    pub passed: bool,
    pub actual_output: Option<String>,
    pub error: Option<String>,
    pub duration: Duration,
}
```

**Example test cases**:

```json theme={null}
{
  "test_cases": [
    {
      "description": "Basic GitHub API call",
      "input": {
        "action": "get_repo",
        "owner": "rust-lang",
        "repo": "rust"
      },
      "expected_output": "name: rust"
    },
    {
      "description": "Invalid repo",
      "input": {
        "action": "get_repo",
        "owner": "invalid",
        "repo": "nonexistent"
      },
      "expected_error": "404"
    }
  ]
}
```

## Validation

**Location**: `src/tools/builder/validation.rs`

### WASM Validator

```rust theme={null}
pub struct WasmValidator;

impl WasmValidator {
    /// Validate WASM tool interface compliance
    pub async fn validate(
        wasm_path: &Path,
        runtime: &WasmToolRuntime,
    ) -> ValidationResult;
}

pub struct ValidationResult {
    pub valid: bool,
    pub errors: Vec<ValidationError>,
    pub warnings: Vec<String>,
}

pub enum ValidationError {
    MissingExport { name: String },
    InvalidSchema { reason: String },
    RuntimeError { error: String },
    InterfaceMismatch { expected: String, actual: String },
}
```

**Validation checks**:

1. WASM binary is valid
2. Exports required functions (name, description, parameters\_schema, execute)
3. Parameters schema is valid JSON Schema
4. Tool can be instantiated
5. Test execution doesn't trap

## Builder Configuration

**Location**: `src/tools/builder/core.rs:87-110`

```rust theme={null}
pub struct BuilderConfig {
    /// Maximum build/fix iterations
    pub max_iterations: u32,
    /// Timeout for each build attempt
    pub build_timeout: Duration,
    /// Timeout for test execution
    pub test_timeout: Duration,
    /// Whether to preserve intermediate build artifacts
    pub keep_artifacts: bool,
    /// Whether to run tests
    pub run_tests: bool,
    /// Whether to validate WASM tools
    pub validate_wasm: bool,
}

impl Default for BuilderConfig {
    fn default() -> Self {
        Self {
            max_iterations: 5,
            build_timeout: Duration::from_secs(300),
            test_timeout: Duration::from_secs(60),
            keep_artifacts: false,
            run_tests: true,
            validate_wasm: true,
        }
    }
}
```

## LLM Software Builder

**Location**: `src/tools/builder/core.rs:112-200`

```rust theme={null}
pub struct LlmSoftwareBuilder {
    config: BuilderConfig,
    llm: Arc<dyn LlmProvider>,
    safety: Arc<SafetyLayer>,
    tools: Arc<ToolRegistry>,
}

impl LlmSoftwareBuilder {
    pub fn new(
        config: BuilderConfig,
        llm: Arc<dyn LlmProvider>,
        safety: Arc<SafetyLayer>,
        tools: Arc<ToolRegistry>,
    ) -> Self;
    
    pub async fn build(
        &self,
        requirement: BuildRequirement,
    ) -> Result<BuildResult, BuildError>;
}

pub struct BuildRequirement {
    pub description: String,
    pub software_type: SoftwareType,
    pub language: Language,
    pub output_path: PathBuf,
    pub test_cases: Vec<TestCase>,
    pub context: HashMap<String, String>,
}

pub struct BuildResult {
    pub success: bool,
    pub artifact_path: Option<PathBuf>,
    pub phases: Vec<BuildPhase>,
    pub logs: Vec<BuildLog>,
    pub test_results: Vec<TestResult>,
    pub validation: Option<ValidationResult>,
}
```

## Usage Examples

### Build WASM Tool

```rust theme={null}
use ironclaw::tools::builder::{LlmSoftwareBuilder, BuildRequirement, SoftwareType, Language, TestCase};
use std::path::PathBuf;

let requirement = BuildRequirement {
    description: "Create a WASM tool that fetches GitHub repository information".to_string(),
    software_type: SoftwareType::WasmTool,
    language: Language::Rust,
    output_path: PathBuf::from("/workspace/github-info-tool"),
    test_cases: vec![
        TestCase {
            description: "Get rust-lang/rust repo".to_string(),
            input: serde_json::json!({
                "owner": "rust-lang",
                "repo": "rust"
            }),
            expected_output: Some("stars:".to_string()),
            expected_error: None,
        },
    ],
    context: HashMap::new(),
};

let builder = LlmSoftwareBuilder::new(config, llm, safety, tools);
let result = builder.build(requirement).await?;

if result.success {
    println!("Built successfully: {:?}", result.artifact_path);
} else {
    println!("Build failed");
    for log in result.logs {
        println!("  {}: {}", log.phase, log.message);
    }
}
```

### Build CLI App

```rust theme={null}
let requirement = BuildRequirement {
    description: "Create a CLI tool that converts Markdown to HTML".to_string(),
    software_type: SoftwareType::CliApp,
    language: Language::Rust,
    output_path: PathBuf::from("/workspace/md2html"),
    test_cases: vec![],
    context: HashMap::new(),
};

let result = builder.build(requirement).await?;
```

### Build with Agent Tool

```json theme={null}
{
  "tool": "build_software",
  "params": {
    "requirement": "Create a Python script that analyzes log files and generates statistics",
    "software_type": "script",
    "language": "python",
    "output_path": "/workspace/log-analyzer.py",
    "test_cases": [
      {
        "description": "Analyze sample log",
        "input": {
          "log_file": "/tmp/test.log"
        },
        "expected_output": "Total lines:"
      }
    ]
  }
}
```

## Error Recovery

The builder automatically recovers from common errors:

### Compilation Errors

```rust theme={null}
// Builder detects error:
// error[E0425]: cannot find value `foo` in this scope

// LLM fixes by:
// 1. Reading error message
// 2. Identifying missing variable
// 3. Adding declaration or import
// 4. Rebuilding
```

### Dependency Errors

```rust theme={null}
// Builder detects:
// error: package `serde` cannot be found

// LLM fixes by:
// 1. Adding to Cargo.toml dependencies
// 2. Running cargo build again
```

### Test Failures

```rust theme={null}
// Builder detects test failure:
// expected: "success"
// actual: "error: invalid input"

// LLM fixes by:
// 1. Analyzing test case
// 2. Identifying logic error
// 3. Modifying implementation
// 4. Re-running tests
```

## Best Practices

1. **Provide clear requirements**: Detailed descriptions lead to better results
2. **Include test cases**: Tests guide the implementation and catch errors
3. **Set appropriate timeouts**: Complex builds may need longer timeouts
4. **Review generated code**: Always review before deploying to production
5. **Iterate on requirements**: Refine the description if initial results are off
6. **Use context**: Provide relevant context (API docs, examples, constraints)
7. **Monitor iterations**: If max\_iterations is reached, simplify the requirement

## Limitations

* **LLM quality dependent**: Results depend on the underlying LLM's capabilities
* **Complex projects**: Very large or complex projects may exceed context limits
* **External dependencies**: May struggle with undocumented or obscure APIs
* **Architecture decisions**: May not make optimal architectural choices
* **Security**: Generated code should be reviewed for security issues

## Next Steps

<CardGroup cols={2}>
  <Card title="WASM Tools" icon="cube" href="/tools/wasm">
    Learn about the WASM tool system
  </Card>

  <Card title="Built-in Tools" icon="wrench" href="/tools/builtin">
    Explore built-in tool reference
  </Card>
</CardGroup>
