tools — Agent Tool Framework

Agent Tool Framework

Plugin architecture with 40+ tool implementations. Each tool defines a JSON schema, input validation, permission requirements, and execution logic. Tools are the “hands” of the AI agent — they read files, edit code, run commands, search, and interact with external services.

42
Tool Types
184
Files
~51k
Lines
TS
TypeScript

🔵 Plugin Architecture 🟢 JSON Schema Validation 🟡 Permission-Gated 🔴 Streaming Results

💡 What is this?

The tools module is the execution layer of the Claude Code agent. Think of it like specialized departments in a company: the File department (FileRead, FileWrite, FileEdit) handles all document work, the Operations department (BashTool, PowerShellTool) runs shell commands, the Research department (GrepTool, GlobTool, WebSearchTool) gathers information, and the Management department (AgentTool, TaskCreateTool) delegates work to sub-agents. Each department has a clear job description (JSON schema), security clearance (permissions), and a standard reporting format (ToolResult). The tools.ts registry acts as the company directory — it decides which departments are available for each session based on feature flags and permission rules.

Architecture

flowchart LR
  subgraph Base["Tool Base Layer"]
    ToolTS["Tool.ts\n(interface + buildTool)"]
    ToolDef["ToolDef\n(partial definition)"]
    ToolResult["ToolResult<T>\n(return type)"]
  end

  subgraph FileTools["File Tools"]
    FR["FileReadTool"]
    FE["FileEditTool"]
    FW["FileWriteTool"]
    NE["NotebookEditTool"]
  end

  subgraph ShellTools["Shell Tools"]
    BT["BashTool"]
    PS["PowerShellTool"]
    RP["REPLTool"]
  end

  subgraph SearchTools["Search Tools"]
    GR["GrepTool"]
    GL["GlobTool"]
    WS["WebSearchTool"]
    WF["WebFetchTool"]
    LS["LSPTool"]
  end

  subgraph AgentTools["Agent & Task Tools"]
    AT["AgentTool"]
    TC["TaskCreateTool"]
    SM["SendMessageTool"]
    SK["SkillTool"]
    TW["TodoWriteTool"]
  end

  subgraph MCPTools["MCP Integration"]
    MC["MCPTool"]
    LR2["ListMcpResourcesTool"]
    RR["ReadMcpResourceTool"]
  end

  ToolTS --> ToolDef
  ToolDef --> FileTools
  ToolDef --> ShellTools
  ToolDef --> SearchTools
  ToolDef --> AgentTools
  ToolDef --> MCPTools

  FileTools --> Registry["tools.ts\ngetAllBaseTools()"]
  ShellTools --> Registry
  SearchTools --> Registry
  AgentTools --> Registry
  MCPTools --> Registry

  Registry --> GetTools["getTools()\npermission filter"]
  GetTools --> QE["QueryEngine\nexecution loop"]
  QE --> ToolResult

Data Flow

sequenceDiagram
    participant Model as AI Model
    participant QE as QueryEngine
    participant Reg as Tool Registry
    participant Perm as Permission Check
    participant BT as BashTool
    participant Shell as Shell Process
    participant UI as Result Renderer

    Model->>QE: tool_use: BashTool { command: "ls -la" }
    QE->>Reg: findToolByName("BashTool")
    Reg-->>QE: BashTool instance
    QE->>BT: validateInput(input, context)
    BT-->>QE: { result: true }
    QE->>Perm: checkPermissions(input, ctx)
    Perm-->>QE: { behavior: "allow" }
    QE->>BT: call(input, context, canUseTool, msg, onProgress)
    BT->>Shell: exec("ls -la", { timeout: 60s })
    Shell-->>BT: stdout + exitCode
    BT->>BT: trackGitOperations(cmd, stdout, stderr)
    BT-->>QE: ToolResult { data: { stdout, exitCode } }
    QE->>UI: mapToolResultToToolResultBlockParam()
    UI-->>Model: tool_result content block

