Agents/Tool Use/ — Function Calling & Tool Infrastructure

60+ agent tools and the infrastructure for LLM function calling

The tool-use sub-module implements OpenClaw’s complete library of agent tools and the infrastructure that enables LLMs to call them. It handles tool call normalization, argument validation and repair, parameter type checking, action gating, error propagation, result truncation, and context-window guards — turning raw LLM function-call requests into safe, validated tool executions.

Each of the 60+ tools follows a consistent contract: validate inputs via readStringParam() and TypeBox schemas, check authorization via action gates, execute the operation, and return a structured result within configured size limits.

60+
Tools
6
Categories
~40k
Total Lines
TypeScript
Language

Function Calling Schema Validation Action Gating Error Recovery

📚 What is this & why does it exist?

The tool-use sub-module is the bridge between what an LLM wants to do and what actually happens. When an LLM decides it needs to fetch a web page, spawn a sub-agent, generate an image, or run a cron job, this module validates the request, checks permissions, repairs any malformed arguments, executes the tool, and returns the result in a format the LLM can understand. Without it, function calling would be unreliable and insecure.

It covers every stage from the moment the LLM emits a tool_call JSON object to the moment the result is injected back into the conversation context — including the surprisingly common case where the LLM produces syntactically broken JSON that needs automatic repair.

💡 Real-world analogy

Think of a Swiss Army knife with 60+ blades. Each blade is a different tool (web fetch, image generation, cron scheduling, etc.), but you can’t just yank any blade out — there’s a safety mechanism. The tool-use module is the spring-loaded locking system: it checks which blade you asked for, validates that your grip is correct (parameter validation), ensures you’re authorized to use that blade (action gating), and if you try to open the blade at a weird angle (malformed JSON), it auto-corrects your grip before the blade deploys. If something goes wrong, it safely folds the blade back and reports what happened.

Contents

Architecture

The tool execution pipeline is a linear chain with early-exit error branches. Every tool call from the LLM passes through normalization, argument repair, parameter validation, and action gating before reaching the actual tool handler. Results flow back through truncation and context guards before being returned to the LLM.

flowchart TD
  LLM["LLM Response"] --> NORM["Tool Call Normalization\nattempt.tool-call-normalization.ts"]
  NORM --> REPAIR["Argument Repair\nattempt.tool-call-argument-repair.ts"]
  REPAIR --> VALIDATE["Parameter Validation\nreadStringParam / TypeBox schemas"]
  VALIDATE --> GATE["Action Gate\ncreateActionGate()"]
  GATE --> DISPATCH["Tool Dispatch\nAnyAgentTool union routing"]
  DISPATCH --> EXEC["Tool Execution\nIndividual tool handlers"]
  EXEC --> TRUNC["Result Truncation\nDEFAULT_FETCH_MAX_CHARS"]
  TRUNC --> GUARD["Context Guard\nWindow boundary check"]
  GUARD --> LLM

Data Flow

The sequence diagram below shows the full lifecycle of a single tool call, from raw LLM output through normalization, gating, execution, and result delivery. Error branches (400 validation errors, 403 authorization errors) return structured error messages directly to the LLM.

sequenceDiagram
    participant LLM as LLM Provider
    participant Norm as Tool Call Normalizer
    participant Repair as Argument Repair
    participant Gate as Action Gate
    participant Tool as Tool Handler
    participant Trunc as Result Truncation
    participant Ctx as Context Guard

    LLM->>Norm: Raw tool_call JSON
    Norm->>Norm: Normalize argument keys
    Norm->>Repair: Normalized call
    alt Malformed JSON
        Repair->>Repair: Attempt JSON repair
    end
    Repair->>Gate: Valid tool call
    alt Permission denied
        Gate-->>LLM: ToolAuthorizationError (403)
    end
    Gate->>Tool: Authorized call
    Tool->>Tool: Execute (web-fetch, spawn, cron, etc.)
    alt Tool error
        Tool-->>LLM: ToolInputError (400)
    end
    Tool->>Trunc: Raw result
    Trunc->>Trunc: Enforce MAX_CHARS / MAX_BYTES
    Trunc->>Ctx: Truncated result
    Ctx->>Ctx: Check context window budget
    Ctx-->>LLM: Final tool result

