Skip to main content
Every agent in Fabro has access to a set of built-in tools for interacting with the codebase and environment. Tools execute inside the agent’s sandbox — whether that’s the local machine, a Docker container, or a Daytona VM — so the same tool calls work identically regardless of provider.
The tools described on this page apply to the API backend (the default). When using the CLI backend, the external CLI tool (claude, codex, or gemini) provides its own tools — Fabro’s built-in tools are not used.

Core tools

These tools are registered for every provider profile:
ToolCategoryDescription
shellshellRun shell commands via /bin/bash -c
read_filereadRead file contents with optional offset and limit
write_filewriteCreate or overwrite a file
grepreadSearch file contents with regex patterns
globreadFind files by name pattern
web_searchshellSearch the web via Brave Search
web_fetchshellFetch and optionally summarize a URL

Provider-specific tools

Some tools are only available with certain LLM providers:
ToolProvidersDescription
edit_fileAnthropic, GeminiReplace a string in a file (find-and-replace)
apply_patchOpenAIApply a v4a-format patch to modify files
read_many_filesGeminiRead multiple files in a single call
list_dirGeminiList directory contents with depth control

Tool reference

shell

Executes a shell command via /bin/bash -c in the sandbox’s working directory.
ParameterTypeRequiredDescription
commandstringyesThe shell command to execute
timeout_msintegernoTimeout in milliseconds
descriptionstringnoDescription of what the command does
The timeout defaults to the provider’s configured value (10s for most providers, 120s for Anthropic) and is capped at the maximum (600s / 10 minutes). If the command exceeds the timeout, Fabro kills the process and returns a “Command timed out” message along with any output captured so far. The output includes the exit code, stdout, and stderr.

read_file