🚶 Step-by-Step Narrated Walkthrough

Follow a single FileEditTool operation as it flows through the entire tools pipeline:

  1. Model Emits tool_use — The AI model decides a file needs editing and emits a tool_use block with name: "FileEditTool", file_path, old_string, and new_string parameters.
  2. Tool Lookup — The QueryEngine calls findToolByName(tools, "FileEditTool") on the registry assembled by getTools(). The tool is found and returned.
  3. Input Validation — validateInput() runs synchronously: checks that file_path is non-empty, old_string differs from new_string, and the path doesn’t escape the working directory.
  4. Permission Check — checkPermissions() evaluates write permission rules. The path is matched against allow/deny patterns using matchWildcardPattern(). If the result is ask, a permission dialog appears.
  5. File Read — The tool reads the target file from disk. If the file exceeds the size limit (1 GB), it returns an error. If the file is not found, findSimilarFile() suggests alternatives.
  6. Search & Replace — The old_string is located in the file content. If an exact match fails, fuzzy matching kicks in. The replacement is applied, producing the new file content.
  7. Diff Generation — utils/gitDiff.ts computes a structured patch with context lines. Both a git-style diff and a structured patch object are generated for the result.
  8. File Write — The modified content is written to disk atomically. The file state cache is updated so subsequent edits have the correct baseline.
  9. Skill Activation — If the edited file matches a skill trigger pattern (via skills/loadSkillsDir.js), the associated skill is activated for follow-up actions.
  10. LSP Notification — If LSP is enabled, getLspServerManager() is notified of the file change so diagnostics update in real time.
  11. Result Assembly — A ToolResult is returned containing the diff output, line-change counts, and any new context messages. The result is sized-checked against maxResultSizeChars.
  12. UI Rendering — renderToolResultMessage() converts the result into a React component showing the diff with syntax highlighting. The model receives the serialized tool_result block.

Key Components

ComponentPathPurposeKey Detail
BashToolBashTool/Shell command execution18 files; AST security parsing, sandbox support, git tracking
FileEditToolFileEditTool/Diff-based file editing6 files; undo support, fuzzy matching, skill activation
FileReadToolFileReadTool/File content retrieval5 files; permission checks, size limits, path suggestions
FileWriteToolFileWriteTool/New file creation3 files; git diff output on create
GrepToolGrepTool/Regex text search via ripgrep2 files; context lines, output modes (content/files/count)
GlobToolGlobTool/File pattern matching2 files; glob syntax, recursive directory traversal
AgentToolAgentTool/Sub-agent spawning3 files; task decomposition, nested agent invocation
MCPToolMCPTool/MCP protocol bridge2 files; mcp__server__tool naming convention
WebFetchToolWebFetchTool/HTTP URL fetching4 files; preapproved domain checking
WebSearchToolWebSearchTool/Internet search1 file; Anthropic search API v20250305
REPLToolREPLTool/Interactive REPL environment2 files; Ant-only, wraps Bash/Read/Edit in VM
LSPToolLSPTool/Language Server Protocol integration3 files; IDE-like features, diagnostics, code navigation
SkillToolSkillTool/Custom plugin execution3 files; skill directory loading, trigger patterns
TaskCreateToolTaskCreateTool/Task creation (Todo v2)2 files; feature-gated via isTodoV2Enabled()
shared/shared/Cross-tool utilities2 files; git operation tracking, multi-agent spawning helpers

Sub-Modules

BashTool/

Shell command execution with security validation, sandboxing, and git operation tracking.

  • AST-based command parsing
  • Mode validation (sync/async/interactive)
  • Sandbox containerization

AgentTool/

Spawns nested sub-agents for complex task decomposition and parallel workstreams.

  • Sub-agent lifecycle management
  • Context isolation
  • Result aggregation

FileEditTool/

