API Reference

Built-in Tools

Complete reference for the BuiltinTools registry and every built-in tool: its name, description, JSON schema parameters, and behavior.


BuiltinTools

pub struct BuiltinTools { /* fields omitted */ }

Registry of built-in tools. Provides methods to access tool configurations and executors for registration with the tool system.

Constructors

all()

pub fn all() -> Self

Creates a registry containing all built-in tools. Returns 9 tools.

select()

pub fn select(tools: &[&str]) -> Result<Self, ToolError>

Creates a registry containing only the specified tools by name. Returns an error if an unknown tool name is provided.

let tools = BuiltinTools::select(&["read_file", "write_file", "glob"])?;

Query methods

available()

pub fn available() -> Vec<&'static str>

Lists all available built-in tool names (9 total).

get_config()

pub fn get_config(&self, name: &str) -> Option<&ToolConfig>

Returns the configuration for a specific tool.

get_executor()

pub fn get_executor(&self, name: &str) -> Option<Arc<BoxedToolExecutor>>

Returns the executor for a specific tool.

configs()

pub fn configs(&self) -> impl Iterator<Item = (&String, &ToolConfig)>

Returns an iterator over all registered tool configurations.

executors()

pub fn executors(&self) -> impl Iterator<Item = (&String, &Arc<BoxedToolExecutor>)>

Returns an iterator over all registered tool executors.

len()

pub fn len(&self) -> usize

Returns the number of registered tools.

is_empty()

pub fn is_empty(&self) -> bool

Returns true if no tools are registered.


Enabling built-in tools

There are several ways to make built-in tools available to the LLM.

// All builtins, auto-enabled on every prompt
ActonAI::builder()
    .with_builtins()
    .launch().await?;

// Specific builtins, auto-enabled
ActonAI::builder()
    .with_builtin_tools(&["read_file", "glob", "grep", "bash"])
    .launch().await?;

// All builtins, but require manual opt-in per prompt
ActonAI::builder()
    .with_builtins()
    .manual_builtins()
    .launch().await?;

On the prompt

When manual_builtins() is set, you must enable them on each prompt:

runtime.prompt("List files")
    .use_builtins()
    .collect()
    .await?;

See ActonAIBuilder and PromptBuilder for full details.


Tool reference

Each tool below lists its name (used by the LLM), description, JSON schema parameters, and behavior notes.

read_file

Reads file contents with line numbers.

Parameters:

{
  "type": "object",
  "properties": {
    "path": {
      "type": "string",
      "description": "Absolute path to the file to read"
    },
    "offset": {
      "type": "integer",
      "description": "Line number to start from (1-indexed, default: 1)",
      "minimum": 1
    },
    "limit": {
      "type": "integer",
      "description": "Maximum number of lines to read (default: 2000)",
      "minimum": 1
    }
  },
  "required": ["path"]
}

Returns: { content, total_lines, start_line, end_line, truncated }

Behavior:

  • Path must be absolute. Relative paths are rejected.
  • Content is returned with line numbers in cat -n style format.
  • Lines longer than 2000 characters are truncated.
  • Binary files are detected and rejected.
  • Path is validated by PathValidator for security (prevents path traversal).

write_file

Writes content to a file, creating parent directories if needed.

Parameters:

{
  "type": "object",
  "properties": {
    "path": {
      "type": "string",
      "description": "Absolute path to the file to write"
    },
    "content": {
      "type": "string",
      "description": "Content to write to the file"
    }
  },
  "required": ["path", "content"]
}

Returns: { success, path, bytes_written }

Behavior:

  • Path must be absolute.
  • Parent directories are created automatically if they do not exist.
  • Overwrites existing files.
  • Marked as requiring sandbox (sandboxed: true).

edit_file

Makes targeted string replacements in a file.

Parameters:

{
  "type": "object",
  "properties": {
    "path": {
      "type": "string",
      "description": "Absolute path to the file to edit"
    },
    "old_string": {
      "type": "string",
      "description": "Exact string to find and replace"
    },
    "new_string": {
      "type": "string",
      "description": "Replacement string"
    },
    "replace_all": {
      "type": "boolean",
      "description": "Replace all occurrences (default: false, which requires exactly one match)"
    }
  },
  "required": ["path", "old_string", "new_string"]
}

Returns: { success, path, replacements, diff }

Behavior:

  • Path must be absolute.
  • When replace_all is false (default), the old_string must appear exactly once in the file. If it appears multiple times, the tool returns an error suggesting to use replace_all: true or provide more context.
  • old_string and new_string must be different.
  • Returns a simple diff-style output showing what changed.
  • Marked as requiring sandbox (sandboxed: true).

list_directory

Lists directory contents with metadata (type, size, modified time).

Parameters:

{
  "type": "object",
  "properties": {
    "path": {
      "type": "string",
      "description": "Directory path to list"
    }
  },
  "required": ["path"]
}

Returns: { path, entries: [{ name, entry_type, size, modified }], count }