Reads a file and returns its contents with line numbers.
ParameterTypeRequiredDescription
file_pathstringyesAbsolute path to the file
offsetintegerno1-based line number to start reading from
limitintegernoNumber of lines to read (default: 2000)
Output is formatted with line numbers (e.g. 1 | fn main() {), making it easy for agents to reference specific lines when editing.

write_file

Creates or overwrites a file.
ParameterTypeRequiredDescription
file_pathstringyesAbsolute path to the file
contentstringyesContent to write
The read-before-write guardrail prevents writing to existing files that haven’t been read first. Writing to new files is always allowed.

edit_file

Replaces a string in an existing file. Available for Anthropic and Gemini providers.
ParameterTypeRequiredDescription
file_pathstringyesAbsolute path to the file
old_stringstringyesThe string to find
new_stringstringyesThe replacement string
replace_allbooleannoReplace all occurrences (default: false)
If old_string is not found, the tool returns an error. If multiple occurrences exist and replace_all is false, the tool returns an error asking for more context or to set replace_all. The tool reads the file internally before writing, so it satisfies the read-before-write guardrail automatically.

grep

Searches file contents with a regex pattern, powered by ripgrep in the sandbox.
ParameterTypeRequiredDescription
patternstringyesRegex pattern to search for
pathstringnoPath to search in (default: .)
glob_filterstringnoGlob pattern to filter which files are searched
case_insensitivebooleannoCase-insensitive search (default: false)
max_resultsintegernoMaximum number of results
Results are returned as file:line:content lines. Files that appear in grep results are marked as “read” for the read-before-write guardrail.

glob

Finds files matching a glob pattern.
ParameterTypeRequiredDescription
patternstringyesGlob pattern to match files (e.g. **/*.rs)
pathstringnoDirectory to search in (default: working directory)
Returns matching file paths, one per line.
Unlike grep, glob does not mark files as read for the read-before-write guardrail. To modify a file found via glob, the agent must read it first.
Searches the web using the Brave Search API.
ParameterTypeRequiredDescription
querystringyesSearch query
max_resultsintegernoMaximum results (default: 5, max: 20)
Requires the BRAVE_SEARCH_API_KEY environment variable. Returns numbered results with title, URL, and description.

web_fetch

Fetches content from a URL and optionally summarizes it with an LLM.
ParameterTypeRequiredDescription
urlstringyesURL to fetch (must be http:// or https://)
promptstringnoA question about the page content; returns a concise answer instead of the full page
timeout_msintegernoTimeout in milliseconds (default: 30000, max: 60000)
HTML content is automatically converted to Markdown (with script and style tags stripped). Output is capped at 100KB. When a prompt is provided and a summarizer model is configured, the fetched content is passed to a lightweight LLM call that returns a concise answer.

apply_patch

Applies a v4a-format patch to create, update, or delete files. Available for OpenAI providers.
ParameterTypeRequiredDescription
patchstringyesPatch content in v4a format
The v4a format uses *** Begin Patch / *** End Patch delimiters with *** Add File:, *** Delete File:, and *** Update File: operations.

read_many_files

Reads multiple files in a single tool call. Available for Gemini.
ParameterTypeRequiredDescription
pathsstring[]yesArray of absolute file paths
Returns each file’s contents prefixed with === path ===.

list_dir

Lists directory contents with optional depth control. Available for Gemini.
ParameterTypeRequiredDescription
pathstringyesDirectory path to list
depthintegernoDepth of listing (default: 1)
Directories are suffixed with / in the output.

Read-before-write guardrail

Fabro wraps every sandbox in a ReadBeforeWriteSandbox decorator that tracks which files the agent has seen. The rules are:
  1. Writing to a new file (one that doesn’t exist yet) is always allowed
  2. Writing to an existing file requires that the agent has previously read it via read_file or seen it in grep results
  3. Deleting an existing file follows the same rule as writing
If an agent attempts to write to an existing file it hasn’t read, the tool returns an error:
Cannot write to 'src/main.rs': file exists but has not been read.
Use read_file to read the file before writing to it.
This prevents agents from blindly overwriting files they haven’t inspected. The guardrail normalizes paths so that reading src/main.rs (relative) and /workspace/src/main.rs (absolute) both satisfy the check.

Tool execution

Parallel execution

When an LLM returns multiple tool calls in a single response, Fabro can execute them in parallel. Independent tool calls run concurrently, while the results are collected in order. If the agent session is cancelled, pending tool calls return a “Cancelled” error.

Argument validation

Before executing a tool, Fabro validates the arguments against the tool’s JSON Schema. Invalid arguments are rejected with a descriptive error before the tool executor runs.

Output truncation

Tool output is truncated before being stored in conversation history to prevent context window bloat. Each tool has default limits:
ToolCharacter limitTruncation mode
grep30,000Tail (keep end)
glob20,000Tail
edit_file10,000Tail
apply_patch10,000Tail
write_file1,000Tail
Other toolsNo default limitHead + tail
Limits can be overridden per-tool via SessionConfig.tool_output_limits.

Error handling

When a tool call fails, the error is returned to the agent as a tool result with an error flag — the agent loop continues. Tool errors do not fail the stage. The LLM sees the error message and decides how to respond: retry the call, try an alternative approach, or move on. Common error cases:
ErrorCause
Unknown toolThe agent called a tool that doesn’t exist
Argument validation failureArguments don’t match the tool’s JSON Schema
File not foundThe target file doesn’t exist
Command timeoutA shell command exceeded its timeout
Read-before-writeThe agent tried to write to a file it hasn’t read (see guardrail)

Timeouts

Shell commands have two timeout settings:
SettingDefaultDescription
default_command_timeout_ms10,000 (120,000 for Anthropic)Timeout when the agent doesn’t specify one
max_command_timeout_ms600,000 (10 minutes)Hard cap regardless of what the agent requests
The agent can request a specific timeout via the timeout_ms parameter, but it’s always capped at the maximum.

Extending with MCP

Additional tools can be added via MCP servers. MCP tools appear alongside built-in tools in the agent’s tool set and follow the same permission and execution model.

Further reading