Documentation Index Fetch the complete documentation index at: https://mintlify.com/nullclaw/nullclaw/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Tools are NullClaw’s capability layer for LLM function calling. Every tool implements the Tool vtable interface, enabling the agent to execute system commands, file I/O, API calls, and hardware interactions.
pub const Tool = struct {
ptr : * anyopaque ,
vtable : * const VTable ,
pub const VTable = struct {
execute : * const fn (
ptr : * anyopaque ,
allocator : std . mem . Allocator ,
args : JsonObjectMap ,
) anyerror ! ToolResult ,
name : * const fn ( ptr : * anyopaque ) [] const u8 ,
description : * const fn ( ptr : * anyopaque ) [] const u8 ,
parameters_json : * const fn ( ptr : * anyopaque ) [] const u8 ,
deinit : ?* const fn ( ptr : * anyopaque , allocator : std . mem . Allocator ) void = null ,
};
};
pub const ToolResult = struct {
success : bool ,
output : [] const u8 , // Owned by caller, must free
error_msg : ? [] const u8 , // Owned by caller, must free if non-null
};
Tool Description Parameters file_read Read file contents path: string, offset?: number, limit?: numberfile_write Write/overwrite file path: string, content: stringfile_edit Edit file (search/replace) path: string, old_string: string, new_string: stringfile_append Append to file path: string, content: string
Shell Execution
Tool Description Parameters shell Run shell command command: string, timeout_secs?: number
Tool Description Parameters memory_store Save memory entry key: string, content: string, category?: stringmemory_recall Search memory query: string, limit?: numbermemory_list List all memories category?: stringmemory_forget Delete memory entry key: string
Tool Description Parameters http_request HTTP GET/POST url: string, method?: string, headers?: object, body?: stringweb_search Search the web query: string, num_results?: numberweb_fetch Fetch webpage content url: string, max_chars?: numberbrowser_open Open URL in browser url: stringscreenshot Take screenshot output_path?: string
Tool Description Parameters git Run git commands command: string
Tool Description Parameters hardware_info Get board info board: stringhardware_memory Read/write memory board: string, address: number, value?: numberi2c I2C read/write bus: number, address: number, register: number, value?: numberspi SPI transfer bus: number, data: array<number>
Tool Description Parameters cron_add Add cron job expression: string, command: stringcron_list List cron jobs — cron_remove Remove cron job id: stringcron_run Run job now id: stringcron_update Update job id: string, expression?: string, command?: stringcron_runs List recent runs limit?: number
Tool Description Parameters delegate Delegate to subagent agent_id: string, task: stringspawn Spawn async subagent task: string, timeout_secs?: numberschedule Schedule future task when: string, task: string
Tool Description Parameters message Send message to channel channel: string, target: string, message: stringpushover Send push notification message: string, priority?: number
Tool Description Parameters composio Execute Composio action action: string, params: objectimage Get image metadata path: string
Step-by-Step
LLM returns tool calls in ChatResponse.tool_calls:
{
"id" : "call_abc123" ,
"name" : "file_read" ,
"arguments" : "{ \" path \" : \" README.md \" }"
}
Agent dispatcher looks up tool by name
Parses arguments from JSON string to JsonObjectMap
Security policy check :
Workspace scoping (file paths)
Command allowlist (shell commands)
Risk classification (high-risk commands)
Tool execution via vtable.execute():
const result = try tool . execute ( allocator , args );
Result formatting :
if ( result . success ) {
// Append result.output to conversation
} else {
// Append result.error_msg as error
}
Next LLM call with tool result in context
Security Boundaries
Workspace Scoping
By default, file tools are restricted to ~/.nullclaw/workspace/:
{
"autonomy" : {
"workspace_only" : true ,
"allowed_paths" : [] // Additional paths outside workspace
}
}
Path validation :
Null byte injection blocked
Symlink escape detection
Absolute path resolution
Parent directory traversal blocked (unless in allowed_paths)
Command Allowlist
Shell tool enforces command allowlist:
{
"autonomy" : {
"allowed_commands" : [ "git" , "npm" , "zig" ], // Prefix matching
"block_high_risk_commands" : true
}
}
Risk levels :
High : rm -rf, dd, mkfs, shutdown, reboot
Medium : sudo, curl, wget, chmod +x
Low : ls, cat, echo, git status
Sandbox Isolation
Tools execute within configured sandbox backend:
{
"security" : {
"sandbox" : {
"backend" : "auto" // landlock | firejail | bubblewrap | docker
}
}
}
Sandbox blocks:
Network access (unless allowed)
Filesystem access outside workspace
Subprocess spawning (unless allowed)
Syscall filtering (landlock)
Configuration
{
"tools" : {
"http_request" : {
"enabled" : true ,
"allowed_domains" : [ "api.github.com" , "*.example.com" ],
"max_response_size" : 1000000 ,
"timeout_secs" : 30
},
"web_search" : {
"enabled" : true ,
"search_provider" : "searxng" ,
"search_base_url" : "https://searx.example.com"
},
"shell" : {
"timeout_secs" : 60 ,
"max_output_bytes" : 100000
}
}
}
{
"tools" : {
"max_file_size_bytes" : 10485760 , // 10 MB
"shell_timeout_secs" : 60 ,
"shell_max_output_bytes" : 100000 ,
"web_fetch_max_chars" : 50000
}
}
const std = @import("std");
const Tool = @import("root.zig").Tool;
const ToolResult = @import("root.zig").ToolResult;
const JsonObjectMap = @import("root.zig").JsonObjectMap;
const getString = @import("root.zig").getString;
pub const MyTool = struct {
pub const tool_name = "my_tool";
pub const tool_description = "Does something useful";
pub const tool_params =
\\{"type":"object","properties":{
\\ "input":{"type":"string","description":"Input text"}
\\},"required":["input"]}
;
pub fn execute(
self: *MyTool,
allocator: std.mem.Allocator,
args: JsonObjectMap,
) anyerror!ToolResult {
const input = getString(args, "input") orelse
return ToolResult.fail("missing required parameter: input");
// Do something with input...
const output = try std.fmt.allocPrint(allocator, "Processed: {s}", .{input});
return .{ .success = true, .output = output };
}
pub fn tool(self: *MyTool) Tool {
return .{ .ptr = @ptrCast(self), .vtable = &vtable };
}
pub const vtable = @import("root.zig").ToolVTable(MyTool);
};
Add to src/tools/root.zig:
pub const my_tool = @import ( "my_tool.zig" );
pub fn allTools (...) ! [] Tool {
// ...
const mt = try allocator . create ( my_tool . MyTool );
mt . * = .{};
try list . append ( allocator , mt . tool ());
// ...
}
memory_store
Saves structured knowledge:
{
"key" : "alice_preference_editor" ,
"content" : "Alice prefers vim over emacs" ,
"category" : "core"
}
Categories:
core — long-term facts
daily — today’s context
conversation — session-specific
Custom categories (e.g., "project_alpha")
memory_recall
Hybrid search (FTS5 + vector similarity):
{
"query" : "What editor does Alice like?" ,
"limit" : 5
}
Returns scored results:
[
{
"key" : "alice_preference_editor" ,
"content" : "Alice prefers vim over emacs" ,
"score" : 0.92 ,
"timestamp" : "2026-03-01T12:34:56Z"
}
]
Vector search requires embedding provider configuration. Falls back to keyword-only (FTS5) if disabled.
Web Search Providers
The web_search tool supports multiple providers:
Provider API Key Required Features SearXNG No Self-hosted, privacy-first DuckDuckGo No Free, rate-limited Brave Yes Privacy-focused, fast Jina Yes AI-optimized search Perplexity Yes LLM-augmented search Tavily Yes Research-grade results Exa Yes Semantic search
Configuration:
{
"tools" : {
"http_request" : {
"search_provider" : "brave" ,
"search_fallback_providers" : [ "jina" , "duckduckgo" ]
}
}
}
Env vars: BRAVE_API_KEY, JINA_API_KEY, etc.
Supported Boards
Arduino (Uno, Mega, Nano)
Raspberry Pi (all models, GPIO via sysfs)
STM32/Nucleo (via probe-rs)
ESP32 (via serial)
Example: Read I2C Sensor
{
"tool" : "i2c" ,
"bus" : 1 ,
"address" : 0 x 48 ,
"register" : 0 x 00
}
Returns raw byte value from register.
Next Steps
Configuration Full tool configuration reference
Security Learn about tool security policies