Behavior:

  • Path must be absolute.
  • Each entry includes its type ("file", "dir", or "symlink"), size (for files), and last modified time in ISO 8601 format.
  • Results are sorted alphabetically by name.

glob

Finds files matching a glob pattern.

Parameters:

{
  "type": "object",
  "properties": {
    "pattern": {
      "type": "string",
      "description": "Glob pattern to match (e.g., '**/*.rs', 'src/**/*.ts')"
    },
    "path": {
      "type": "string",
      "description": "Base directory to search in (default: current working directory)"
    }
  },
  "required": ["pattern"]
}

Returns: { matches: [string], count, truncated, pattern, base_path }

Behavior:

  • Supports recursive patterns with **.
  • Returns up to 1000 matching paths.
  • Results are sorted alphabetically.
  • If path is provided, it must be absolute.

grep

Searches file contents using regex patterns.

Parameters:

{
  "type": "object",
  "properties": {
    "pattern": {
      "type": "string",
      "description": "Regex pattern to search for"
    },
    "path": {
      "type": "string",
      "description": "File or directory to search in (default: current directory)"
    },
    "glob": {
      "type": "string",
      "description": "File pattern to filter files (e.g., '*.rs', '*.{ts,tsx}')"
    },
    "context_lines": {
      "type": "integer",
      "description": "Number of context lines before and after each match",
      "minimum": 0,
      "maximum": 10
    },
    "ignore_case": {
      "type": "boolean",
      "description": "Case insensitive search (default: false)"
    }
  },
  "required": ["pattern"]
}

Returns: { matches: [{ file, line, content, before, after }], count, files_searched, truncated, pattern }

Behavior:

  • Uses Rust's regex crate for pattern matching.
  • Returns up to 500 matches.
  • Skips hidden files (starting with .), binary files, and files larger than 10MB.
  • When searching a directory, walks the tree recursively.
  • Context lines (before/after) are included when context_lines > 0.
  • If path is provided, it must be absolute.

bash

Executes shell commands and captures output.

Parameters:

{
  "type": "object",
  "properties": {
    "command": {
      "type": "string",
      "description": "The shell command to execute"
    },
    "timeout": {
      "type": "integer",
      "description": "Timeout in seconds (default: 120, max: 600)",
      "minimum": 1,
      "maximum": 600
    },
    "cwd": {
      "type": "string",
      "description": "Absolute path to working directory. Only specify if you need a different directory than the current one."
    }
  },
  "required": ["command"]
}

Returns: { exit_code, stdout, stderr, success, truncated }

Behavior:

  • Runs the command via bash -c.
  • stdin is connected to /dev/null (no interactive input).
  • Output is captured and truncated at 1MB per stream (stdout/stderr).
  • If cwd is provided, it must be an absolute path to an existing directory.
  • Rejects obviously dangerous commands (rm -rf /, fork bombs, mkfs, dd to devices).
  • Marked as requiring sandbox (sandboxed: true).
  • Killed after the timeout expires.

Security

The bash tool executes arbitrary shell commands. In production, enable the Process Sandbox via with_process_sandbox() so each command runs in a subprocess with rlimits, a timeout, and (on Linux) best-effort landlock + seccomp filters.


calculate

Evaluates mathematical expressions using the fasteval crate.

Parameters:

{
  "type": "object",
  "properties": {
    "expression": {
      "type": "string",
      "description": "Mathematical expression to evaluate (e.g., '2 + 2', 'abs(-5)', 'sin(pi()/2)')"
    },
    "variables": {
      "type": "object",
      "description": "Optional variable bindings (e.g., {\"x\": 5, \"y\": 10})",
      "additionalProperties": {
        "type": "number"
      }
    }
  },
  "required": ["expression"]
}

Returns: { result, formatted, expression, is_special }

Behavior:

  • Supports arithmetic operators: +, -, *, /, ^, %.
  • Built-in functions: sin, cos, tan, log, abs, min, max, floor, ceil, round, sqrt, and more.
  • Constants via functions: pi(), e().
  • User-defined variables can be passed via the variables field.
  • Results are formatted nicely: integer results show as integers, floats as floats.
  • Special values (NaN, Infinity) are detected and flagged.
  • Expression length is capped at 1000 characters.
  • This is a safe math parser -- it does not execute arbitrary code.

web_fetch

Fetches content from a URL. Supports GET and POST methods with custom headers.

Parameters:

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "URL to fetch (must be http or https)"
    },
    "method": {
      "type": "string",
      "enum": ["GET", "POST"],
      "description": "HTTP method (default: GET)"
    },
    "headers": {
      "type": "object",
      "description": "Optional HTTP headers",
      "additionalProperties": {
        "type": "string"
      }
    },
    "body": {
      "type": "string",
      "description": "Optional request body (for POST requests)"
    },
    "timeout": {
      "type": "integer",
      "description": "Timeout in seconds (default: 30, max: 120)",
      "minimum": 1,
      "maximum": 120
    }
  },
  "required": ["url"]
}

