作用
AbstractFilesystem 把 agent 对工作区的访问从「一定是本机磁盘」抽象成统一接口:ls / read / write / edit / grep / glob / upload / download。需要在隔离环境执行命令时,后端再实现 AbstractSandboxFilesystem,HarnessAgent 才会注册 ShellExecuteTool。
在 harness 里,文件系统承担三种不同但常混为一谈的职责:
- 工具面:
FilesystemTool(及可选的ShellExecuteTool)只认一个AbstractFilesystem实例;所有路径与执行都经此出口,便于替换实现。 - 工作区读写的物理落点:
WorkspaceManager读时「优先走 filesystem、未命中再回退本地」;写与上传一律走 filesystem。因此长期记忆、日流水账、会话日志等最终落在哪个介质上,由你选的 模式 决定。 - 多租户与隔离:
NamespaceFactory在每次操作中从RuntimeContext.userId等来源拼出路径前缀,使同一套代码在用户 / 会话 / 全局之间切换存储分片;RemoteFilesystemSpec与SandboxFilesystemSpec还把 IsolationScope 接到「共享 KV」或「沙箱状态键」上,与 Sandbox 的隔离叙事一致。
三种声明式模式
HarnessAgent.Builder 在 filesystem(...) 系列 中至多选一(与 abstractFilesystem(...) 互斥;后者为自带实现的逃生口,见下节):
默认未调用任何
filesystem(...) 时 与 显式 filesystem(new LocalFilesystemSpec()) 等价,即模式 3,根目录为 workspace、在宿主上提供 shell。
模式一:复合 + 存储(RemoteFilesystemSpec)
- 结构:
RemoteFilesystemSpec#toFilesystem组合出CompositeFilesystem:- 默认/未匹配的前缀 → 纯
LocalFilesystem(无ShellExecuteTool); - 配置的前缀(如默认的
MEMORY.md、memory/、agents/<agentId>/sessions/等 + 可addSharedPrefix)→RemoteFilesystem(BaseStore之上,由IsolationScope控制命名空间:SESSION / USER / AGENT / GLOBAL)。
- 默认/未匹配的前缀 → 纯
- 为何默认不用
LocalFilesystemWithShell:模式 1 的设计目标是跨节点一致的长记忆与日志,同时避免在宿主上开放 shell;需要 shell 时请用模式 2 或 3。
模式二:沙箱(SandboxFilesystemSpec)
- 见 沙箱(Sandbox)。要点:对外仍是
AbstractFilesystem+ 可选ShellExecuteTool(经AbstractSandboxFilesystem),但真实 IO/进程在SandboxClient侧;SandboxLifecycleHook在每次call周围 acquire/persist/release。
模式三:本机 + shell(LocalFilesystemSpec 或默认)
- 行为:
LocalFilesystemWithShell根目录为工作区,命令为宿主上的sh -c(可配超时、环境变量、virtualMode等),与模式 1 的「无 shell 本地根」有本质区别。
类层次与 ShellExecuteTool 注册
CompositeFilesystem只实现AbstractFilesystem,不实现AbstractSandboxFilesystem,因此不会注册ShellExecuteTool;若需组合路由且又要 shell,需自行用abstractFilesystem提供含 shell 的默认后端或选用沙箱/本机模式。read(filePath, offset, limit)中limit <= 0表示使用实现定义的「读默认行数」(本地与沙箱可能不同)。
各实现速查
BaseSandboxFilesystem 的默认实现策略
子类主要实现 execute / uploadFiles / downloadFiles / id 时,基类常把 ls/read/grep/glob/edit/write 转为远程 shell 与 Python3 片段(与旧版 filesystem.md 描述一致),便于在标准 Unix 环境快速落地。
NamespaceFactory 与多租户
["users", "alice"])。HarnessAgent 构建时可用 AtomicReference 与 RuntimeContext.userId 联动,使同一份 AbstractFilesystem 实例在不同用户下落在不同子树。
WorkspaceIndex 与 grep 语义(模式 1)
RemoteFilesystem 可选挂载一份本地 SQLite WorkspaceIndex(使用 RemoteFilesystemSpec 时自动构建),用于加速 ls / glob / exists / grep,避免全量 Store 扫描。该索引是尽力而为的,可能不包含其他副本节点写入的文件。
ls / glob / exists先查索引,无命中时回退到 Store 扫描,从而保留跨副本可见性。grep同样:先用索引枚举候选,索引返回 0 条匹配时回退到 Store 扫描。这样即使节点 B 的索引尚未感知节点 A 的写入,grep仍能在节点 B 上发现 A 写入的内容。- 若需要权威枚举(而非快速读路径),可通过
WorkspaceIndex.rebuildFromDisk(...)重建索引,或直接依赖 Store 回退路径。
配置示例
推荐:先选三种模式之一,再仅在需要时接触abstractFilesystem:
filesystem(…Spec) 互斥):
abstractFilesystem 或自建工厂中仍可使用 CompositeFilesystem + LocalFilesystemWithShell 等,但需自行保证安全边界与 ShellExecuteTool 是否应暴露。
相关文档
- 沙箱(Sandbox) — 沙箱模式原理、
SandboxStateStore、分布式 - 工具 —
FilesystemTool/ShellExecuteTool入参 - 工作区 —
WorkspaceManager与两层读 - 架构 — 与 Hook、RuntimeContext 的协作