FileSystem Backend

πŸ’‘Package: github.com/cloudwego/eino/adk/filesystem

Background and Goals

AI Agents need to interact with file systems (read, search, edit, execute commands), but different runtime environments have very different access methods: local disk, remote sandbox, in-memory simulation, object storage, etc. If each environment independently implements file operation logic, it leads to coupling between Middleware/Agent code and the underlying storage.

The filesystem.Backend interface solves this problem β€” as a unified file system operation protocol:

  1. Decouple storage from business logic β€” Middleware depends only on the interface, not the underlying implementation
  2. Pluggable replacement β€” Switching Backends enables running in different environments without modifying business code
  3. Testability β€” Built-in InMemoryBackend requires no real disk I/O
  4. Forward compatibility β€” All methods use struct parameters; adding new fields does not break existing implementations

Backend Interface

type Backend interface {
    LsInfo(ctx context.Context, req *LsInfoRequest) ([]FileInfo, error)
    Read(ctx context.Context, req *ReadRequest) (*FileContent, error)
    GrepRaw(ctx context.Context, req *GrepRequest) ([]GrepMatch, error)
    GlobInfo(ctx context.Context, req *GlobInfoRequest) ([]FileInfo, error)
    Write(ctx context.Context, req *WriteRequest) error
    Edit(ctx context.Context, req *EditRequest) error
}
MethodFunctionReturn
LsInfo
List files and directory info under the specified path
[]FileInfo
Read
Read file content, supports line-based pagination (offset + limit)
*FileContent
GrepRaw
Search for content matching a pattern in files
[]GrepMatch
GlobInfo
Find matching files by glob pattern
[]FileInfo
Write
Write or create a file
error
Edit
Replace string content in a file
error

Extension Interfaces

Shell / StreamingShell

Backends can optionally implement command execution capabilities. When a Backend implements Shell or StreamingShell, the Filesystem Middleware additionally registers the execute tool. The two are mutually exclusive and cannot be configured simultaneously.

type Shell interface {
    Execute(ctx context.Context, input *ExecuteRequest) (result *ExecuteResponse, err error)
}

type StreamingShell interface {
    ExecuteStreaming(ctx context.Context, input *ExecuteRequest) (result *schema.StreamReader[*ExecuteResponse], err error)
}

MultiModalReader

An optional extension interface supporting multi-modal file reading (images, PDFs, etc.), returning structured MultiFileContent.

type MultiModalReader interface {
    MultiModalRead(ctx context.Context, req *MultiModalReadRequest) (*MultiFileContent, error)
}

When a Backend implements this interface and the Middleware is configured with UseMultiModalRead = true, the read_file tool will use multi-modal reading.

Core Data Types

Request Types

TypeFieldsDescription
LsInfoRequest
Path string
Directory path to list
ReadRequest
FilePath string
Offset int
Limit int
File path; starting line number (1-based, <1 treated as 1); maximum lines to read (0=all)
MultiModalReadRequest
Embeds
ReadRequest
Pages string
Inherits all ReadRequest fields; Pages specifies PDF page range (e.g. "1-5", "3")
GrepRequest
Pattern string
Path string
Glob string
FileType string
CaseInsensitive bool
EnableMultiline bool
AfterLines int
BeforeLines int
Regex search pattern (ripgrep syntax); search directory; glob file filter; file type filter (e.g. "go", "py"); case-insensitive; enable multiline matching; show N lines after match; show N lines before match
GlobInfoRequest
Pattern string
Path string
Glob expression (supports
*
,
**
,
?
,
[abc]
); starting search directory
WriteRequest
FilePath string
Content string
Target file path; content to write
EditRequest
FilePath string
OldString string
NewString string
ReplaceAll bool
File path; exact string to replace (non-empty); replacement string; when false, OldString must appear exactly once in the file
ExecuteRequest
Command string
RunInBackendGround bool
Command string to execute; whether to run in background

Response Types

TypeFieldsDescription
FileInfo
Path string
IsDir bool
Size int64
ModifiedAt string
File/directory path; whether it is a directory; file size (bytes); last modified time (ISO 8601 format)
FileContent
Content string
Plain text content of the file
MultiFileContent
*FileContent
Parts []FileContentPart
Embeds FileContent; multi-modal output parts. Parts and FileContent are mutually exclusive: FileContent is ignored when Parts is non-empty
FileContentPart
Type FileContentPartType
MIMEType string
Data []byte
Content type (
"image"
or
"pdf"
); MIME type (e.g. "image/png"); raw binary data
GrepMatch
Content string
Path string
Line int
Matched line content; file path; 1-based line number
ExecuteResponse
Output string
ExitCode *int
Truncated bool
Command output content; exit code (pointer, may be nil); whether output was truncated