Returns: { status_code, success, content_type, body, body_length, truncated, headers }

Behavior:

  • Only http and https schemes are allowed.
  • Blocks requests to localhost, 127.0.0.1, ::1, and private IP ranges (192.168.*, 10.*, 172.16-31.*) for security.
  • Response body is truncated at 5MB.
  • Default timeout is 30 seconds.
  • User agent is set to acton-ai/0.1.

update_plan

Maintains the model's structured plan for the current task. The only built-in that runs no code: it validates what the model sent, records it as the turn's plan, echoes back the normalized version, and broadcasts it. The tool's description teaches the model to skip planning for trivial tasks, never send a single-step plan, and update the plan right after completing each step.

Parameters:

{
  "type": "object",
  "properties": {
    "steps": {
      "type": "array",
      "description": "The complete ordered list of steps, resent in full on every call",
      "minItems": 2,
      "maxItems": 32,
      "items": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "What this step does, in a few words"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "in_progress", "completed"]
          }
        },
        "required": ["title", "status"]
      }
    },
    "note": {
      "type": "string",
      "description": "Optional one-line note about the plan or why it changed"
    }
  },
  "required": ["steps"]
}

Returns: { status: "recorded", plan, completed, total }

Behavior:

  • The model sends the whole plan every time, not a diff.
  • A plan must have 2--32 steps; each step's title is trimmed, non-empty, at most 200 characters, and distinct from every other step. A single-step plan is refused with a corrective message: split the work, or skip planning.
  • At most one step may be in_progress. A step with no status is pending.
  • A note is optional, at most 1000 characters; blank counts as absent.
  • A plan that breaks any of those rules is refused, and the reason goes back to the model as that call's tool result so it can correct itself. Nothing is broadcast for a refused plan, and the plan already recorded stands.
  • The prompt round loop owns the turn's current plan: it carries across every round of the tool loop, and the turn's final plan is returned on CollectedResponse::plan.
  • Every accepted plan is broadcast on the broker as a PlanUpdated message (defined in acton_ai::messages, alongside the other stream and lifecycle events) carrying the turn ID, the round's correlation ID, the tool call ID, and the validated Plan. The acton-ai chat REPL renders each update as an inline checklist. Subscribe an actor to render progress yourself:
// On the builder, before start() -- a later subscription is ignored.
builder.handle().subscribe::<PlanUpdated>().await;

builder.mutate_on::<PlanUpdated>(|actor, envelope| {
    let plan = &envelope.message().plan;
    println!("{}/{} steps done", plan.completed_count(), plan.step_count());
    Reply::ready()
});

Agent skill tools

These tools are auto-registered on every prompt when skills are loaded via ActonAIBuilder::with_skill_paths or a [skills] TOML section (or the --skill-dir CLI flag). If no skill paths are supplied, the tools are absent.

list_skills

Lists available agent skills with their descriptions.

Parameters:

{
  "type": "object",
  "properties": {
    "filter": {
      "type": "string",
      "description": "Optional filter pattern for skill names (case-insensitive substring match)"
    }
  }
}

Returns: { skills: [{ name, description, tags }], count }

Behavior:

  • Returns all registered skills, optionally filtered by name.
  • Use this to discover available skills before activating one.

activate_skill

Activates a skill and receives its full instructions.

Parameters:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Name of the skill to activate"
    }
  },
  "required": ["name"]
}

Returns: { name, description, instructions, path, tags }

Behavior:

  • Loads the full instructions for the named skill.
  • Call list_skills first to see what is available.
  • The instructions field contains the complete skill content that guides the agent.

Enabling skill tools

use acton_ai::tools::builtins::{spawn_skill_tool_actors, skill_tool_names};
use acton_ai::skills::SkillRegistry;
use std::sync::Arc;

let registry = Arc::new(SkillRegistry::new());
let skill_tools = spawn_skill_tool_actors(&mut runtime, registry).await;

// skill_tool_names() returns ["list_skills", "activate_skill"]

Tool summary table

ToolSandboxedCategoryDescription
read_fileNoFilesystemRead file contents with line numbers
write_fileYesFilesystemWrite content to files
edit_fileYesFilesystemTargeted string replacements
list_directoryNoFilesystemList directory contents with metadata
globNoFilesystemFind files matching glob patterns
grepNoFilesystemSearch file contents with regex
bashYesExecutionExecute shell commands
calculateNoComputationEvaluate math expressions
web_fetchNoWebFetch content from URLs
update_planNoCoordinationRecord the task plan and its progress
list_skillsNoSkillsList available agent skills
activate_skillNoSkillsActivate a skill for the agent

Sandboxed tools

Tools marked as sandboxed (write_file, edit_file, bash) run inside a ProcessSandbox child process when sandbox mode is enabled via with_process_sandbox(). Without sandbox mode, they still execute but directly in the parent process.

Previous
Conversation