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.
🔵 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:
- Model Emits tool_use — The AI model decides a file needs editing and emits a
tool_useblock withname: "FileEditTool",file_path,old_string, andnew_stringparameters. - Tool Lookup — The QueryEngine calls
findToolByName(tools, "FileEditTool")on the registry assembled bygetTools(). The tool is found and returned. - Input Validation —
validateInput()runs synchronously: checks thatfile_pathis non-empty,old_stringdiffers fromnew_string, and the path doesn’t escape the working directory. - Permission Check —
checkPermissions()evaluates write permission rules. The path is matched against allow/deny patterns usingmatchWildcardPattern(). If the result isask, a permission dialog appears. - 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. - Search & Replace — The
old_stringis located in the file content. If an exact match fails, fuzzy matching kicks in. The replacement is applied, producing the new file content. - Diff Generation —
utils/gitDiff.tscomputes a structured patch with context lines. Both a git-style diff and a structured patch object are generated for the result. - File Write — The modified content is written to disk atomically. The file state cache is updated so subsequent edits have the correct baseline.
- Skill Activation — If the edited file matches a skill trigger pattern (via
skills/loadSkillsDir.js), the associated skill is activated for follow-up actions. - LSP Notification — If LSP is enabled,
getLspServerManager()is notified of the file change so diagnostics update in real time. - Result Assembly — A
ToolResultis returned containing the diff output, line-change counts, and any new context messages. The result is sized-checked againstmaxResultSizeChars. - 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
| Component | Path | Purpose | Key Detail |
|---|---|---|---|
| BashTool | BashTool/ | Shell command execution | 18 files; AST security parsing, sandbox support, git tracking |
| FileEditTool | FileEditTool/ | Diff-based file editing | 6 files; undo support, fuzzy matching, skill activation |
| FileReadTool | FileReadTool/ | File content retrieval | 5 files; permission checks, size limits, path suggestions |
| FileWriteTool | FileWriteTool/ | New file creation | 3 files; git diff output on create |
| GrepTool | GrepTool/ | Regex text search via ripgrep | 2 files; context lines, output modes (content/files/count) |
| GlobTool | GlobTool/ | File pattern matching | 2 files; glob syntax, recursive directory traversal |
| AgentTool | AgentTool/ | Sub-agent spawning | 3 files; task decomposition, nested agent invocation |
| MCPTool | MCPTool/ | MCP protocol bridge | 2 files; mcp__server__tool naming convention |
| WebFetchTool | WebFetchTool/ | HTTP URL fetching | 4 files; preapproved domain checking |
| WebSearchTool | WebSearchTool/ | Internet search | 1 file; Anthropic search API v20250305 |
| REPLTool | REPLTool/ | Interactive REPL environment | 2 files; Ant-only, wraps Bash/Read/Edit in VM |
| LSPTool | LSPTool/ | Language Server Protocol integration | 3 files; IDE-like features, diagnostics, code navigation |
| SkillTool | SkillTool/ | Custom plugin execution | 3 files; skill directory loading, trigger patterns |
| TaskCreateTool | TaskCreateTool/ | Task creation (Todo v2) | 2 files; feature-gated via isTodoV2Enabled() |
| shared/ | shared/ | Cross-tool utilities | 2 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
| Knob | Source | Default | Effect |
|---|---|---|---|
maxResultSizeChars | Tool.ts per tool | 100,000 | Max chars in tool result before spilling to disk |
| Bash timeout | BashTool/ | 60 seconds | Max execution time; killed on timeout |
| File size limit | FileEditTool/constants.ts | 1 GB | Max file size for read/edit operations |
USER_TYPE=ant | Environment | unset | Enables Ant-only tools: REPLTool, ConfigTool |
ENABLE_LSP_TOOL | Environment | false | Activates LSPTool for IDE-like code navigation |
CLAUDE_CODE_SIMPLE | Environment | false | Restricts to Bash/Read/Edit tools only |
isTodoV2Enabled() | Feature flag | false | Enables Task* tools (Create, Get, Update, List, Stop) |
isToolSearchEnabled() | Feature flag | false | Enables ToolSearchTool for deferred tool discovery |
PROACTIVE / KAIROS | Feature flag | false | Enables SleepTool for deliberate execution pauses |
AGENT_TRIGGERS | Feature flag | false | Enables cron scheduling tools (Create/Delete/List) |
| Permission mode | ToolPermissionContext | default | Controls permission behavior: default, bypass, or ask |
isConcurrencySafe | TOOL_DEFAULTS | false | When false, tool calls are serialized; true allows parallel execution |
shouldDefer | Per tool definition | false | When true, tool is hidden from initial prompt; discovered via ToolSearchTool |
shouldUseSandbox() | BashTool/ | auto | Containerizes 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"]