Key Classes

The core types and functions below form the backbone of the tool infrastructure. AnyAgentTool is the discriminated union through which every tool call is routed; ToolInputError and ToolAuthorizationError are the standard error types; and createActionGate() is the factory that builds permission boundaries around individual tool actions.

Class / FunctionFilePurpose
AnyAgentTooltools/common.tsUnion type encompassing all 60+ agent tools for type-safe dispatch
ToolInputErrortools/common.ts400-level error for parameter validation failures; extends Error
ToolAuthorizationErrortools/common.ts403-level error for access control violations; extends ToolInputError
createActionGate()tools/common.tsFactory that creates tool-level allow/deny action gates
readStringParam()tools/common.tsValidates and reads string params with trim, required, and label options
SessionsSpawnToolSchemasessions-spawn-tool.tsTypeBox schema defining the spawn tool’s parameter shape
web-fetch.tstools/Fetches web pages with configurable char/byte limits and redirect caps
web-search.tstools/Performs web searches and returns structured results
sessions-spawn-tool.tstools/Spawns sub-agent sessions with runtime and sandbox mode selection
cron-tool.tstools/Manages scheduled tasks: add, update, remove, run, list, status
attempt.tool-call-normalization.tsrun/Normalizes tool call argument keys and formats before dispatch
attempt.tool-call-argument-repair.tsrun/Repairs malformed JSON in tool call arguments from LLM output
message-tool.tstools/Sends structured messages between agents and users
gateway-tool.tstools/Routes requests through the API gateway with auth propagation
subagents-tool.tstools/Manages sub-agent lifecycle: creation, delegation, result collection

Data Structures

Constants and type definitions that control tool behaviour at compile time and runtime. The discriminated union AnyAgentTool enables exhaustive switch statements; spawn runtime and sandbox mode literals constrain session creation; and fetch/error limit constants set safe defaults.

TypeNameDescription
typeAnyAgentToolDiscriminated union of all tool types for exhaustive pattern matching
interfaceStringParamOptionsOptions for readStringParam(): required, trim, label, allowEmpty
constOWNER_ONLY_TOOL_ERRORError constant returned when non-owners attempt owner-restricted tools
constSESSIONS_SPAWN_RUNTIMES["subagent", "acp"] — available spawn runtime backends
constSESSIONS_SPAWN_SANDBOX_MODES["inherit", "require"] — sandbox inheritance modes for spawned sessions
constCRON_ACTIONS["status", "list", "add", "update", "remove", "run", "runs", "wake"]
constDEFAULT_FETCH_MAX_CHARS50000 — character limit for web fetch tool results
constDEFAULT_FETCH_MAX_RESPONSE_BYTES2000000 — byte limit for web fetch responses
constDEFAULT_FETCH_MAX_REDIRECTS3 — maximum HTTP redirect hops
constDEFAULT_TOOL_ALLOWDefault allowlist of 16 tool actions permitted for agents
constACP_SPAWN_MODES["run", "session"] — ACP spawn execution modes
constACP_SPAWN_SANDBOX_MODES["inherit", "require"] — ACP sandbox enforcement modes

Tool Categories

Tools are organized into six functional categories. Each category groups tools that share a common domain, and tools within a category often share utility functions, error types, and configuration constants.

CategoryToolsDescription
Webweb-fetch, web-search, web-toolsHTTP fetching, search engine queries, and web utilities
Sessionsessions-spawn, sessions-send, sessions-list, sessions-history, sessions-yield, session-statusSub-agent session lifecycle management
Mediaimage, image-generate, canvas, pdf, ttsImage processing, generation, document handling, text-to-speech
Datanodes, nodes-commands, nodes-mediaStructured data node operations and media attachments
Systemcron, gateway, agent-step, agents-list, subagentsScheduling, API gateway, agent orchestration
Messagemessage-toolStructured message delivery between agents and channels

Interactions

The tool-use sub-module sits at the centre of the agent execution loop, interacting with nearly every other subsystem. Inbound interactions arrive as tool call requests from the LLM streaming pipeline; outbound interactions fan out to web APIs, session managers, sandboxes, and MCP servers.

