Decision: Files Module (L4)
Status: implemented Implemented: 2026-09-02
Problem
Users need file operations in sandboxes including read, write, upload, download, and directory watching.
Decision
api/files.py — FilesModule with:
- read(path, encoding) → str | bytes
- write(path, data, encoding) → None
- list(path) → list[FileInfo]
- upload(local_path, remote_path) → None (convenience: read local + write remote)
- download(remote_path, local_path) → None (convenience: read remote + write local)
- exists(path) → bool
- remove(path) → None
- make_dir(path) → None
- watch(path) → AsyncIterator[FileEvent] (streaming directory watch)
Large file support: chunked upload/download for files > 5MB.
API Design
class FilesModule:
async def read(self, path: str, encoding: str = "utf-8") -> str | bytes: ...
async def write(self, path: str, data: str | bytes, encoding: str = "utf-8") -> None: ...
async def list(self, path: str) -> list[FileInfo]: ...
async def upload(self, local_path: str, remote_path: str) -> None: ...
async def download(self, remote_path: str, local_path: str) -> None: ...
async def exists(self, path: str) -> bool: ...
async def remove(self, path: str) -> None: ...
async def make_dir(self, path: str) -> None: ...
def watch(self, path: str) -> AsyncIterator[FileEvent]: ...
Implementation
- Source:
src/agent_sandbox/api/files.py - Tests:
tests/test_api/test_files.py - Protocol dependency:
src/agent_sandbox/protocol/filesystem.py
Alternatives considered
- Separate Upload/Download classes — Over-abstraction for simple file ops
- pathlib-style interface — Too different from E2B API, breaks compatibility
Dependencies
protocol/filesystem.pyfor Connect protocol file operations
Test Strategy
- File CRUD operations with mock protocol
- Binary file handling (images, archives)
- Large file chunked transfer
- Directory watch event stream
Acceptance criteria
- ✅ Full file operations work (read/write/list/upload/download/exists/remove/mkdir)
- ✅ Binary files handled correctly
- ✅ Watch produces real-time events