Diff-based file modification with undo support, fuzzy matching, and skill activation.

  • Search & replace with diff output
  • File state caching
  • LSP change notifications

FileReadTool/

Reads file contents with permission checks, size limits, and path suggestions on error.

  • Smart path resolution
  • Large file preview + disk path
  • Similar file suggestions

GrepTool/

Ripgrep-powered text search with regex support and multiple output modes.

  • Context lines (-A, -B, -C)
  • Glob filtering
  • Count & file-list modes

MCPTool/

Model Context Protocol bridge integrating external tool servers into the agent runtime.

  • Dynamic tool discovery
  • Server authentication
  • Resource listing & fetching

WebFetchTool/

HTTP URL fetching with preapproved domain lists and content extraction.

  • Domain allowlisting
  • Content-type handling
  • Response size limits

SkillTool/

Custom plugin/extension execution with directory-based skill loading.

  • Trigger pattern matching
  • Skill activation on file edits
  • Extension point for custom logic

shared/

Cross-tool utilities for git operation tracking and multi-agent spawning.

  • Git commit/PR detection
  • OTLP counter increments
  • Analytics event firing

Directory Map

Source tree for tools/
tools/
├── Tool.ts                        ← Core interface: Tool<I,O,P>, buildTool(), ToolDef
├── tools.ts                       ← Registry: getAllBaseTools(), getTools(), assembleToolPool()
├── utils.ts                       ← Message tagging helpers
├── AgentTool/                     ← Sub-agent spawning & task decomposition
├── AskUserQuestionTool/           ← Interactive user prompts
├── BashTool/                      ← Shell execution (18 files)
│   ├── BashTool.tsx               ← Main tool definition
│   ├── bashPermissions.ts         ← Security validation & permission rules
│   ├── modeValidation.ts          ← Sync/async/interactive mode checks
│   ├── sedValidation.ts           ← sed/perl regex injection prevention
│   └── ...                        ← Sandbox, timeout, git tracking
├── FileEditTool/                  ← Diff-based editing (6 files)
│   ├── FileEditTool.ts            ← Main definition with fuzzy matching
│   ├── constants.ts               ← Size limits (1GB max)
│   └── utils.ts                   ← Diff generation helpers
├── FileReadTool/                  ← File content retrieval (5 files)
├── FileWriteTool/                 ← New file creation (3 files)
├── GlobTool/                      ← Glob pattern matching (2 files)
├── GrepTool/                      ← Ripgrep text search (2 files)
├── LSPTool/                       ← Language Server Protocol (3 files)
├── MCPTool/                       ← MCP protocol bridge (2 files)
├── ListMcpResourcesTool/          ← MCP resource enumeration
├── ReadMcpResourceTool/           ← MCP resource fetching
├── McpAuthTool/                   ← MCP server authentication
├── NotebookEditTool/              ← Jupyter cell manipulation
├── PowerShellTool/                ← Windows PowerShell execution
├── REPLTool/                      ← Interactive REPL (Ant-only)
├── SkillTool/                     ← Custom plugin execution
├── TaskCreateTool/                ← Task creation (Todo v2)
├── TaskGetTool/                   ← Task retrieval
├── TaskListTool/                  ← Task enumeration with filtering
├── TaskUpdateTool/                ← Task status modification
├── TaskStopTool/                  ← Task cancellation
├── TaskOutputTool/                ← Background task streaming
├── TodoWriteTool/                 ← Quick todo creation
├── ToolSearchTool/                ← Deferred tool discovery
├── WebFetchTool/                  ← HTTP fetching (4 files)
├── WebSearchTool/                 ← Anthropic search API
├── SendMessageTool/               ← Async teammate messaging
├── TeamCreateTool/                ← Agent swarm creation
├── TeamDeleteTool/                ← Team deletion
├── ScheduleCronTool/              ← Cron job management
├── RemoteTriggerTool/             ← Remote task triggering
├── SleepTool/                     ← Execution pause (PROACTIVE mode)
├── SyntheticOutputTool/           ← Synthetic result generation
├── shared/                        ← Git tracking, multi-agent helpers
│   ├── gitOperationTracking.ts    ← Commit/PR/push regex detection
│   └── multiAgentSpawning.ts      ← Shared spawning logic
└── testing/                       ← Test utilities