DirectionPartnerInterfaceDescription
→LLM ProvidersFunction call protocolReceives tool call requests from streaming LLM responses
→Streaming Pipelineattempt.tsTool calls are extracted and dispatched from the streaming attempt loop
→Web APIsHTTP / fetchWeb-fetch and web-search tools make outbound HTTP requests
→Session ManagerSessionManagerSession tools (spawn, send, list) interact with session state
→Sandbox RuntimeDocker / SSHSandboxed execution tools delegate to container or SSH backends
→MCP ServersMCP protocolMCP bridge tools connect to external Model Context Protocol servers
←Auth SystemcreateActionGate()Action gates consult auth profiles for tool-level authorization
→Context EngineResult truncationTool results are truncated to fit within context window budgets

Configuration

Tool behaviour is controlled through a layered configuration system. Global defaults are defined as module-level constants, while per-tool overrides can be supplied at runtime. Fetch limits, error truncation thresholds, execution host strategies, and security policies are all configurable.

Knob / ParameterDefaultDescription
DEFAULT_FETCH_MAX_CHARS50000Maximum characters returned by the web-fetch tool
DEFAULT_FETCH_MAX_RESPONSE_BYTES2000000Maximum response body size in bytes for web-fetch
FETCH_MAX_RESPONSE_BYTES_MIN32000Floor value for configurable fetch byte limit
FETCH_MAX_RESPONSE_BYTES_MAX10000000Ceiling value for configurable fetch byte limit
DEFAULT_FETCH_MAX_REDIRECTS3Maximum HTTP redirect hops before aborting
DEFAULT_ERROR_MAX_CHARS4000Maximum characters in error messages returned to LLM
DEFAULT_ERROR_MAX_BYTES64000Maximum bytes in serialized error payloads
ExecToolDefaults.hostautoExecution host strategy: auto, local, or sandbox
ExecToolDefaults.askoffUser confirmation mode: off, on, or escalate
ExecToolDefaults.securityfullSecurity level: full, limited, or strict
DEFAULT_TOOL_ALLOW16 actionsDefault allowlist: exec, process, read, write, edit, apply_patch, image, sessions_list, sessions_history, sessions_send, sessions_spawn, sessions_yield, subagents, session_status
ACP_SPAWN_MODES["run","session"]Available ACP spawn execution modes
ACP_SPAWN_SANDBOX_MODES["inherit","require"]ACP sandbox enforcement modes for spawned processes

Directory Map

The tool source files are split across two directories: tools/ contains the individual tool implementations and shared utilities, while run/ contains the normalization and repair logic that preprocesses tool calls before dispatch.

Source tree for tool-use
tools/
├── common.ts                              ← AnyAgentTool, ToolInputError, createActionGate()
├── web-fetch.ts                           ← Web page fetching with limits
├── web-search.ts                          ← Search engine integration
├── web-tools.ts                           ← Shared web utilities
├── message-tool.ts                        ← Structured message delivery
├── sessions-spawn-tool.ts                 ← Sub-agent session spawning
├── sessions-send-tool.ts                  ← Send messages to sessions
├── sessions-list-tool.ts                  ← List active sessions
├── sessions-history-tool.ts               ← Session history retrieval
├── sessions-yield-tool.ts                 ← Yield control to parent
├── session-status-tool.ts                 ← Session status queries
├── cron-tool.ts                           ← Cron job management (8 actions)
├── pdf-tool.ts                            ← PDF document handling
├── image-tool.ts                          ← Image processing
├── image-generate-tool.ts                 ← Image generation
├── canvas-tool.ts                         ← Canvas rendering
├── tts-tool.ts                            ← Text-to-speech synthesis
├── nodes-tool.ts                          ← Data node operations
├── nodes-commands-tool.ts                 ← Node command execution
├── nodes-media-tool.ts                    ← Node media attachments
├── gateway-tool.ts                        ← API gateway routing
├── subagents-tool.ts                      ← Sub-agent lifecycle management
├── agents-list-tool.ts                    ← Agent enumeration
├── agent-step-tool.ts                     ← Single agent step execution
run/
├── attempt.tool-call-normalization.ts     ← Normalizes tool call arguments
└── attempt.tool-call-argument-repair.ts   ← Repairs malformed JSON in args

Deep-Dive Highlights

Core tool-use mechanisms have been extracted into dedicated focus pages for in-depth exploration. Each page covers one subsystem with diagrams, code walks, and configuration details.

