The Tool Interface
Tools are defined by theTool<Input, Output, P> generic type in src/Tool.ts. The three type parameters are:
Core members of the
Tool interface:
Input schemas use Zod v4. The schema is converted to JSON Schema for the Anthropic API and validated locally before
call() is ever invoked.Available Tools
All tools are registered insrc/tools.ts and passed to QueryEngine. Some tools are conditionally included based on feature flags or environment variables.
File & Shell tools
File & Shell tools
Web & search tools
Web & search tools
Agent & collaboration tools
Agent & collaboration tools
Task & planning tools
Task & planning tools
Advanced & feature-gated tools
Advanced & feature-gated tools
Tool Registration
src/tools.ts assembles the complete tool list and exports it. Feature-gated tools are loaded via conditional require() so that Bun’s build system can eliminate them from the bundle entirely when the corresponding flag is inactive:
Tools array is passed directly into QueryEngine at construction time and forwarded into every ToolUseContext.
How a Tool Call Flows
1
LLM emits a tool_use block
The streamed API response includes one or more
tool_use content blocks, each with a name and a JSON input object.2
Input validation
The tool’s Zod
inputSchema parses the raw JSON input. If parsing fails, an error result is returned to the model immediately — call() is never invoked.3
validateInput() (optional)
If the tool defines
validateInput(), it runs next. This handles semantic validation that Zod can’t express (e.g., “this file path must be within the project root”).4
checkPermissions()
Every tool invocation goes through
checkPermissions(). The result flows into the toolPermission hook, which either auto-resolves based on the current permission mode or shows an interactive prompt. See Permissions & Safety.5
call() executes
With permission granted,
call() runs with the validated input and a ToolUseContext that provides access to app state, the abort controller, file cache, and more.6
Result returned to LLM
The tool’s
Output is serialized via mapToolResultToToolResultBlockParam() and appended as a tool_result message. The model is then re-queried.Tool Concurrency
Tools that declareisConcurrencySafe() returning true may be executed in parallel when the LLM emits multiple tool_use blocks in a single response. Read-only tools (e.g., GlobTool, GrepTool, FileReadTool) are typically concurrency-safe; mutating tools (e.g., FileWriteTool, BashTool) are not.
Deferred Tools
Tools withshouldDefer: true are sent to the model with defer_loading: true — their full schema is omitted from the initial system prompt. The model must call ToolSearchTool first to discover and load a deferred tool’s schema before it can be invoked. This keeps the initial context window smaller for projects with many MCP tools.
Tools with alwaysLoad: true are never deferred and always appear in the initial prompt, even when ToolSearchTool is active.