Running a workspace takes two steps: create one on the backend that matches your target environment, then hand its resources to the agent.
Create Workspace
Each backend has its own persistence model and directory layout. Pick the tab matching your target environment:
Local
Bubblewrap
Docker
E2B
Daytona
Kubernetes
OpenSandbox
LocalWorkspace persists state directly under workdir on the host filesystem; restarts simply re-open the same directory. The directory has the following layout:The Glob and Grep tools returned by await workspace.list_tools() use workdir as their default search directory. An omitted path or path="." searches the workspace; path="src" searches its src subdirectory. An absolute path selects that location directly. These defaults apply even when the Python process was launched from a different directory.BubblewrapWorkspace runs every command through bubblewrap (bwrap), so it needs no daemon or cloud account, only the bwrap binary on a Linux host. host_workdir is mounted read-write at /workspace and holds the persisted state; omit it for an ephemeral temp directory removed on close.This is not a network sandbox. The MCP gateway is reached over host loopback across separate bwrap executions, so share_net must stay True and sandboxed code shares the host network namespace: it can reach any service the host can, including other loopback services and cloud metadata endpoints. Bubblewrap still isolates the other namespaces and the mounted filesystem. Use Docker, K8s, or a cloud sandbox when the workload also needs network isolation.
An explicit host_cache_dir must not overlap host_workdir; sharing one cache directory across workspaces trades isolation for faster bootstrap and should be limited to mutually trusted workspaces.DockerWorkspace bind-mounts the host workdir to /workspace inside the container, so the layout below lives on the host and survives container restarts. Omit workdir for a purely ephemeral container whose writable layer disappears with it.E2BWorkspace uses the sandbox filesystem itself as the persistence layer; there is no host workdir. Each sandbox is tagged with workspace_id in its E2B metadata; on restart the workspace looks it up via AsyncSandbox.list(...) and reconnects with connect(sandbox_id=...). Pausing keeps disk state, resuming restores it intact.DaytonaWorkspace targets a Daytona deployment; the sandbox filesystem is the persistence layer, so there is no host workdir. Each sandbox carries workspace_id in its Daytona labels; on restart the workspace reattaches by that label and reuses the sandbox’s disk state.K8sWorkspace runs one Pod per workspace on a Kubernetes cluster, with a PVC mounted as the persistence layer, so the filesystem below survives Pod restarts. On restart the workspace reattaches to the Pod and PVC by their workspace-id-derived names. Set delete_pvc_on_close=True to remove the PVC when the workspace closes.OpenSandboxWorkspace targets an OpenSandbox deployment; the sandbox filesystem is the persistence layer, so there is no host workdir. Each sandbox is tagged with workspace_id under the agentscope.workspace.id metadata key; on restart the workspace filters list_sandbox_infos(...) by that key and resumes the matching sandbox, restoring its disk state intact.The gateway venv is bootstrapped inside the sandbox on first initialize(); extra_pip packages are installed into it alongside the base gateway requirements. Because the slim base image streams apt-get + uv + pip for several minutes on a cold start, bootstrap commands run under a longer per-command timeout; leave request_timeout_seconds at its default (which matches the bootstrap budget) unless you know your image is pre-provisioned.
default_mcps and skill_paths are seed-time inputs, but they never make resources shared inside a shared workspace. Each agent / session gets its own client instances the first time it accesses MCPs, and each agent gets its own skill partition copied from skills/.seed the first time it accesses skills. Later additions and removals only affect that agent / session.
Integrate with Agent
A workspace plugs into Agent along two axes: as a source of tools, MCPs, and skills, and as the offloader for context compression:
The tools returned by list_tools() are already bound to the workspace’s execution backend, so on a sandboxed workspace they run inside the container or sandbox. To bind your own tool instances to the same environment, obtain the backend with workspace.get_backend() and pass it to the tool constructor; see Switch Tool Backend.
Because the workspace exposes its resources as flat lists, you can partition them into ToolGroups when the agent has too many tools to keep all active at once. Pass the groups to Toolkit(tool_groups=[...]) and the agent activates them on demand through the built-in meta tool; only the reserved basic group stays always-on.