# How to Use the File Toolkit in aisuite: A Complete Guide to Filesystem Tools

> Master the aisuite file toolkit for filesystem operations. Learn to read, list, search, and modify files efficiently with this comprehensive guide.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: how-to-guide
- Published: 2026-06-16

---

**The aisuite file toolkit is a collection of filesystem tools that enables agents to read, list, search, and modify files within sandboxed root directories through the `files()` function in [`aisuite/toolkits/files.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py).**

The aisuite file toolkit provides controlled filesystem access for LLM-driven agents, allowing safe interaction with directories and files while enforcing strict security boundaries. As implemented in the `andrewyng/aisuite` repository, this toolkit wraps filesystem operations with safety guards and metadata, making it suitable for production agent workflows.

## Core Concepts and Configuration

### Root Directory Configuration

The entry point for the file toolkit is the public function **`files()`** defined in [`aisuite/toolkits/files.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py)【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L22-L31】. This function requires either a single `root` path or a list of `roots` where each entry can be a path string or a dictionary specifying `{"path": "...", "writable": bool}`.

The first root in the list serves as the **primary root** used for relative path resolution. According to the source code, the `FileToolkit` stores a reference to the supplied roots and recomputes resolved paths on each call, allowing dynamic modification of the root list without rebuilding the toolkit【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L39-L45】.

### Read-Only vs. Writable Operations

By default, the file toolkit exposes only read-only tools. Write-related tools—including `write_file`, `apply_unified_diff`, `apply_patch`, and `replace_in_file`—become available only when `allow_write=True` **or** when any supplied root is marked writable【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L27-L38】【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L48-L51】.

### Safety Guards and Limits

The toolkit implements multiple security measures to prevent abuse:

- **Path traversal protection**: Every access is resolved against declared roots and rejected if it escapes them【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L75-L85】.
- **Read size limits**: Reads are capped at `max_read_bytes` (default 200 kB) and searches at `max_search_bytes` (default 1 MB) to prevent denial-of-service attacks.
- **Ignore list filtering**: A default ignore list automatically excludes noisy directories like `git`, caches, and `node_modules`【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L9-L19】.

## Available File Tools

The `files()` function returns a `list` of callables wrapped as aisuite-compatible tools, each carrying `ToolMetadata` describing category, risk level, and capabilities【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L94-L108】.

### Listing and Reading Files

- **`list_files(path=".", pattern="*", recursive=True, max_results=100)`**: Returns a sorted list of relative file paths matching the glob pattern.
- **`read_file(path)`**: Reads a UTF-8 text file up to `max_read_bytes` and returns contents as a string.
- **`read_file_lines(path, start_line=1, max_lines=100)`**: Returns a dictionary with selected line range, total line count, and extracted text.

### Searching File Contents

- **`search_files(query, path=".", pattern="*", max_results=50)`**: Performs grep-style search across UTF-8 files under the root, returning a list of dictionaries containing `path`, `line`, and `text`.

### Writing and Modifying Files

These tools require writable roots:

- **`write_file(path, content, overwrite=True)`**: Writes or overwrites UTF-8 files within writable root boundaries.
- **`apply_unified_diff(diff)`**: Applies classic unified-diff patches (standard `diff -u` format).
- **`apply_patch(patch)`**: Applies Codex-style patches using BEGIN/END markers supporting add, delete, and update operations.
- **`replace_in_file(path, old, new, expected_replacements=1)`**: Performs string replacement, rejecting operations where match counts differ from expectations.

## Integration with aisuite Agents

### Attaching Tools to an Agent

When creating an `Agent` instance, pass the toolkit as the `tools` parameter:

```python
import aisuite as ai

agent = ai.Agent(
    model="openai:gpt-4",
    tools=ai.toolkits.files(root="/my/project", allow_write=True)
)

```

The `Agent` (or `ai.Client`) surfaces these wrapped callables to the LLM and enforces approval flows for write operations.