Configuration & Knobs

KnobSourceDefaultEffect
maxResultSizeCharsTool.ts per tool100,000Max chars in tool result before spilling to disk
Bash timeoutBashTool/60 secondsMax execution time; killed on timeout
File size limitFileEditTool/constants.ts1 GBMax file size for read/edit operations
USER_TYPE=antEnvironmentunsetEnables Ant-only tools: REPLTool, ConfigTool
ENABLE_LSP_TOOLEnvironmentfalseActivates LSPTool for IDE-like code navigation
CLAUDE_CODE_SIMPLEEnvironmentfalseRestricts to Bash/Read/Edit tools only
isTodoV2Enabled()Feature flagfalseEnables Task* tools (Create, Get, Update, List, Stop)
isToolSearchEnabled()Feature flagfalseEnables ToolSearchTool for deferred tool discovery
PROACTIVE / KAIROSFeature flagfalseEnables SleepTool for deliberate execution pauses
AGENT_TRIGGERSFeature flagfalseEnables cron scheduling tools (Create/Delete/List)
Permission modeToolPermissionContextdefaultControls permission behavior: default, bypass, or ask
isConcurrencySafeTOOL_DEFAULTSfalseWhen false, tool calls are serialized; true allows parallel execution
shouldDeferPer tool definitionfalseWhen true, tool is hidden from initial prompt; discovered via ToolSearchTool
shouldUseSandbox()BashTool/autoContainerizes risky commands in sandbox environment

Core Types

// Tool.ts — Core interface (simplified)
export type Tool<Input, Output, P> = {
  readonly name: string
  readonly inputSchema: Input
  readonly inputJSONSchema?: ToolInputJSONSchema
  aliases?: string[]
  searchHint?: string
  maxResultSizeChars: number

  call(
    args: z.infer<Input>,
    context: ToolUseContext,
    canUseTool: CanUseToolFn,
    parentMessage: AssistantMessage,
    onProgress?: ToolCallProgress<P>,
  ): Promise<ToolResult<Output>>

  description(input: z.infer<Input>, options: DescOpts): Promise<string>
  validateInput(input: unknown, ctx: ToolUseContext): ValidationResult
  checkPermissions(input: z.infer<Input>, ctx: ToolPermCtx): Promise<PermResult>
  isEnabled(): boolean
  isReadOnly(input: z.infer<Input>): boolean
  isConcurrencySafe(input: z.infer<Input>): boolean
}

// Factory function
export function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D> {
  return { ...TOOL_DEFAULTS, userFacingName: () => def.name, ...def }
}

Tool Invocation Lifecycle

flowchart TD
    P["PENDING\ntool_use received"] --> V{"validateInput()"}
    V -->|invalid| ERR["Error Block\nto model"]
    V -->|valid| CP{"checkPermissions()"}
    CP -->|deny| REJ["Rejected\nrenderToolUseRejectedMessage()"]
    CP -->|ask| DLG["Permission Dialog"]
    DLG -->|approved| EXEC
    DLG -->|denied| REJ
    CP -->|allow| EXEC["tool.call()\nexecution"]
    EXEC -->|onProgress| PROG["Progress Events\nToolProgress stream"]
    EXEC -->|error| ERRMSG["renderToolUseErrorMessage()"]
    EXEC -->|success| RES["ToolResult<Output>"]
    RES --> MAP["mapToolResultToToolResultBlockParam()"]
    MAP --> RENDER["renderToolResultMessage()"]
    RENDER --> DONE["DONE\ntool_result to model"]