Constants

type FileContentPartType string

const (
    FileContentPartTypeImage FileContentPartType = "image"
    FileContentPartTypePDF   FileContentPartType = "pdf"
)

Built-in Implementation: InMemoryBackend

InMemoryBackend stores files in an in-memory map, primarily used for:

  • Unit testing β€” Test Agent/Middleware file operation logic without a real file system
  • Lightweight scenarios β€” Temporary file operations that don’t require persistence
  • Tool result offloading β€” The Filesystem Middleware’s large tool result offloading feature uses InMemoryBackend by default

Constructor

func NewInMemoryBackend() *InMemoryBackend

Zero-parameter constructor, returns an empty in-memory file system.

Usage Example

backend := filesystem.NewInMemoryBackend()
ctx := context.Background()

// Write
_ = backend.Write(ctx, &filesystem.WriteRequest{
    FilePath: "/example/test.txt",
    Content:  "Hello, World!\nLine 2\nLine 3",
})

// Read (paginated)
content, _ := backend.Read(ctx, &filesystem.ReadRequest{
    FilePath: "/example/test.txt",
    Offset:   1,
    Limit:    10,
})

// List directory
files, _ := backend.LsInfo(ctx, &filesystem.LsInfoRequest{Path: "/example"})

// Search (regex)
matches, _ := backend.GrepRaw(ctx, &filesystem.GrepRequest{
    Pattern:         "Hello",
    Path:            "/example",
    CaseInsensitive: true,
})

// Edit
_ = backend.Edit(ctx, &filesystem.EditRequest{
    FilePath:   "/example/test.txt",
    OldString:  "Hello",
    NewString:  "Hi",
    ReplaceAll: false,
})

Implementation Features

  • Thread-safe β€” Based on sync.RWMutex; read operations use read locks, write operations use write locks
  • GrepRaw parallel processing β€” Launches up to 10 workers for parallel matching during multi-file searches
  • Regex support β€” Supports full regex, case-insensitive ((?i) prefix), multiline mode
  • Context lines β€” GrepRaw supports BeforeLines/AfterLines to show context around matches
  • Glob matching β€” Uses the doublestar library to support ** recursive matching
  • FileType mapping β€” Built-in mapping table of 70+ file types to extensions (go, py, ts, rust, etc.)
  • Does not implement Shell β€” InMemoryBackend does not implement the Shell/StreamingShell interfaces

External Implementations

The following Backend implementations reside in the eino-ext repository:

  • Local Backend (github.com/cloudwego/eino-ext/adk/backend/local) β€” Local file system implementation, directly operates on the host disk
  • Ark Agentkit Sandbox (github.com/cloudwego/eino-ext/adk/backend/agentkit) β€” Volcengine Agentkit remote sandbox implementation

Implementation Comparison

FeatureInMemoryLocalAgentkit Sandbox
Execution modelIn-memoryLocal directRemote sandbox
Network dependencyNoneNoneRequired
Configuration complexityZero configZero configCredentials required
PersistenceNoYesYes
Shell supportNoShell + StreamingShellShell
MultiModalReaderNoImplementation-dependentImplementation-dependent
Use casesTests / temporary storageDevelopment / local environmentMulti-tenant / production

Custom Implementation

Implement the Backend interface to integrate custom storage. For command execution, additionally implement Shell or StreamingShell; for multi-modal reading, implement MultiModalReader.

type MyBackend struct { /* ... */ }

func (b *MyBackend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]filesystem.FileInfo, error) {
    // Custom implementation
}

func (b *MyBackend) Read(ctx context.Context, req *filesystem.ReadRequest) (*filesystem.FileContent, error) {
    // Custom implementation
}

func (b *MyBackend) GrepRaw(ctx context.Context, req *filesystem.GrepRequest) ([]filesystem.GrepMatch, error) {
    // Custom implementation
}

func (b *MyBackend) GlobInfo(ctx context.Context, req *filesystem.GlobInfoRequest) ([]filesystem.FileInfo, error) {
    // Custom implementation
}

func (b *MyBackend) Write(ctx context.Context, req *filesystem.WriteRequest) error {
    // Custom implementation
}

func (b *MyBackend) Edit(ctx context.Context, req *filesystem.EditRequest) error {
    // Custom implementation
}

// Optional: implement Shell
func (b *MyBackend) Execute(ctx context.Context, input *filesystem.ExecuteRequest) (*filesystem.ExecuteResponse, error) {
    // Custom implementation
}

// Optional: implement MultiModalReader
func (b *MyBackend) MultiModalRead(ctx context.Context, req *filesystem.MultiModalReadRequest) (*filesystem.MultiFileContent, error) {
    // Custom implementation
}