RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /How-to
  5. /How to Add File System Operations as Agent Tools
HOW-TO · RAG

How to Add File System Operations as Agent Tools

intermediate·20 min·By Fredoline Eruo
Target environment
Ubuntu 24.04 · Ollama 0.4.x
PREREQUISITES

Agent with tool use, Python os/pathlib, Python 3.10+

What this does

File system tools let agents read, write, list, and organize files on the local machine — enabling tasks like saving search results, reading configuration files, and generating reports.

Steps

  • Create a read_file tool. Restrict to an allowed directory for security.
from langchain.tools import tool
import os

ALLOWED_DIR = os.path.expanduser("~/agent_workspace")

def safe_path(path: str) -> str:
    full = os.path.abspath(os.path.join(ALLOWED_DIR, path))
    if not full.startswith(ALLOWED_DIR):
        raise PermissionError(f"Access denied: {path}")
    return full

@tool
def read_file(path: str) -> str:
    """Read the contents of a file within the workspace."""
    safe = safe_path(path)
    if not os.path.exists(safe):
        return f"Error: file not found: {path}"
    with open(safe, "r") as f:
        return f.read()
  • Create a write_file tool.
@tool
def write_file(path: str, content: str) -> str:
    """Write content to a file within the workspace."""
    safe = safe_path(path)
    os.makedirs(os.path.dirname(safe), exist_ok=True)
    with open(safe, "w") as f:
        f.write(content)
    return f"Written {len(content)} bytes to {path}"
  • Create list_directory and file_info tools.
@tool
def list_directory(path: str = ".") -> str:
    """List files and directories in the workspace."""
    safe = safe_path(path)
    items = os.listdir(safe)
    result = []
    for item in sorted(items):
        full = os.path.join(safe, item)
        size = os.path.getsize(full) if os.path.isfile(full) else 0
        kind = "📄" if os.path.isfile(full) else "📁"
        result.append(f"{kind} {item} ({size} bytes)")
    return "\n".join(result)

@tool
def file_info(path: str) -> str:
    """Get metadata about a file."""
    safe = safe_path(path)
    stat = os.stat(safe)
    return f"Size: {stat.st_size} bytes\nModified: {stat.st_mtime}"
  • Add a search-in-files tool.
@tool
def search_files(pattern: str, path: str = ".") -> str:
    """Search for text pattern in workspace files."""
    safe = safe_path(path)
    matches = []
    for root, _, files in os.walk(safe):
        for fname in files:
            fpath = os.path.join(root, fname)
            try:
                with open(fpath) as f:
                    for i, line in enumerate(f, 1):
                        if pattern in line:
                            rel = os.path.relpath(fpath, ALLOWED_DIR)
                            matches.append(f"{rel}:{i}: {line.strip()[:100]}")
            except (UnicodeDecodeError, PermissionError):
                continue
    return "\n".join(matches[:50]) or "No matches found."
  • Register all file tools with the agent.
file_tools = [read_file, write_file, list_directory, file_info, search_files]
registry = ToolRegistry()
for t in file_tools:
    registry.register(t)

Verification

python -c "
import os
p = os.path.abspath(os.path.join(os.path.expanduser('~'), 'test.txt'))
print(p.startswith(os.path.expanduser('~')))
# Expected: True
"

Common failures

  • Path traversal vulnerability. A malicious path = "../../etc/passwd" escapes the workspace. Always normalize with os.path.abspath and check the prefix.
  • Binary file read errors. Reading a binary file as text raises UnicodeDecodeError. Detect binary files by extension or catch the exception.
  • Disk space exhaustion. The agent could write unlimited data. Implement a quota or max file size check before writing.
  • Version mismatch - The installed package or runtime differs from the command shown; check the version first and rerun the smallest verification command.
  • Local environment drift - Another service, virtual environment, model, or path is being used; print the active binary path and configuration before changing the guide steps.

Related guides

  • How to Implement Secure File Operations for Agents
  • How to Build Custom Tools for Agents
← All how-to guidesCourses →