Skip to main content

Filesystem sandbox toolset for PydanticAI agents with LLM-friendly errors

Project description

pydantic-ai-filesystem-sandbox

Filesystem sandbox toolset for PydanticAI agents with LLM-friendly errors.

Why This Package?

When building LLM agents that interact with the filesystem, you need:

  1. Sandboxing - Restrict which directories the agent can access
  2. Read/Write Control - Fine-grained permissions per path
  3. LLM-Friendly Errors - Error messages that help the LLM correct its behavior
  4. Approval Integration - Works with human-in-the-loop approval flows

Architecture

Installation

pip install pydantic-ai-filesystem-sandbox

Quick Start

from pydantic_ai import Agent
from pydantic_ai_filesystem_sandbox import (
    FileSystemToolset,
    Sandbox,
    SandboxConfig,
    PathConfig,
)

# Configure sandbox paths
config = SandboxConfig(paths={
    "input": PathConfig(root="./data/input", mode="ro"),   # Read-only
    "output": PathConfig(root="./data/output", mode="rw"), # Read-write
})

# Create the sandbox (security boundary)
sandbox = Sandbox(config)

# Create the toolset (file I/O tools)
toolset = FileSystemToolset(sandbox)

# Use with PydanticAI agent
agent = Agent("openai:gpt-4", toolsets=[toolset])

Simple Usage

For simple cases, use the factory method:

from pydantic_ai_filesystem_sandbox import FileSystemToolset

# Single directory with read-write access
toolset = FileSystemToolset.create_default("./data", mode="rw")

agent = Agent("openai:gpt-4", toolsets=[toolset])

Configuration

See API Reference for complete details.

PathConfig Options

Option Type Default Description
root str required Root directory path
mode "ro" | "rw" "ro" Access mode
suffixes list[str] | None None Allowed file extensions (None = all)
max_file_bytes int | None None Maximum file size limit
write_approval bool True Require approval for writes
read_approval bool False Require approval for reads

Example Configuration

config = SandboxConfig(paths={
    # Read-only input - any file type
    "input": PathConfig(
        root="./data/input",
        mode="ro",
    ),
    # Read-write output - only markdown and text
    "output": PathConfig(
        root="./data/output",
        mode="rw",
        suffixes=[".md", ".txt"],
        max_file_bytes=1_000_000,  # 1MB limit
    ),
    # Config files - read-only, requires approval
    "config": PathConfig(
        root="./config",
        mode="ro",
        read_approval=True,
    ),
})

RootSandboxConfig (single root)

You can configure a sandbox as a single virtual / rooted at a host directory:

from pydantic_ai_filesystem_sandbox import Sandbox, SandboxConfig, RootSandboxConfig

config = SandboxConfig(root=RootSandboxConfig(root=".", readonly=False))
sandbox = Sandbox(config)

sandbox.resolve("/src/main.py")  # -> <cwd>/src/main.py

Deriving child sandboxes

Use Sandbox.derive() to create a restricted child sandbox. By default the child has no access unless you explicitly allow paths.

parent = Sandbox(config)

# Empty child (secure by default)
child = parent.derive()

# Allow read-only access to a subtree
reader = parent.derive(allow_read="output/reports")

# Allow read/write access to a subtree
writer = parent.derive(allow_write="output/reports")

Available Tools

The toolset provides seven tools to the agent:

read_file

Read a text file from the sandbox.

Path format: 'sandbox_name/relative/path'
Parameters:
  - path: str (required)
  - max_chars: int (default: 20,000)
  - offset: int (default: 0)

write_file

Write a text file to the sandbox (requires mode="rw"). Parent directories are created automatically.

Path format: 'sandbox_name/relative/path'
Parameters:
  - path: str (required)
  - content: str (required)

edit_file

Edit a file by replacing exact text (requires mode="rw").

Path format: 'sandbox_name/relative/path'
Parameters:
  - path: str (required)
  - old_text: str (required) - must match exactly and be unique
  - new_text: str (required)

delete_file

Delete a file from the sandbox (requires mode="rw").

Path format: 'sandbox_name/relative/path'
Parameters:
  - path: str (required)

move_file

Move or rename a file within the sandbox (requires mode="rw" for both source and destination). Parent directories are created automatically.

Path format: 'sandbox_name/relative/path'
Parameters:
  - source: str (required)
  - destination: str (required)

