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.
Overview
Tools are IronClaw’s interface to the outside world. They enable the agent to perform actions: call APIs, read files, execute code, search memory, and more. The tool system is designed for security, extensibility, and self-expansion.
Built-in Tools Core tools written in Rust
echo, time, json
http, web_fetch
shell, read_file, write_file
memory_search, memory_write
WASM Tools Sandboxed tools in WebAssembly
User-built tools
Dynamically created by agent
Capability-based security
Hot-reloadable
MCP Servers Model Context Protocol extensions
Filesystem access
Database connections
External APIs
Third-party integrations
All tools implement a common interface:
#[async_trait]
pub trait Tool : Send + Sync {
/// Tool name (must be unique)
fn name ( & self ) -> & str ;
/// Human-readable description for LLM
fn description ( & self ) -> & str ;
/// JSON Schema for parameters
fn parameters_schema ( & self ) -> serde_json :: Value ;
/// Execute the tool
async fn execute (
& self ,
params : serde_json :: Value ,
ctx : & JobContext ,
) -> Result < ToolOutput , ToolError >;
/// Execution domain (orchestrator vs container)
fn domain ( & self ) -> ToolDomain {
ToolDomain :: Orchestrator
}
/// Require user approval before execution
fn requires_approval ( & self , _params : & serde_json :: Value ) -> ApprovalRequirement {
ApprovalRequirement :: NotRequired
}
/// Rate limiting configuration
fn rate_limit_config ( & self ) -> Option < ToolRateLimitConfig > {
None
}
/// Execution timeout
fn execution_timeout ( & self ) -> Duration {
Duration :: from_secs ( 30 )
}
}
Description : Returns current time in various formatsParameters :{
"format" : "iso8601 | unix | human" ,
"timezone" : "UTC | America/New_York | ..."
}
Example :{
"format" : "human" ,
"timezone" : "America/Los_Angeles"
}
// Returns: "Tuesday, March 3, 2026 at 2:30 PM PST"
json - Parse and manipulate JSON
Description : Query, transform, and validate JSON dataParameters :{
"operation" : "parse | stringify | query | validate" ,
"data" : "string or object" ,
"path" : "optional JSONPath query"
}
Example :{
"operation" : "query" ,
"data" : { "users" : [{ "name" : "Alice" , "age" : 30 }]},
"path" : "$.users[0].name"
}
// Returns: "Alice"
http - Make HTTP requests
Description : Call external APIs with full controlParameters :{
"url" : "string" ,
"method" : "GET | POST | PUT | DELETE" ,
"headers" : { "key" : "value" },
"body" : "optional request body" ,
"credential" : "optional credential name"
}
Credential Injection :{
"url" : "https://api.openai.com/v1/chat/completions" ,
"method" : "POST" ,
"credential" : "OPENAI_API_KEY" ,
"headers" : { "Content-Type" : "application/json" },
"body" : "{...}"
}
// Orchestrator injects: Authorization: Bearer sk-...
// Tool never sees actual key
The tool requests a credential by name , but never sees the actual value. The orchestrator injects it at the HTTP boundary.
web_fetch - Fetch and convert web pages
Description : Fetch URLs and convert HTML to readable markdownParameters :{
"url" : "string" ,
"selector" : "optional CSS selector" ,
"convert_to_markdown" : true
}
Example :{
"url" : "https://docs.example.com/api" ,
"selector" : "article.documentation" ,
"convert_to_markdown" : true
}
// Returns clean markdown of documentation
Features :
HTML to Markdown conversion
CSS selector filtering
JavaScript rendering (headless browser)
Image alt-text extraction
read_file - Read file contents
Description : Read files from the working directoryDomain : Container (sandboxed environment only)Parameters :Security :
Only available in Docker containers
Cannot read files outside job workspace
Path traversal (../) blocked
write_file - Write file contents
Description : Create or overwrite filesDomain : ContainerParameters :{
"path" : "string" ,
"content" : "string"
}
Approval : Requires user approval for destructive operations
list_dir - List directory contents
Description : List files and directoriesDomain : ContainerParameters :{
"path" : "string" ,
"recursive" : false
}
apply_patch - Apply unified diff patch
Description : Apply code changes via unified diff formatDomain : ContainerParameters :{
"patch" : "unified diff string"
}
Example :--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
fn main() {
+ println!("Hello, world!");
// existing code
}
memory_search - Hybrid search across workspace
Description : Full-text + semantic search using Reciprocal Rank FusionParameters :{
"query" : "string" ,
"limit" : 10
}
Example :{
"query" : "project alpha deployment issues" ,
"limit" : 5
}
Returns :[
{
"path" : "projects/alpha/notes.md" ,
"score" : 0.89 ,
"content" : "Deployment failed due to..." ,
"chunk_index" : 3
},
...
]
memory_write - Write to workspace
Description : Create or update workspace filesParameters :{
"path" : "string" ,
"content" : "string" ,
"mode" : "write | append"
}
Automatic Indexing : Written content is automatically:
Chunked (500 char chunks with 50 char overlap)
Embedded (vector embeddings for semantic search)
Indexed (BM25 for full-text search)
memory_read - Read workspace file
Description : Read a specific workspace file by pathParameters :
memory_tree - Browse workspace structure
Description : List workspace files and directoriesParameters :{
"directory" : "string" ,
"recursive" : false
}
WASM Sandbox
Untrusted tools run in isolated WebAssembly containers.
Architecture
┌───────────────────────────────────────────────────────────┐
│ WASM Tool Execution │
│ │
│ Tool Call ──► Validate ──► Allowlist ──► Inject ──► Run │
│ Schema Endpoints Creds WASM │
│ │
│ ◄──── Leak Scan ◄──── Result │
│ Sanitize │
└───────────────────────────────────────────────────────────┘
Capability System
WASM tools start with zero capabilities:
No Capabilities (Default)
HTTP Capability
Secrets Capability
Workspace Capability
Tool Invoke Capability
Capabilities :: none ()
// Can only process JSON input/output
// No network, no secrets, no filesystem
Security Boundaries
Fuel Metering
Memory Limits
Network Isolation
Credential Injection
Threat : Infinite loops, CPU exhaustionProtection :const DEFAULT_FUEL_LIMIT : u64 = 200_000_000 ;
// Approximately 2 seconds of execution
Behavior :
Fuel consumed per WASM instruction
Automatic termination when fuel exhausted
Per-execution timeout (30s default)
Threat : Unbounded allocationsProtection :pub struct ResourceLimits {
pub memory_limit : usize , // Default: 10MB
}
Behavior :
Hard cap enforced by Wasmtime ResourceLimiter
Memory growth tracking
Instance discarded on overflow
Threat : Unauthorized API callsProtection :AllowlistValidator :: validate (
& request_url ,
& allowed_patterns
)
Behavior :
Every HTTP request validated against allowlist
Host + path + method matching
Deny by default
Leak detection on response
Threat : Secret exposureProtection :// WASM requests credential by name
http_call ( url , "OPENAI_API_KEY" )
// Orchestrator injects actual value
injector . inject ( & request , & secrets_store )
Behavior :
WASM never sees actual credential
Injection at host boundary
Leak scan on all outputs
Automatic redaction
Host Functions
WASM tools can call host-provided functions:
// Logging
log ( level : u8 , message : & str )
// Time
time_now () -> i64
// HTTP (if capability granted)
http_call (
url : & str ,
method : & str ,
headers : & str ,
body : & str ,
credential_name : Option < & str >
) -> Result < HttpResponse >
// Workspace (if capability granted)
workspace_read ( path : & str ) -> Result < String >
workspace_write ( path : & str , content : & str ) -> Result <()>
workspace_search ( query : & str , limit : u32 ) -> Result < Vec < SearchResult >>
// Tool Invocation (if capability granted)
invoke_tool ( name : & str , params : & str ) -> Result < String >
Create Rust Project
cargo new --lib my_tool
cd my_tool
Add Dependencies
[ dependencies ]
serde = { version = "1.0" , features = [ "derive" ] }
serde_json = "1.0"
[ lib ]
crate-type = [ "cdylib" ]
Implement Tool
use serde :: { Deserialize , Serialize };
#[derive( Deserialize )]
struct Input {
query : String ,
}
#[derive( Serialize )]
struct Output {
result : String ,
}
#[no_mangle]
pub extern "C" fn execute ( input_ptr : * const u8 , input_len : usize ) -> u64 {
let input = unsafe {
std :: slice :: from_raw_parts ( input_ptr , input_len )
};
let params : Input = serde_json :: from_slice ( input ) . unwrap ();
let output = Output {
result : format! ( "Processed: {}" , params . query),
};
let output_json = serde_json :: to_vec ( & output ) . unwrap ();
// Return pointer and length as u64
let ptr = output_json . as_ptr () as u64 ;
let len = output_json . len () as u64 ;
( ptr << 32 ) | len
}
Build WASM Module
cargo build --target wasm32-wasip1 --release
Register with IronClaw
let wasm_bytes = std :: fs :: read (
"target/wasm32-wasip1/release/my_tool.wasm"
) ? ;
registry . register_wasm ( WasmToolRegistration {
name : "my_tool" ,
wasm_bytes : & wasm_bytes ,
runtime : & runtime ,
capabilities : Capabilities :: none (),
limits : None ,
description : Some ( "My custom tool" ),
schema : Some ( serde_json :: json! ({
"type" : "object" ,
"properties" : {
"query" : { "type" : "string" }
},
"required" : [ "query" ]
})),
secrets_store : None ,
oauth_refresh : None ,
}) . await ? ;
Use the build_software tool to have IronClaw build WASM tools for you automatically.
IronClaw can build new tools on the fly.
{
"description" : "Build a tool that fetches cryptocurrency prices from CoinGecko API" ,
"software_type" : "wasm_tool" ,
"language" : "rust" ,
"requirements" : [
"Fetch price for a given coin ID" ,
"Support USD, EUR, GBP currencies" ,
"Return current price and 24h change"
]
}
Build Process
Iterative Refinement
The builder uses an iterative loop:
Plan : Break down requirements into steps
Generate : Write code using LLM
Compile : Build in Docker sandbox
Test : Run test cases
Fix : If tests fail, analyze errors and regenerate
Validate : Ensure schema matches
Register : Add to tool registry
The builder can iterate up to 10 times to fix compilation errors and test failures.
MCP Protocol
Model Context Protocol servers provide additional capabilities.
MCP Architecture
┌─────────────────────────────────────────────────────┐
│ IronClaw Core │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ MCP Client Manager │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Filesystem │ PostgreSQL │ │ GitHub │ │ │
│ │ │ MCP │ │ MCP │ │ MCP │ │ │
│ │ └─────┬────┘ └─────┬────┘ └─────┬────┘ │ │
│ └────────┼─────────────┼─────────────┼───────┘ │
│ │ │ │ │
│ └─────────────┴─────────────┘ │
│ │ │
│ Tool Registry │
└─────────────────────────────────────────────────┘
MCP Server Configuration
{
"mcpServers" : {
"filesystem" : {
"command" : "npx" ,
"args" : [ "-y" , "@modelcontextprotocol/server-filesystem" , "/home/user/projects" ],
"env" : {}
},
"postgres" : {
"command" : "npx" ,
"args" : [ "-y" , "@modelcontextprotocol/server-postgres" ],
"env" : {
"POSTGRES_CONNECTION_STRING" : "postgresql://..."
}
}
}
}
MCP server tools are automatically wrapped as IronClaw tools:
// MCP server exposes: read_file, write_file, list_directory
// IronClaw wraps as:
tool_registry . register ( "mcp_filesystem_read_file" )
tool_registry . register ( "mcp_filesystem_write_file" )
tool_registry . register ( "mcp_filesystem_list_directory" )
MCP servers run as untrusted processes. Do not grant them access to sensitive credentials.
Central registry managing all available tools.
pub struct ToolRegistry {
tools : RwLock < HashMap < String , Arc < dyn Tool >>>,
builtin_names : RwLock < HashSet < String >>,
credential_registry : Option < Arc < SharedCredentialRegistry >>,
secrets_store : Option < Arc < dyn SecretsStore >>,
rate_limiter : RateLimiter ,
}
Core tools cannot be shadowed:
const PROTECTED_TOOL_NAMES : & [ & str ] = & [
"echo" , "time" , "json" , "http" , "shell" ,
"read_file" , "write_file" , "list_dir" ,
"memory_search" , "memory_write" , "memory_read" ,
"create_job" , "list_jobs" , "cancel_job" ,
"build_software" ,
// ... and more
];
Dynamically registered tools (WASM, MCP) cannot override protected names. This prevents malicious tools from replacing security-critical operations.
// List all tools
let tools = registry . list () . await ;
// Get tool definitions for LLM
let definitions = registry . tool_definitions () . await ;
// Get specific tool
let tool = registry . get ( "memory_search" ) . await ;
// Check if tool exists
if registry . has ( "crypto_price" ) . await {
// ...
}
Rate Limiting
Per-tool rate limits prevent abuse:
pub struct ToolRateLimitConfig {
pub max_calls : u32 , // Max calls per window
pub window_secs : u64 , // Window duration
pub burst_size : Option < u32 >, // Allow bursts
}
Approval System
Sensitive operations require user approval:
pub enum ApprovalRequirement {
NotRequired ,
Required { reason : String },
ConditionallyRequired { condition : Box < dyn Fn ( & Value ) -> bool > },
}
Example: Conditional Approval
impl Tool for WriteFileTool {
fn requires_approval ( & self , params : & Value ) -> ApprovalRequirement {
let path = params [ "path" ] . as_str () . unwrap_or ( "" );
if path . ends_with ( ".rs" ) || path . ends_with ( ".toml" ) {
ApprovalRequirement :: Required {
reason : "Modifying source code" . into ()
}
} else {
ApprovalRequirement :: NotRequired
}
}
}
Approval Flow :
Tool execution requested
Check requires_approval(params)
If required, send StatusUpdate::ApprovalNeeded
Wait for user response
Execute if approved, skip if denied
Next Steps
WASM Sandbox Deep dive into WASM security and capabilities
MCP Integration Connect Model Context Protocol servers
Building Tools Create custom tools dynamically
Tool Examples Real-world tool implementations