openhands/sdk/workspace/
Core Responsibilities
The Workspace system has four primary responsibilities:- Execution Abstraction - Unified interface for command execution across environments
- File Operations - Upload, download, and manipulate files in workspace
- Resource Management - Context manager protocol for setup/teardown
- Environment Isolation - Separate agent execution from host system
Architecture
Key Components
| Component | Purpose | Design |
|---|---|---|
BaseWorkspace | Abstract interface | Defines execution and file operation contracts |
LocalWorkspace | Local execution | Subprocess-based command execution |
RemoteWorkspace | Remote execution | HTTP API-based execution via agent-server |
CommandResult | Execution output | Structured result with stdout, stderr, exit_code |
FileOperationResult | File op outcome | Success status and metadata |
Workspace Types
Local vs Remote Execution
| Aspect | LocalWorkspace | RemoteWorkspace |
|---|---|---|
| Execution | Direct subprocess | HTTP → agent-server |
| Isolation | Process-level | Container/VM-level |
| Performance | Fast (no network) | Network overhead |
| Security | Host system access | Sandboxed |
| Use Case | Development, CLI | Production, web apps |
Core Operations
Command Execution
Command Result Structure:| Field | Type | Description |
|---|---|---|
| stdout | str | Standard output stream |
| stderr | str | Standard error stream |
| exit_code | int | Process exit code (0 = success) |
| timeout | bool | Whether command timed out |
| duration | float | Execution time in seconds |
Invariants (Normative)
Workspace Factory: Host Chooses Remote
TheWorkspace(...) constructor is a factory:
- If
hostis provided, it returns aRemoteWorkspace. - Otherwise it returns a
LocalWorkspace.
context Workspace::__new__ post RemoteIffHost: (host <> null) implies result.oclIsKindOf(RemoteWorkspace)
BaseWorkspace Contract
All workspace implementations must satisfy:execute_command(command, cwd, timeout)returns aCommandResultwhereexit_code=-1indicates timeout.file_upload/file_downloadreturn aFileOperationResultwithsuccess=falseand a populatederrorfield on failure.- Git helpers (
git_changes,git_diff) must raise if the path is not a git repository.
working_dir Normalization
Natural language invariant:working_diris normalized to astreven if passed as aPath.
Pause/Resume Semantics (Optional Capability)
pause() / resume() are intentionally optional capabilities:
LocalWorkspace.pause()/.resume()are no-ops.- Remote/container workspaces may implement pause/resume to conserve resources.
- If a workspace type does not support pausing, it must raise
NotImplementedError.
Discussion: pause() / resume() semantics (design tradeoff)
There is an argument that this is compatible with the “swap workspaces without rewriting code” principle, because most client code should only rely on the core workspace and conversation operations, while optional capabilities are feature-detected or used conditionally.
There is a mild design smell here: the method names pause() / resume() suggest a strong guarantee (that work is actually suspended), but the SDK currently treats them as a best-effort resource management hook.
- Locally, there is often nothing meaningful the workspace can suspend at the boundary (it is operating on the host OS), so
LocalWorkspace.pause()is a no-op. - Some remote/container workspaces may be able to pause a container or VM, but others may not.
- Ergonomic expectation: orchestration code can call
pause()unconditionally and it will be safe. - Guarantee expectation: calling
pause()actually pauses resource usage.
- Add
supports_pause(or a richerpause_capability) toBaseWorkspace, and - Make
pause()/resume()no-ops everywhere by default (including remote) while letting pausable implementations override, - Keep a strict helper (e.g.,
pause_or_raise()) for callers who require a guarantee.
File Operations
| Operation | Local Implementation | Remote Implementation |
|---|---|---|
| Upload | shutil.copy() | POST /file/upload with multipart |
| Download | shutil.copy() | GET /file/download stream |
| Result | FileOperationResult | FileOperationResult |
Resource Management
Workspaces use context manager for safe resource handling: Lifecycle Hooks:| Phase | LocalWorkspace | RemoteWorkspace |
|---|---|---|
| Enter | Create working directory | Connect to agent-server, verify |
| Use | Execute commands | Proxy commands via HTTP |
| Exit | No cleanup (persistent) | Disconnect, optionally stop container |
Remote Workspace Extensions
The SDK provides remote workspace implementations inopenhands-workspace package:
Implementation Comparison:
| Type | Setup | Isolation | Use Case |
|---|---|---|---|
| LocalWorkspace | Immediate | Process | Development, trusted code |
| DockerWorkspace | Spawn container | Container | Multi-user, untrusted code |
| RemoteAPIWorkspace | Connect to URL | Remote server | Distributed systems, cloud |
- DockerWorkspace:
openhands-workspace/openhands/workspace/docker - RemoteAPIWorkspace:
openhands-workspace/openhands/workspace/remote_api
Component Relationships
How Workspace Integrates
Relationship Characteristics:- Conversation → Workspace: Conversation factory uses workspace type to select LocalConversation or RemoteConversation
- Workspace → Agent Server: RemoteWorkspace delegates operations to agent-server API
- Tools Independence: Tools run in the same environment as workspace
See Also
- Conversation Architecture - How workspace type determines conversation implementation
- Agent Server - Remote execution API
- Tool System - Tools that use workspace for execution

