#1281·eino

[Bug] ADK virtual filesystem paths are cleaned with filepath, so InMemoryBackend and its middlewares return nothing on Windows

Author: newnewselfCreated Sep 12, 2026Updated Sep 12, 2026

Describe the bug

The ADK treats filesystem.Backend paths as virtual, slash-separated paths — InMemoryBackend's glob and prefix matching hard-code /:

go
// backend_inmemory.go
matchPath = strings.TrimPrefix(normalizedFilePath, basePath+"/")
matched, err := doublestar.Match(globPattern, matchPath)   // "/" is the separator
return filepath.Clean(path)                                 // ← but this is host-dependent

normalizePath (and path.Base / path.Ext call sites) uses path/filepath, so on Windows every stored path is rewritten with backslashes (/skills/my-skill/SKILL.md\skills\my-skill\SKILL.md) while the matching above still assumes /. Nothing matches, and the backend returns an empty result set instead of an error.

The same pattern runs through the ADK middlewares that read and write through the backend (filepath.Join, filepath.Dir, filepath.Base), so they also stop finding the files they just wrote.

To Reproduce

On Windows:

bash
$ go test ./adk/filesystem/... ./adk/middlewares/skill/... ./adk/middlewares/agentsmd/... \
           ./adk/middlewares/filesystem/... ./adk/middlewares/plantask/... \
           ./adk/middlewares/reduction/... ./adk/middlewares/agentsmd/...
FAIL github.com/cloudwego/eino/adk/filesystem
FAIL github.com/cloudwego/eino/adk/middlewares/agentsmd
FAIL github.com/cloudwego/eino/adk/middlewares/filesystem
FAIL github.com/cloudwego/eino/adk/middlewares/plantask
FAIL github.com/cloudwego/eino/adk/middlewares/reduction
FAIL github.com/cloudwego/eino/adk/middlewares/skill

adk/filesystem fails TestInMemoryBackend_LsInfo / TestInMemoryBackend_GlobInfo; the middlewares fail because a file written through the backend is not found again (file not found), e.g. plantask "Task created successfully" followed by TaskGet get Task #1 failed, err: file not found.

A minimal shape:

go
backend := filesystem.NewInMemoryBackend()
_ = backend.Write(ctx, &filesystem.WriteRequest{FilePath: "/tasks/1.json", Content: "{}"})
// LsInfo/GlobInfo on "/tasks" returns nothing on Windows, the file on Linux

Expected behavior

Paths of a virtual backend should not depend on the host OS. The in-memory backend and the ADK middlewares should use the slash-only path package for these paths (path.Clean/Base/Ext/Join/Dir), so behaviour is identical on every platform. filepath stays correct for the real-OS reads/writes that exist in adk/prebuilt/deep tests.

Version:

main (v0.9.x).

Environment:

$ go version
go version go1.26.2 windows/amd64

Additional context

  • CI runs ubuntu-latest only, where path.Clean == filepath.Clean, so this is invisible upstream and only affects Windows users.
  • InMemoryBackend is the only Backend implementation in-tree and is exported API, so this is not a test-only concern.
  • Secondary test-quality issue on the same path: adk/middlewares/skill/filesystem_backend_test.go indexes skills[0] without a length assertion, so the real failure surfaces as panic: index out of range instead of a clear assertion.

A PR follows that fixes the backend, the five middlewares that use it, and their test helpers.