Skip to main content

Role

HarnessAgent abstracts the agent’s view of the workspace away from “must be local disk” into a uniform interface. All file tools (read_file / write_file / edit_file / grep_files / glob_files / list_files) and the optional execute (shell) go through this abstraction. The payoff: you can switch between three deployment modes without changing agent code:
  • Local + shell — single process, local, trusted env;
  • Shared store — multiple replicas / pods share the same long-term memory;
  • Sandbox — files and commands run in an isolated container; the same workspace state is restored across calls.

Three declarative modes

Pick one with filesystem(...) on HarnessAgent.Builder (no call = mode 3 by default):
filesystem(...) is mutually exclusive with abstractFilesystem(...); the latter is an escape hatch for fully self-managed filesystems and rarely needed.

Mode 1: shared store (RemoteFilesystemSpec)

For “multi-replica, but the user’s long-term memory must stay in sync”. Pass a BaseStore implementation (Redis / JDBC / in-memory) and the framework automatically routes workspace files into the KV store by path prefix:

All configuration options

Built-in routing rules

The framework automatically routes the following paths to the shared KV, each in its own namespace segment to prevent key collisions: Paths not in the table above fall through to a local LocalFilesystem (no shell).

Example: multi-replica customer-service agent

Three pods each running a HarnessAgent, sharing one Redis as the BaseStore:
  • Each pod’s local AGENTS.md / knowledge/ / skills/ serve as read-only templates (git-synced);
  • Runtime outputs (MEMORY.md, memory/, conversation logs) are stored in Redis automatically — any pod reads the latest state;
  • Alice’s memory lives under KV key agents/customer-service/users/alice/memory/....
This mode does not provide shell — on purpose: for shell, use mode 2 (sandbox) or 3 (local).

Available BaseStore implementations


Mode 2: sandbox (SandboxFilesystemSpec family)

For “code may run untrusted operations” or “isolate from the production host”. Every file op and shell command goes to the sandbox; the host is untouched.

Docker sandbox

DockerFilesystemSpec — all options:

Kubernetes sandbox (agent-sandbox)

The Kubernetes store is fully based on agent-sandbox: sandbox pods are managed by the agent-sandbox controller in your cluster, and image, resources, and PVCs are all declared cluster-side in a SandboxTemplate / SandboxWarmPool (not configured from Java). The Java side claims instances from the warm pool via SandboxClaim. Install the agent-sandbox controller and create the template and warm pool before use.
Main KubernetesFilesystemSpec options: When neither apiUrl nor gateway* is set, a local tunnel via kubectl port-forward is used (good for development). The runtime image must satisfy the runtime image contract; workspace persistence depends on the PVC configured in the template — see Sandbox - Kubernetes state persistence.

E2B sandbox

Daytona sandbox

AgentRun sandbox (Alibaba Cloud)

Common options inherited from SandboxFilesystemSpec

Snapshot strategies

Snapshots let the next call() restore the previous sandbox state (installed deps, generated files, etc.):

Example: coding assistant (Docker + local snapshots)

Workspace projection

When a sandbox starts, the framework tars the workspace’s “static assets” and hydrates them into /workspace inside the container. These include:
  • AGENTS.md (persona file)
  • skills/ (skill directory)
  • subagents/ (subagent declarations)
  • knowledge/ (knowledge base)
  • .skills-cache/ (skill cache)
Projection compares content by SHA-256; unchanged files skip hydration. Customize which paths are included via workspaceProjectionRoots(List), or disable entirely with workspaceProjectionEnabled(false).

Mode 3: local + shell (default)

What you get with no filesystem(...) call: workspace lives at ${cwd}/.agentscope/workspace/, shell runs on the host:

All configuration options

Path resolution policy (LocalFsMode)

Overlay filesystem

Local mode actually produces an OverlayFilesystem:
  • Upper (read-write): LocalFilesystemWithShell, rooted at workspace, provides shell;
  • Lower (read-only): LocalFilesystem, rooted at project.
Reads check workspace first, then fall back to project (copy-on-write semantics). Shell pwd is the project directory, so ls shows project files.

Project-writable mode (projectWritable)

By default all writes land in the workspace — fine for read/analyze scenarios, but if the agent’s job is to generate code (e.g. scaffold a microservice), files end up in .agentscope/workspace/ instead of the project directory. Enable projectWritable(true) and the framework routes writes by path:
Read behavior is unchanged — workspace first, project fallback.

Example: local development assistant

The agent can read/write files under /Users/alice/my-project and /Users/alice/.config, run shell commands with cwd at /Users/alice/my-project, but cannot access other host directories.

IsolationScope — bucketing across users and replicas

Both mode 1 (shared store) and mode 2 (sandbox) use the same IsolationScope concept to decide who shares state with whom:

Fallback rules per scope

  • Under USER scope, if RuntimeContext.userId is absent, falls back to SESSION (isolates by sessionId).
  • Under SESSION scope, if RuntimeContext.sessionId is absent, state lookup is skipped and a fresh environment is created.
  • AGENT scope uses the agent name (fixed at build time) as the namespace key — it never degrades due to missing context fields.

Concurrency in sandbox mode

IsolationScope in sandbox mode is sequential-reuse sharing, not live-instance sharing. Concurrent calls at the same scope key each get their own running container; at call end, the last-written snapshot wins. For AGENT / GLOBAL scopes where multiple users share state, use executionGuard(SandboxExecutionGuard) to serialize concurrent access.

Example: scope combinations for different business needs

Scenario 1: per-user coding sandbox, preserving installed deps across sessions
Scenario 2: per-conversation disposable sandbox
Scenario 3: shared-knowledge customer-service agent (shared store)

How multi-user isolation works

RuntimeContext.userId is the key to multi-user splitting: Without userId, single-tenant default applies and everyone shares one root.

Runtime data vs static assets

Runtime data (conversation logs, tasks, memory) follows IsolationScope / userId and is automatically isolated. Static assets (AGENTS.md, tools.json, knowledge/) are shared across all users and are not auto-partitioned by userId. Differentiation is only possible through per-user override directories:

How skills and tools behave in each mode

Skills

DynamicSkillMiddleware merges skills from the repository list before each reasoning turn and renders them into the system prompt. Skill file loading goes through the AbstractFilesystem interface, so it works transparently across all three modes: The four-layer priority is unchanged (low → high): projectGlobalSkillsDirskillRepositoryworkspace/skills/<userId>/skills/.

File tools (read_file / write_file / edit_file / …)

All file tools call through the AbstractFilesystem interface, passing the current RuntimeContext on every operation. The filesystem implementation decides the actual read/write location. Agent code is completely unaware of the mode.

Shell execution (execute)

tools.json / MCP servers

tools.json is read once from the workspace at build() time (through WorkspaceManager, supporting two-layer reads), registering MCP servers and applying allow/deny filters. Behavior is the same across all three modes — configuration is read at build time, unaffected by the runtime filesystem mode. Under shared-store mode, tools.json also follows the “remote upper, local template lower” overlay: modifying tools.json via an admin console requires re-building the agent to take effect (MCP server registration is a one-time operation).

Two-layer reading in the workspace

Key files like AGENTS.md, MEMORY.md, KNOWLEDGE.md have a “two-layer fallback” on reads: look in your configured filesystem first, fall back to local disk if not found. This is useful for “template files” in mode 1 (shared store): the first replica’s local has the template AGENTS.md so it works immediately; later replicas read the up-to-date version from the shared store. Writes always go through the configured filesystem store.

Fully self-managed: abstractFilesystem(...)

If none of the three modes fits, pass a fully self-implemented filesystem:
Usually not needed — the three modes cover ~95% of use cases.
  • Sandbox — runtime details of mode 2 (container lifecycle, snapshot recovery chain)
  • Workspace — directory layout, loading mechanics, the “lower layer” of two-layer reads
  • ContextAgentState and AgentStateStore, (userId, sessionId) addressing
  • Skills — four-layer composition, self-learning loop, the <available_skills> block
  • Toolsread_file / write_file / execute parameters
  • Architecture — how filesystem and runtime context cooperate