Deep-Dive Pages

These focus pages drill into the three most complex subsystems within the tool-use module. Start with Function Calling if you want to understand the end-to-end tool invocation protocol; MCP Bridge if you are integrating external tool servers; Sandbox Execution if you are working on security boundaries.

Function Calling Focus

Tool call protocol, schema validation with TypeBox, and the argument repair pipeline that recovers from malformed LLM JSON output.

Extracted topic page

MCP Bridge Focus

Model Context Protocol server integration, tool runtime helpers, and the bridge that exposes external MCP tools to agents.

Extracted topic page

Sandbox Execution Focus

Sandboxed code execution infrastructure with Docker and SSH backends, security policies, and resource isolation.

Extracted topic page

Error Handling

The tool-use module defines a two-tier error hierarchy. ToolInputError (HTTP 400 equivalent) signals parameter validation failures — missing required fields, invalid types, or out-of-range values. ToolAuthorizationError (HTTP 403 equivalent) extends ToolInputError and signals permission violations when an agent tries to invoke an owner-restricted tool or an action blocked by the gate.

Both error types are caught by the attempt loop and returned to the LLM as structured error messages, capped at DEFAULT_ERROR_MAX_CHARS (4000) characters. This approach ensures the LLM can understand what went wrong and retry with corrected parameters, rather than receiving an opaque failure. The error hierarchy is intentionally modeled after HTTP status codes for familiarity.

Code Examples

Example: ToolInputError Usage Pattern

import { ToolInputError, ToolAuthorizationError } from "./tools/common";

function validateFetchUrl(url: string): void {
  if (!url || typeof url !== "string") {
    throw new ToolInputError("url parameter is required and must be a string");
  }
  const parsed = new URL(url);
  if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
    throw new ToolInputError(`Unsupported protocol: ${parsed.protocol}`);
  }
}

function checkToolAccess(tool: string, userId: string, ownerId: string): void {
  if (tool === "gateway" && userId !== ownerId) {
    throw new ToolAuthorizationError(OWNER_ONLY_TOOL_ERROR);
  }
}

Example: createActionGate() Factory Pattern

Action gates provide composable permission boundaries. An admin gate may allow all default tools, while a restricted user gate only permits read-only actions. Gates are checked synchronously before every tool dispatch.

import { createActionGate } from "./tools/common";

// Create a gate that allows only specific tool actions
const gate = createActionGate({
  allow: ["exec", "read", "write", "sessions_spawn"],
  deny: ["gateway", "subagents"],
});

// Gate returns true/false for each tool action
if (!gate.isAllowed("gateway")) {
  throw new ToolAuthorizationError("gateway tool is not permitted");
}

// Gates can be composed for layered permission checks
const adminGate = createActionGate({ allow: DEFAULT_TOOL_ALLOW });
const userGate = createActionGate({
  allow: ["read", "web_fetch", "web_search"],
  deny: ["exec", "write", "apply_patch"],
});

Example: Web Fetch Config Resolution

The fetch configuration resolver clamps user-supplied overrides within the allowed bounds, ensuring safety limits are always respected even when callers request extreme values.

const DEFAULT_FETCH_MAX_CHARS = 50_000;
const DEFAULT_FETCH_MAX_RESPONSE_BYTES = 2_000_000;
const DEFAULT_FETCH_MAX_REDIRECTS = 3;
const FETCH_MAX_RESPONSE_BYTES_MIN = 32_000;
const FETCH_MAX_RESPONSE_BYTES_MAX = 10_000_000;

function resolveFetchConfig(overrides?: Partial<FetchConfig>): FetchConfig {
  const maxBytes = Math.min(
    FETCH_MAX_RESPONSE_BYTES_MAX,
    Math.max(
      FETCH_MAX_RESPONSE_BYTES_MIN,
      overrides?.maxResponseBytes ?? DEFAULT_FETCH_MAX_RESPONSE_BYTES,
    ),
  );
  return {
    maxChars: overrides?.maxChars ?? DEFAULT_FETCH_MAX_CHARS,
    maxResponseBytes: maxBytes,
    maxRedirects: overrides?.maxRedirects ?? DEFAULT_FETCH_MAX_REDIRECTS,
  };
}