Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
7591e23
docs: add workspace types guide and saas_runtime_mode documentation
jpshackelford Mar 23, 2026
ada6d42
docs: nest workspace pages under Workspace Types group
jpshackelford Mar 23, 2026
b9db0ea
docs: rename group to Workspaces, page to Overview
jpshackelford Mar 23, 2026
aaf30a2
docs: simplify quick comparison table for better column widths
jpshackelford Mar 23, 2026
bbbb8cd
docs: use full class names with hyperlinks in comparison table
jpshackelford Mar 23, 2026
b2e9a13
docs: clarify APIRemoteWorkspace is for Enterprise with responsibilities
jpshackelford Mar 23, 2026
de1f9d5
docs: compact table columns to avoid horizontal scroll
jpshackelford Mar 23, 2026
7667853
docs: add table CSS to reduce column widths
jpshackelford Mar 23, 2026
3eced6e
fix: add missing href to stylesheet link in docs.json
jpshackelford Mar 23, 2026
7cd08c3
docs: use checkbox emoji style consistent with Feature Comparison table
jpshackelford Mar 23, 2026
e0767d0
docs: restructure workspace overview into Local vs Remote scenarios
jpshackelford Mar 23, 2026
0c17284
docs: replace ASCII diagram with SVG for saas_runtime_mode
jpshackelford Mar 23, 2026
47de2d0
docs: replace ASCII diagrams with SVGs in cloud-workspace.mdx
jpshackelford Mar 23, 2026
cbed48d
docs: rename saas_runtime_mode to local_agent_server_mode
openhands-agent Mar 25, 2026
e9650dc
Merge branch 'main' into docs/workspace-types-and-saas-runtime-mode
enyst Apr 4, 2026
69da85f
Merge branch 'main' into docs/workspace-types-and-saas-runtime-mode
enyst Apr 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,17 @@
"group": "Remote Agent Server",
"pages": [
"sdk/guides/agent-server/overview",
"sdk/guides/agent-server/local-server",
"sdk/guides/agent-server/docker-sandbox",
"sdk/guides/agent-server/apptainer-sandbox",
"sdk/guides/agent-server/api-sandbox",
"sdk/guides/agent-server/cloud-workspace",
{
"group": "Workspaces",
"pages": [
"sdk/guides/agent-server/workspace-types",
"sdk/guides/agent-server/local-server",
"sdk/guides/agent-server/docker-sandbox",
"sdk/guides/agent-server/apptainer-sandbox",
"sdk/guides/agent-server/api-sandbox",
"sdk/guides/agent-server/cloud-workspace"
]
},
"sdk/guides/agent-server/custom-tools",
{
"group": "API Reference",
Expand Down Expand Up @@ -454,7 +460,8 @@
{
"tag": "link",
"attributes": {
"rel": "stylesheet"
"rel": "stylesheet",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Acceptable: This fixes a broken stylesheet reference (link tag had rel="stylesheet" but no href). The stylesheet wasn't loading before. Good catch.

"href": "/style.css"
}
}
],
Expand Down
115 changes: 115 additions & 0 deletions sdk/guides/agent-server/cloud-workspace.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

> A ready-to-run example is available [here](#ready-to-run-example)!

The `OpenHandsCloudWorkspace` demonstrates how to use the [OpenHands Cloud](https://app.all-hands.dev) to provision and manage sandboxed environments for agent execution. This provides a seamless experience with automatic sandbox provisioning, monitoring, and secure execution without managing your own infrastructure.

Check warning on line 8 in sdk/guides/agent-server/cloud-workspace.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-server/cloud-workspace.mdx#L8

Did you really mean 'sandboxed'?

## Key Concepts

Expand Down Expand Up @@ -71,7 +71,7 @@

```python icon="python" focus={1-3}
result = workspace.execute_command(
"echo 'Hello from OpenHands Cloud sandbox!' && pwd"

Check warning on line 74 in sdk/guides/agent-server/cloud-workspace.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-server/cloud-workspace.mdx#L74

Did you really mean 'pwd'?
)
logger.info(f"Command completed: {result.exit_code}, {result.stdout}")
```
Expand Down Expand Up @@ -383,6 +383,121 @@
uv run python examples/02_remote_agent_server/10_cloud_workspace_share_credentials.py
```

## Local Agent Server Mode

Use `local_agent_server_mode=True` when your SDK script is **already running inside** an OpenHands Cloud sandbox — for example, as part of an automation workflow deployed to the cloud.

### When to Use This Mode

| Scenario | Normal Mode | Local Agent Server Mode |
|----------|-------------|-------------------------|
| Script runs on your local machine | ✅ | ❌ |
| Script runs in CI (GitHub Actions runner) | ✅ | ❌ |
| Script deployed to run inside Cloud sandbox | ❌ | ✅ |
| Automation service executes your script | ❌ | ✅ |

### How It Differs from Normal Mode

In **normal mode**, `OpenHandsCloudWorkspace` provisions a new sandbox via the Cloud API:

<Frame>
<img src="/sdk/guides/agent-server/images/normal-mode.svg" alt="Normal mode: Your machine communicates with OpenHands Cloud via API" />
</Frame>

In **local agent server mode**, your script is already inside the sandbox and connects to the local agent-server:

<Frame>
<img src="/sdk/guides/agent-server/images/local-agent-server-mode-simple.svg" alt="Local agent server mode: Script runs inside Cloud sandbox" />
</Frame>

Key differences:
- **No sandbox provisioning** — skips create/wait/delete lifecycle
- **Connects to localhost** — talks to the agent-server already running in the sandbox
- **Cloud credentials still work** — `get_llm()` and `get_secrets()` call the Cloud API

### Configuration

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `local_agent_server_mode` | `bool` | `False` | Skip sandbox provisioning, connect to localhost |
| `agent_server_port` | `int` | `60000` | Port of the local agent-server |

### Environment Variables

When running inside a Cloud sandbox, these environment variables are set automatically:

| Variable | Description |
|----------|-------------|
| `SANDBOX_ID` | Sandbox identifier for `get_llm()` / `get_secrets()` |
| `SESSION_API_KEY` | Session auth key (fallback: `OH_SESSION_API_KEYS_0`) |
| `AGENT_SERVER_PORT` | Port override (optional) |
| `AUTOMATION_CALLBACK_URL` | URL to POST completion status on exit (optional) |
| `AUTOMATION_RUN_ID` | ID included in callback payload (optional) |

### Example: Automation Script Inside a Cloud Sandbox

This script is designed to be uploaded and executed inside an OpenHands Cloud sandbox:

```python icon="python"
# my_automation.py — runs INSIDE a Cloud sandbox
import os
from openhands.workspace import OpenHandsCloudWorkspace
from openhands.sdk import Conversation
from openhands.tools.preset.default import get_default_agent

with OpenHandsCloudWorkspace(
local_agent_server_mode=True,
cloud_api_url="https://app.all-hands.dev",
cloud_api_key=os.environ["OPENHANDS_API_KEY"],
) as workspace:
# No sandbox created — connects to local agent-server at localhost:60000

# Cloud credentials still work
llm = workspace.get_llm()
secrets = workspace.get_secrets()

agent = get_default_agent(llm=llm, cli_mode=True)
conversation = Conversation(agent=agent, workspace=workspace)

if secrets:
conversation.update_secrets(secrets)

conversation.send_message("Perform the automation task")
conversation.run()
conversation.close()

# On exit: completion callback sent automatically (if AUTOMATION_CALLBACK_URL is set)
```

### Orchestration Pattern

To deploy an automation script that uses local agent server mode:

1. **Create a sandbox** using normal mode (from your local machine or CI):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Acceptable: The orchestration pattern steps are logically correct, but the presentation suggests step 2's code runs outside the context manager.

Readers might wonder: "Can I call workspace.execute_command() after the with block exits?"

Actual answer: Yes, if keep_alive=True keeps the sandbox alive (which it does). But the workspace object remains valid, so this works.

Not blocking, but consider adding a code comment in step 2:

# Workspace persists due to keep_alive=True
workspace.execute_command("python /workspace/my_automation.py")

```python
with OpenHandsCloudWorkspace(
cloud_api_url="https://app.all-hands.dev",
cloud_api_key=api_key,
keep_alive=True, # Don't delete after setup
) as workspace:
workspace.file_upload("my_automation.py", "/workspace/my_automation.py")
```

2. **Execute the script** inside the sandbox:
```python
workspace.execute_command("python /workspace/my_automation.py")
```

3. The script uses `local_agent_server_mode=True` to connect to the local agent-server

4. **Receive callback** when the script completes (optional)

This pattern enables fire-and-forget automation where your orchestrator doesn't need to maintain a connection for the entire agent session.

<Note>
Local agent server mode is primarily used by the OpenHands automation service. For most SDK users, normal mode with `get_llm()` and `get_secrets()` provides a simpler experience.
</Note>

## Next Steps

- **[API-based Sandbox](/sdk/guides/agent-server/api-sandbox)** - Connect to Runtime API service
Comment on lines +386 to 503
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Technical Verification: I cloned software-agent-sdk PR #2490 and verified:

local_agent_server_mode parameter exists (workspace.py:84-91)
agent_server_port default is 60000 (workspace.py:31,92-98)
✅ All environment variables documented correctly (SANDBOX_ID, SESSION_API_KEY, AGENT_SERVER_PORT, AUTOMATION_CALLBACK_URL, AUTOMATION_RUN_ID)
✅ Code examples match actual API

This section is ~120 lines to explain "connect to localhost instead of provisioning a sandbox," which feels verbose. But previous reviewers flagged this and accepted it as serving a purpose (explaining the automation orchestration pattern). No new issues found beyond what was already discussed.

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions sdk/guides/agent-server/images/local-agent-server-mode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions sdk/guides/agent-server/images/normal-mode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading