Local Filesystem

Local Backend

Package: github.com/cloudwego/eino-ext/adk/backend/local

πŸ’‘ eino v0.8.0+ requires local backend v0.2.1 or above.

Local Backend is the local implementation of Eino ADK FileSystem, directly operating the local file system. It implements both the filesystem.Backend (file operations) and filesystem.StreamingShell (streaming command execution) interfaces.

Core features: Zero configuration, native performance, enforced absolute paths, streaming command execution, optional command validation.


Installation

go get github.com/cloudwego/eino-ext/adk/backend/local

Configuration

type Config struct {
    // Optional: Command validation function for security control of ExecuteStreaming.
    // Rejects execution when returning non-nil error.
    ValidateCommand func(string) error
}

Quick Start

backend, err := local.NewBackend(ctx, &local.Config{})

// Write file (must be absolute path; overwrites if file already exists)
err = backend.Write(ctx, &filesystem.WriteRequest{
    FilePath: "/tmp/hello.txt",
    Content:  "Hello, Local Backend!",
})

// Read file (supports line-level pagination)
fc, err := backend.Read(ctx, &filesystem.ReadRequest{
    FilePath: "/tmp/hello.txt",
    Offset:   1,   // Starting line number (1-based)
    Limit:    50,  // Maximum number of lines, 0 means all
})

Integration with Agent

import (
    "github.com/cloudwego/eino/adk"
    fsMiddleware "github.com/cloudwego/eino/adk/middlewares/filesystem"
    "github.com/cloudwego/eino-ext/adk/backend/local"
)

backend, _ := local.NewBackend(ctx, &local.Config{})

middleware, _ := fsMiddleware.New(ctx, &fsMiddleware.Config{
    Backend:        backend, // Required: registers ls/read/write/edit/glob/grep tools
    StreamingShell: backend, // Optional: registers streaming execute tool
})

agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Model:    chatModel,
    Handlers: []adk.ChatModelAgentMiddleware{middleware},
})

πŸ’‘ In the middleware Config, Shell and StreamingShell are mutually exclusive. Local Backend only implements StreamingShell (streaming command execution), not the non-streaming Shell.


Implemented Interfaces and Methods

filesystem.Backend

MethodSignatureDescription
LsInfo
(ctx, *LsInfoRequest) ([]FileInfo, error)
List directory contents
Read
(ctx, *ReadRequest) (*FileContent, error)
Read file, supports line-level pagination (Offset 1-based, Limit 0=all)
Write
(ctx, *WriteRequest) error
Write file; auto-creates parent directories; overwrites if file already exists
Edit
(ctx, *EditRequest) error
String replacement; supports
ReplaceAll
; errors when
OldString
is not unique (in non-ReplaceAll mode)
GrepRaw
(ctx, *GrepRequest) ([]GrepMatch, error)
Search based on ripgrep, supports full regex syntax; supports case-insensitive, multiline matching, context lines
GlobInfo
(ctx, *GlobInfoRequest) ([]FileInfo, error)
Glob pattern file matching, supports
*
/
**
/
?
/
[abc]

filesystem.StreamingShell

MethodSignatureDescription
ExecuteStreaming
(ctx, *ExecuteRequest) (*StreamReader[*ExecuteResponse], error)
Stream shell command execution with real-time output; supports background execution (
RunInBackendGround
)

Usage Examples

Content Search (Regex)

matches, _ := backend.GrepRaw(ctx, &filesystem.GrepRequest{
    Path:    "/home/user/project",
    Pattern: "TODO|FIXME",       // ripgrep regex syntax
    Glob:    "*.go",
    CaseInsensitive: true,
})

Edit File

backend.Edit(ctx, &filesystem.EditRequest{
    FilePath:   "/tmp/file.txt",
    OldString:  "old text",
    NewString:  "new text",
    ReplaceAll: true,
})

Streaming Command Execution

reader, _ := backend.ExecuteStreaming(ctx, &filesystem.ExecuteRequest{
    Command: "tail -f /var/log/app.log",
})
for {
    resp, err := reader.Recv()
    if err == io.EOF {
        break
    }
    fmt.Print(resp.Output)
}

With Command Validation

backend, _ := local.NewBackend(ctx, &local.Config{
    ValidateCommand: func(cmd string) error {
        allowed := map[string]bool{"ls": true, "cat": true, "grep": true}
        parts := strings.Fields(cmd)
        if len(parts) == 0 || !allowed[parts[0]] {
            return fmt.Errorf("command not allowed: %s", parts[0])
        }
        return nil
    },
})

Path Requirements

All file paths must be absolute paths (starting with /). Relative paths can be converted using filepath.Abs().


Comparison with Agentkit Backend

FeatureLocalAgentkit
Execution modelLocal directRemote sandbox
Network dependencyNoneRequired
Configuration complexityZero configurationRequires credentials
Security modelOS permissions + ValidateCommandIsolated sandbox
Streaming outputSupported (StreamingShell)Not supported
Platform supportUnix/Linux/macOSAny
Use caseDevelopment/local environmentsMulti-tenant/production environments

FAQ

Q: Does GrepRaw support regex?

A: Yes. It uses ripgrep (rg) under the hood, supporting full regex syntax. The system must have ripgrep installed; otherwise it reports ripgrep (rg) is not installed or not in PATH. See https://github.com/BurntSushi/ripgrep#installation for installation instructions.

Q: Does Write create or overwrite?

A: Overwrite. Write uses O_CREATE|O_TRUNC flags β€” if the file exists, it overwrites the content; if not, it creates the file (including auto-creating parent directories).

Q: Is Windows supported?

A: No. ExecuteStreaming depends on /bin/sh. File operations themselves can run on any platform, but command execution is limited to Unix-like systems.

Q: Does Local Backend support non-streaming Execute?

A: No. Local only implements StreamingShell (ExecuteStreaming), not Shell (Execute). In the middleware Config, Shell and StreamingShell are mutually exclusive β€” choose one.