copy_file

Copy a file within the sandbox. Source can be read-only, destination requires mode="rw". Parent directories are created automatically.

Path format: 'sandbox_name/relative/path'
Parameters:
  - source: str (required)
  - destination: str (required)

list_files

List files matching a glob pattern.

Parameters:
  - path: str (default: "." for all sandboxes)
  - pattern: str (default: "**/*")

LLM-Friendly Errors

All errors include guidance on what IS allowed:

# PathNotInSandboxError
"Cannot access 'secret/file.txt': path is outside sandbox.
Readable paths: input, output"

# PathNotWritableError
"Cannot write to 'input/file.txt': path is read-only.
Writable paths: output"

# SuffixNotAllowedError
"Cannot access 'output/data.json': suffix '.json' not allowed.
Allowed suffixes: .md, .txt"

# FileTooLargeError
"Cannot read 'output/huge.txt': file too large (5,000,000 bytes).
Maximum allowed: 1,000,000 bytes"

# EditError
"Cannot edit 'output/file.txt': text not found in file.
Searched for: 'old text...'"

Approval Integration

Works with pydantic-ai-blocking-approval for human-in-the-loop:

from pydantic_ai_filesystem_sandbox import (
    ApprovableFileSystemToolset, Sandbox, SandboxConfig, PathConfig
)
from pydantic_ai_blocking_approval import ApprovalToolset, ApprovalController

# Create sandbox and toolset
config = SandboxConfig(paths={
    "output": PathConfig(root="./output", mode="rw", write_approval=True),
})
sandbox = Sandbox(config)
toolset = ApprovableFileSystemToolset(sandbox)

# Wrap with approval
controller = ApprovalController(mode="interactive")
approved_toolset = ApprovalToolset(
    inner=toolset,
    approval_callback=controller.approval_callback,
    memory=controller.memory,
)

agent = Agent(..., toolsets=[approved_toolset])

ApprovableFileSystemToolset extends FileSystemToolset with needs_approval() (returns ApprovalResult) and get_approval_description() for the approval UI.

Using the Sandbox Directly

The Sandbox class can be used independently for permission checking:

sandbox = Sandbox(config)

# Check permissions
if sandbox.can_write("output/file.txt"):
    resolved = sandbox.resolve("output/file.txt")
    # ... perform operation

# Query boundaries
print(sandbox.readable_roots)  # ["input", "output"]
print(sandbox.writable_roots)  # ["output"]

# Check approval requirements
sandbox.needs_write_approval("output/file.txt")  # True/False

ReadResult

The read_file tool returns a ReadResult object:

class ReadResult(BaseModel):
    content: str        # The file content read
    truncated: bool     # True if more content exists
    total_chars: int    # Total file size in characters
    offset: int         # Starting position used
    chars_read: int     # Characters actually returned

This allows agents to handle large files by reading in chunks:

# First read
result = toolset.read("input/large.txt", max_chars=10000)
if result.truncated:
    # Continue reading
    result2 = toolset.read("input/large.txt", max_chars=10000, offset=10000)

API Reference

See docs/api.md for full API documentation.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydantic_ai_filesystem_sandbox-0.8.0.tar.gz (198.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydantic_ai_filesystem_sandbox-0.8.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file pydantic_ai_filesystem_sandbox-0.8.0.tar.gz.

File metadata

File hashes

Hashes for pydantic_ai_filesystem_sandbox-0.8.0.tar.gz
Algorithm Hash digest
SHA256 be62fe6c4822bcba724dbacb458cf0021215897a9d8ecb5a69d9ad70e464254a
MD5 b48ae77310e8907990b3b5956e19fabb
BLAKE2b-256 6377afde898c0f9451fbba76ad84374f6fa5a67cd9c62d1935901adb7f4e695f

See more details on using hashes here.

File details

Details for the file pydantic_ai_filesystem_sandbox-0.8.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pydantic_ai_filesystem_sandbox-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a394c77a084d906c8d6fc80afe64c734ae9c2b5bff81c9c76fdeab4a0f872001
MD5 3280ccf29c95824db9d37cc4a32c17c1
BLAKE2b-256 bc3995c0ccdfbec1e199bf8186c1bbb4f50bd43f17f3ae6137139aff1ff4bb34

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page