FileSystem Backend

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

Background and Purpose

AI Agents need to interact with file systems (read, search, edit, execute commands), but access methods vary significantly across different runtime environments: local disk, remote sandboxes, in-memory simulation, object storage, etc. If file operation logic is implemented separately for each environment, it couples Middleware/Agent code to the underlying storage.

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

  1. Decouples storage from business logic β€” Middleware depends only on the interface, not the underlying implementation
  2. Pluggable replacement β€” Switch Backend to run in different environments without modifying business code
  3. Easy to test β€” Built-in InMemoryBackend requires no real disk I/O
  4. Forward compatible β€” All methods use struct parameters; new fields don’t 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
}
MethodFunctionReturns
LsInfo
List files and directories at 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 based on a glob pattern
[]FileInfo
Write
Write to 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 also implements Shell or StreamingShell, the Filesystem Middleware will additionally register an execute tool. These 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 that supports multi-modal file reading (images, PDFs, etc.), returning structured MultiFileContent.

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

When the Backend implements this interface and the Middleware has UseMultiModalRead = true configured, 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]
); search starting 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, requires OldString to appear only 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 modification 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: when Parts is non-empty, FileContent is ignored
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; 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 that 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 Characteristics

  • 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), and multiline mode
  • Context lines β€” GrepRaw supports BeforeLines/AfterLines to show context around matches
  • Glob matching β€” Uses the doublestar library for ** 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 interface

External Implementations

The following Backend implementations are located in the eino-ext repository:

  • Local Backend (github.com/cloudwego/eino-ext/adk/backend/local) β€” Local file system implementation that directly operates on the local 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 configRequires credentials
PersistenceNoYesYes
Shell supportNoShell + StreamingShellShell
MultiModalReaderNoDepends on implementationDepends on implementation
Use caseTesting / temporary storageDevelopment / local environmentMulti-tenant / production

Custom Implementation

Implement the Backend interface to integrate with 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
}