Skip to main content

作用

HarnessAgent 把 agent 对工作区的访问从”一定是本机磁盘”抽象成统一接口。所有文件工具(read_file / write_file / edit_file / grep_files / glob_files / list_files)和可选的 execute(shell)都从这个抽象走。 这样做让你能在三种部署模式之间切换,而不改 agent 代码
  • 本机 + shell —— 单进程、本地、信任环境;
  • 共享存储 —— 多副本 / 多 pod 共享同一份长期记忆;
  • 沙箱 —— 文件与命令都在隔离容器里执行,跨调用恢复同一份工作区。

三种声明式模式

HarnessAgent.Builder 上用 filesystem(...) 三选一(不调就是默认模式 3):
filesystem(...)abstractFilesystem(...) 互斥;后者是给完全自管文件系统的逃生口,正常用法不需要。

模式 1:共享存储(RemoteFilesystemSpec

适合”多副本,但用户的长期记忆要一致”。把一个 BaseStore 实现(Redis / JDBC / 内存)传进去,框架自动按路径前缀把工作区文件路由到这个 KV 存储:

所有配置项

内置路由规则

框架自动把以下路径路由到共享 KV,每个路径段各自独立命名空间,不会互相污染: 其余不在上表的路径落到本地 LocalFilesystem(无 shell)。

示例场景:多副本客服 agent

三个 pod 各跑一个 HarnessAgent,用同一个 Redis 做 BaseStore
  • 三个 pod 上本地磁盘的 AGENTS.md / knowledge/ / skills/ 作为只读模板(git 同步);
  • 运行时产物(MEMORY.mdmemory/、对话日志)自动存到 Redis,任意 pod 都能读到最新状态;
  • 用户 alice 的记忆在 KV 键 agents/customer-service/users/alice/memory/... 下。
这种模式不提供 shell——故意的:要 shell 请用模式 2(沙箱)或 3(本机)。

BaseStore 可用实现


模式 2:沙箱(SandboxFilesystemSpec 系列)

适合”代码会执行不可信操作、或要隔离生产环境”。所有文件操作和 shell 命令都发到沙箱里执行,宿主完全不受影响。

Docker 沙箱

DockerFilesystemSpec 所有配置项:

Kubernetes 沙箱(agent-sandbox)

Kubernetes 后端完全基于 agent-sandbox:沙箱 pod 由集群里的 agent-sandbox 控制器管理,镜像、资源、PVC 都声明在集群侧的 SandboxTemplate / SandboxWarmPool 里(不在 Java 侧配置),Java 侧通过 SandboxClaim 从预热池领取实例。使用前需要先安装 agent-sandbox 控制器并创建好模板和预热池。
KubernetesFilesystemSpec 主要配置项: apiUrl / gateway* 都不配时,默认用 kubectl port-forward 方式建立本地隧道(适合开发环境)。运行时镜像必须满足运行时镜像约束工作区持久化依赖模板里的 PVC 配置,详见沙箱 - Kubernetes 后端的状态保存

E2B 沙箱

Daytona 沙箱

AgentRun 沙箱(阿里云)

所有沙箱后端的公共配置(继承自 SandboxFilesystemSpec

快照策略

沙箱可以做快照,使下一次 call() 恢复之前的环境状态(安装的依赖、生成的文件等):

示例场景:编程助手(Docker + 本地快照)

工作区投影(Workspace Projection)

沙箱启动时,框架自动把宿主工作区里的”静态资产”打成 tar,注入(hydrate)到沙箱的 /workspace。这些静态资产包括:
  • AGENTS.md(人格文件)
  • skills/(技能目录)
  • subagents/(子 agent 声明)
  • knowledge/(知识库)
  • .skills-cache/(技能缓存)
投影按内容 SHA-256 做增量比对,没变的文件跳过 hydrate。可通过 workspaceProjectionRoots(List) 自定义包含哪些路径,或用 workspaceProjectionEnabled(false) 完全关闭。

模式 3:本机 + shell(默认)

什么都不写就是这个:工作区落到 ${cwd}/.agentscope/workspace/,shell 在宿主上跑:

所有配置项

路径解析策略(LocalFsMode

Overlay 文件系统

本机模式实际产出的是一个 OverlayFilesystem
  • 上层(读写):LocalFilesystemWithShell,根在 workspace,提供 shell;
  • 下层(只读):LocalFilesystem,根在 project
读取时先看 workspace,没有再退到 project(copy-on-write 语义)。shell 的 pwd 是 project 目录,所以 agent 执行 ls 看到的是项目文件。

项目可写模式(projectWritable

默认情况下,所有写入都落到 workspace——这对阅读/分析类场景足够,但如果 agent 的核心任务是生成代码(如写一个微服务),你会发现文件全写到了 .agentscope/workspace/ 而不是项目目录。 开启 projectWritable(true) 后,框架会根据路径自动路由写入目标:
读取行为不变——仍然是 workspace 优先、project 兜底。

示例场景:本地开发助手

agent 可以读写 /Users/alice/my-project/Users/alice/.config 下的文件,在 /Users/alice/my-project 下执行 shell 命令,但无法访问其他宿主目录。

IsolationScope —— 多用户与多副本怎么分桶

模式 1(共享存储)和模式 2(沙箱)都用同一个 IsolationScope 概念,决定谁和谁共享同一份状态

各 Scope 的降级规则

  • USER scope 下,如果 RuntimeContext.userId 为空,降级为 SESSION(按 sessionId 隔离)。
  • SESSION scope 下,如果 RuntimeContext.sessionId 为空,跳过状态查找,创建全新环境。
  • AGENT scope 的命名空间键由 agent name(build 时固定)决定,不会因缺少上下文字段而降级。

沙箱模式下的并发行为

IsolationScope 在沙箱模式下是顺序复用的共享,不是实时的实例共享。同一 scope key 的并发调用各自启动独立容器;每次调用结束时,最后写入的快照胜出。对 AGENT / GLOBAL 这种多用户共享 scope,如果需要串行化,使用 executionGuard(SandboxExecutionGuard) 做并发守卫。

示例:用 Scope 组合实现不同业务需求

场景 1:每个用户独立的编程沙箱,跨会话保留安装的依赖
场景 2:每个对话独立的一次性沙箱
场景 3:共享知识库的客服 agent(共享存储)

多用户隔离怎么实现

RuntimeContext.userId 是切多用户的钥匙: userId 不传的情况下走单租户默认,所有人共享一个根。

运行时数据 vs 静态资产

运行时数据(对话日志、tasks、memory)跟着 IsolationScope / userId 走,自动隔离。 静态资产AGENTS.mdtools.jsonknowledge/)对所有用户共享,按 userId 自动分区。差异化只能通过「用户覆盖目录」实现:

技能和工具在各模式下的行为

技能(Skills)

DynamicSkillMiddleware 在每轮推理前从技能仓库列表合并技能,渲染到 system prompt 里。技能文件的加载走 AbstractFilesystem 接口,所以在三种模式下透明工作: 四层优先级不变(低 → 高):projectGlobalSkillsDirskillRepositoryworkspace/skills/<userId>/skills/

文件工具(read_file / write_file / edit_file / …)

所有文件工具都通过 AbstractFilesystem 接口调用,每次操作传入当前 RuntimeContext,由文件系统后端决定实际读写位置。agent 代码完全感知不到模式差异。

Shell 执行(execute)

tools.json / MCP 服务器

tools.jsonbuild() 时一次性从工作区读取(走 WorkspaceManager,支持两层读),注册 MCP server 和 allow/deny 过滤。三种模式下行为一致——都是在 build 时读取配置,不受运行时 filesystem 模式影响。 在共享存储模式下,tools.json 也走”远端为上层、本地模板为下层”的 overlay:通过管理台修改 tools.json 后,需要重新 build agent 才能生效(MCP server 注册是一次性的)。

工作区里的两层读取

AGENTS.mdMEMORY.mdKNOWLEDGE.md 等关键文件在读取时有”两层兜底”:先看你配的文件系统后端,没有再退回本地磁盘。这对模式 1(共享存储)下的”模板文件” 很有用:第一个副本启动时本地有 AGENTS.md 模板,立刻可用;后续副本会从共享存储读出最新版本。 写入永远走配置的文件系统后端。

完全自管:abstractFilesystem(...)

如果三种模式都不合适,可以传一个完全自己实现的文件系统:
通常不需要——三种模式覆盖了 95% 的场景。

相关文档

  • 沙箱 — 模式 2 的运行时细节(容器生命周期、快照恢复链路)
  • 工作区 — 目录布局、加载机制、两层读取的”下层”来源
  • ContextAgentStateAgentStateStore(userId, sessionId) 寻址
  • 技能 — 四层合成、自学习闭环、<available_skills>
  • 工具read_file / write_file / execute 等参数
  • 架构 — 文件系统与运行时上下文如何协作