Skip to main content

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.

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

┌─────────────────────────────────────────────────────────────────────────────┐
│                          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.
{
  "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:
ParameterTypeDescription
requirementstringNatural language description of what to build
software_typeenumType of software: wasm_tool, cli_app, library, script
languageenumProgramming language: rust, python, javascript, typescript, bash
output_pathstringWhere to create the project
test_casesarrayOptional test cases to validate against
max_iterationsnumberMax build/fix cycles (default: 5)
auto_installbooleanAutomatically install WASM tools after build
contextobjectAdditional context for code generation
Domain: Container
Approval: Always
Rate Limit: 5/min, 20/hour

Software Types

Location: src/tools/builder/core.rs:28-45
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
pub enum Language {
    Rust,
    Python,
    JavaScript,
    TypeScript,
    Bash,
}

Rust

Build system: Cargo
WASM target: wasm32-wasip2
Package manager: crates.io
Example Cargo.toml:
[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:
{
  "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:
#!/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
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

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:
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
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:
{
  "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

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

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

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

{
  "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

// 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

// Builder detects:
// error: package `serde` cannot be found

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

Test Failures

// 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

WASM Tools

Learn about the WASM tool system

Built-in Tools

Explore built-in tool reference

Build docs developers (and LLMs) love