### Tool Metadata and Approval Flows

Each tool carries **metadata** including category (`filesystem`), risk level (`low` or `medium`), and capability lists. The tracing subsystem uses this metadata to surface tool usage in the UI and determine whether human approval is required before execution【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L120-L138】.

## Practical Code Examples

### Example 1: Read-Only File Operations

```python
from aisuite import toolkits

# Create a read-only toolkit rooted at /tmp/project

fs_tools = toolkits.files(root="/tmp/project")

# Access specific tools by name

list_files = next(t for t in fs_tools if t.__name__ == "list_files")
read_file = next(t for t in fs_tools if t.__name__ == "read_file")

# List all Python files under the root

py_files = list_files(pattern="*.py")
print("Python files:", py_files)

# Read the first file

content = read_file(py_files[0])
print("First file content:", content[:200])

```

### Example 2: Writable File Operations with Multiple Roots

```python
from aisuite import toolkits

# Configure two roots, one writable, one read-only

roots = [
    {"path": "/tmp/project", "writable": False},
    {"path": "/tmp/project/generated", "writable": True},
]

# Build the toolkit (write tools exposed because at least one root is writable)

fs_tools = toolkits.files(roots=roots, allow_write=True)

# Grab the write tool

write_file = next(t for t in fs_tools if t.__name__ == "write_file")

# Write a new file

new_path = write_file("generated/hello.txt", "Hello, aisuite!", overwrite=False)
print("Created:", new_path)

```

### Example 3: Applying a Unified Diff

```python
from aisuite import toolkits

fs = toolkits.files(root="/tmp/project", allow_write=True)
apply_diff = next(t for t in fs if t.__name__ == "apply_unified_diff")

# Simple diff that adds a line to README.md

diff = """--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # Project

 Some description
+Additional line added by diff
"""

result = apply_diff(diff)
print("Patch result:", result)

```

## Summary

- **Entry point**: The `files()` function in [`aisuite/toolkits/files.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py) creates a `FileToolkit` instance and wraps methods as aisuite-compatible tools.
- **Root configuration**: Supports single paths or multiple roots with writable flags; first root is primary for relative path resolution.
- **Security**: Path traversal prevention, size limits (200 kB read, 1 MB search), and automatic filtering of ignored directories protect against abuse.
- **Write access**: Disabled by default; enable via `allow_write=True` or writable root flags to expose `write_file`, `apply_unified_diff`, `apply_patch`, and `replace_in_file`.
- **Integration**: Pass the toolkit list directly to `Agent` tools parameter; metadata automatically handles risk classification and approval flows.

## Frequently Asked Questions

### How do I enable write access in the aisuite file toolkit?

Write access is enabled by either setting `allow_write=True` when calling `files()` or by marking at least one root as writable using `{"path": "...", "writable": True}`. When enabled, the toolkit exposes `write_file`, `apply_unified_diff`, `apply_patch`, and `replace_in_file` tools with appropriate metadata flags for approval workflows.

### What prevents the file toolkit from accessing files outside the root directory?

The toolkit implements path traversal protection in the `_resolve` method within [`aisuite/toolkits/files.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py), which validates every path against declared roots and rejects operations that attempt to escape the sandbox boundaries【https://github.com/andrewyng/aisuite/blob/main/aisuite/toolkits/files.py#L75-L85】.

### How do I apply a unified diff using the file toolkit?

First, create a writable toolkit instance with `allow_write=True`, then retrieve the `apply_unified_diff` tool from the returned list. Pass a valid unified diff string (standard `diff -u` format) to the tool, and it will apply the changes to the specified files under the root directory.

### What is the maximum file size the toolkit will read?

By default, the toolkit limits individual file reads to **200 kB** via `max_read_bytes`, while search operations are limited to **1 MB** via `max_search_bytes`. These defaults prevent memory exhaustion and can be adjusted by passing alternative values to the `files()` constructor when creating the toolkit.