diff --git a/AGENTS.md b/AGENTS.md
index a8e99f357..37c89d155 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -31,7 +31,7 @@ The site is built with **Mintlify** and deployed automatically by Mintlify on pu
Mintlify auto-generates `/llms.txt` and `/llms-full.txt`, but this repo **overrides** them by committing
`llms.txt` and `llms-full.txt` at the repo root.
-We do this so LLMs get **V1-only** context while legacy V0 pages remain available for humans.
+We do this so LLMs get **V1-only** context and do not pick up removed legacy V0 pages.
- Generator script: `scripts/generate-llms-files.py`
- Sync workflow: `.github/workflows/check-llms-files.yml` runs weekly (and on demand) to open a PR when the files drift.
@@ -48,6 +48,8 @@ We do this so LLMs get **V1-only** context while legacy V0 pages remain availabl
make llms-check
```
- Exclusions: `openhands/usage/v0/` and any `V0*`-prefixed page files.
+- Current deprecation route: old `openhands/usage/v0/*` links should redirect to `openhands/usage/v0-deprecated`.
+
## Local development
diff --git a/docs.json b/docs.json
index 4337398f6..548007694 100644
--- a/docs.json
+++ b/docs.json
@@ -77,31 +77,9 @@
"group": "Additional Documentation",
"pages": [
{
- "group": "V0 Reference",
+ "group": "Deprecations",
"pages": [
- "openhands/usage/v0/runtimes/V0_overview",
- {
- "group": "V0 Runtime Providers",
- "pages": [
- "openhands/usage/v0/runtimes/V0_docker",
- "openhands/usage/v0/runtimes/V0_remote",
- "openhands/usage/v0/runtimes/V0_local",
- {
- "group": "V0 Third-Party Providers",
- "pages": [
- "openhands/usage/v0/runtimes/V0_modal",
- "openhands/usage/v0/runtimes/V0_daytona",
- "openhands/usage/v0/runtimes/V0_runloop",
- "openhands/usage/v0/runtimes/V0_e2b"
- ]
- }
- ]
- },
- "openhands/usage/v0/advanced/V0_configuration-options",
- {
- "group": "V0 REST API",
- "openapi": "openapi/V0_openapi.json"
- }
+ "openhands/usage/v0-deprecated"
]
},
{
@@ -690,19 +668,67 @@
},
{
"source": "/openhands/usage/runtimes/e2b",
- "destination": "/openhands/usage/v0/runtimes/V0_e2b"
+ "destination": "/openhands/usage/v0-deprecated"
},
{
"source": "/openhands/usage/runtimes/modal",
- "destination": "/openhands/usage/v0/runtimes/V0_modal"
+ "destination": "/openhands/usage/v0-deprecated"
},
{
"source": "/openhands/usage/runtimes/runloop",
- "destination": "/openhands/usage/v0/runtimes/V0_runloop"
+ "destination": "/openhands/usage/v0-deprecated"
},
{
"source": "/openhands/usage/runtimes/daytona",
- "destination": "/openhands/usage/v0/runtimes/V0_daytona"
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/advanced",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/advanced/V0_configuration-options",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_daytona",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_docker",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_e2b",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_local",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_modal",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_overview",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_remote",
+ "destination": "/openhands/usage/v0-deprecated"
+ },
+ {
+ "source": "/openhands/usage/v0/runtimes/V0_runloop",
+ "destination": "/openhands/usage/v0-deprecated"
},
{
"source": "/openhands/usage/automations/examples",
diff --git a/llms-full.txt b/llms-full.txt
index e77a8dbce..7e80592f8 100644
--- a/llms-full.txt
+++ b/llms-full.txt
@@ -9140,7 +9140,7 @@ from openhands.sdk.agent import ACPAgent
from openhands.sdk.conversation import Conversation
# Point at any ACP-compatible server
-agent = ACPAgent(acp_command=["npx", "-y", "claude-code-acp"])
+agent = ACPAgent(acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"])
conversation = Conversation(agent=agent, workspace="./my-project")
conversation.send_message("Explain the architecture of this project.")
@@ -9155,15 +9155,67 @@ The `acp_command` is the shell command used to spawn the server process. The SDK
**Key difference from standard agents:** With `ACPAgent`, you don't need an `LLM_API_KEY` in your code. The ACP server handles its own LLM authentication and API calls. This is *delegation* — your code sends messages to the ACP server, which manages all LLM interactions internally.
+### Prompt Context (AgentContext)
+
+`ACPAgent` supports `agent_context` for **prompt-only extensions** — skills, repository context, current datetime, and system/user message suffixes are appended to the user message before it reaches the ACP server. This lets you inject the same skill catalog and repo-specific guidance that the built-in Agent receives, without interfering with the server's own tools or execution model.
+
+```python icon="python" highlight={4-12,16}
+from openhands.sdk.agent import ACPAgent
+from openhands.sdk import AgentContext
+from openhands.sdk.context import Skill
+
+context = AgentContext(
+ skills=[
+ Skill(
+ name="code-style",
+ content="Always use type hints in Python.",
+ trigger=None, # always active
+ ),
+ ],
+ system_message_suffix="You are reviewing a Python project.",
+)
+
+agent = ACPAgent(
+ acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"],
+ agent_context=context,
+)
+```
+
+The prompt assembly works as follows:
+
+1. The conversation layer builds the user `MessageEvent`, including any per-turn `extended_content` (e.g. triggered-skill injections).
+2. `ACPAgent._build_acp_prompt()` collects all text blocks from the message and appends the rendered `AgentContext` prompt (datetime, repo context, available skills, system suffix) via `to_acp_prompt_context()`.
+3. The combined text is sent as a single user message to the ACP server.
+
+
+`user_message_suffix` is an ACP-compatible field, but it is **not** duplicated in `to_acp_prompt_context()` because the conversation layer already applies it through `MessageEvent.to_llm_message()`.
+
+
+#### Compatible AgentContext Fields
+
+Each `AgentContext` field is tagged as ACP-compatible or not. At initialization, `validate_acp_compatibility()` rejects any context that uses unsupported fields.
+
+| Field | ACP Compatible | Notes |
+|-------|:-:|-------|
+| `skills` | ✅ | Skill catalog and trigger-based injections |
+| `system_message_suffix` | ✅ | Appended to the prompt context |
+| `user_message_suffix` | ✅ | Applied by the conversation layer |
+| `current_datetime` | ✅ | Included in the rendered prompt |
+| `load_user_skills` | ✅ | Load skills from `~/.openhands/skills/` |
+| `load_public_skills` | ✅ | Load skills from the public extensions repo |
+| `marketplace_path` | ✅ | Filter public skills via marketplace JSON |
+| `secrets` | ❌ | ACP subprocesses do not use OpenHands secret injection |
+
+Passing `secrets` (or any future field marked `acp_compatible: False`) raises `NotImplementedError`.
+
### What ACPAgent Does Not Support
-Because the ACP server manages its own tools and context, these `AgentBase` features are not available on `ACPAgent`:
+Because the ACP server manages its own tools, context window, and execution, these `AgentBase` features are not available on `ACPAgent`:
- `tools` / `include_default_tools` — the server has its own tools
- `mcp_config` — configure MCP on the server side
- `condenser` — the server manages its own context window
- `critic` — the server manages its own evaluation
-- `agent_context` — configure the server directly
Passing any of these raises `NotImplementedError` at initialization.
@@ -9196,9 +9248,9 @@ If you attach to an existing conversation by `conversation_id`, use `ACPAgent` f
```python icon="python"
agent = ACPAgent(
- acp_command=["npx", "-y", "claude-code-acp"],
+ acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"],
acp_args=["--profile", "my-profile"], # extra CLI args
- acp_env={"CLAUDE_API_KEY": "sk-..."}, # extra env vars
+ acp_env={"ANTHROPIC_API_KEY": "sk-..."}, # extra env vars
)
```
@@ -9208,6 +9260,15 @@ agent = ACPAgent(
| `acp_args` | Additional arguments appended to the command |
| `acp_env` | Additional environment variables for the server process |
+### Authentication
+
+When the ACP server advertises authentication methods, `ACPAgent` automatically selects a credential source:
+
+1. **ChatGPT subscription login** — If the server supports a `chatgpt` auth method and `~/.codex/auth.json` exists (created by `LLM.subscription_login()`), this is selected first. This enables ACP-backed workflows to use device-code login credentials without an explicit API key.
+2. **API key environment variables** — Falls back to checking for `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `GEMINI_API_KEY` depending on which auth methods the server supports.
+
+If no supported credential source is found, the server may proceed without authentication (some servers don't require it).
+
## Metrics
Token usage and cost data are automatically captured from the ACP server's responses. You can inspect them through the standard `LLM.metrics` interface:
@@ -9229,7 +9290,7 @@ Usage data comes from two ACP protocol sources:
Always call `agent.close()` when you are done to terminate the ACP server subprocess. A `try/finally` block is recommended:
```python icon="python"
-agent = ACPAgent(acp_command=["npx", "-y", "claude-code-acp"])
+agent = ACPAgent(acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"])
try:
conversation = Conversation(agent=agent, workspace=".")
conversation.send_message("Hello!")
@@ -9247,14 +9308,14 @@ This example is available on GitHub: [examples/01_standalone_sdk/40_acp_agent_ex
```python icon="python" expandable examples/01_standalone_sdk/40_acp_agent_example.py
"""Example: Using ACPAgent with Claude Code ACP server.
-This example shows how to use an ACP-compatible server (claude-code-acp)
+This example shows how to use an ACP-compatible server (claude-agent-acp)
as the agent backend instead of direct LLM calls. It also demonstrates
``ask_agent()`` — a stateless side-question that forks the ACP session
and leaves the main conversation untouched.
Prerequisites:
- Node.js / npx available
- - Claude Code CLI authenticated (or CLAUDE_API_KEY set)
+ - ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY set (can point to LiteLLM proxy)
Usage:
uv run python examples/01_standalone_sdk/40_acp_agent_example.py
@@ -9266,7 +9327,7 @@ from openhands.sdk.agent import ACPAgent
from openhands.sdk.conversation import Conversation
-agent = ACPAgent(acp_command=["npx", "-y", "@zed-industries/claude-code-acp"])
+agent = ACPAgent(acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"])
try:
cwd = os.getcwd()
@@ -9285,18 +9346,24 @@ try:
"Based on what you just saw, which agent class is the newest addition?"
)
print(f"ask_agent response: {response}")
+ # Report cost (ACP server reports usage via session_update notifications)
+ cost = agent.llm.metrics.accumulated_cost
+ print(f"EXAMPLE_COST: {cost:.4f}")
finally:
# Clean up the ACP server subprocess
agent.close()
+cost = conversation.conversation_stats.get_combined_metrics().accumulated_cost
+print(f"\nEXAMPLE_COST: {cost}")
print("Done!")
```
-This example does not use an LLM API key directly — the ACP server (Claude Code) handles authentication on its own.
+This example uses ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY environment variables to configure the Claude Code ACP server.
```bash Running the Example
-# Ensure Claude Code CLI is authenticated first
-# (or set CLAUDE_API_KEY in your environment)
+# Set up environment variables (can point to LiteLLM proxy)
+export ANTHROPIC_BASE_URL="https://your-proxy.example.com"
+export ANTHROPIC_API_KEY="your-api-key"
cd software-agent-sdk
uv run python examples/01_standalone_sdk/40_acp_agent_example.py
```
@@ -10272,12 +10339,20 @@ By default, all agents include `finish` tool and the `think` tool.
| Agent | Tools | Description |
|--------|-------|-------|
-| **default** | `terminal`, `file_editor`, `task_tracker`, `browser_tool_set` | General-purpose agent. Used as the fallback when no agent name is specified. |
-| **default cli mode** | `terminal`, `file_editor`, `task_tracker` | Same as `default` but without browser tools (used in CLI mode). |
-| **explore** | `terminal` | Read-only codebase exploration agent. Finds files, searches code, reads source — never creates or modifies anything. |
-| **bash** | `terminal` | Command execution specialist. Runs shell commands, builds, tests, and git operations. |
+| **general-purpose** | `terminal`, `file_editor`, `task_tracker` | General-purpose agent for tasks requiring a combination of capabilities. Used as the fallback when no agent name is specified. |
+| **code-explorer** | `terminal` | Read-only codebase exploration agent. Finds files, searches code, reads source — never creates or modifies anything. |
+| **bash-runner** | `terminal` | Command execution specialist. Runs shell commands, builds, tests, linters, and git operations. Returns concise reports instead of raw output. |
+| **web-researcher** | `browser_tool_set` + MCP (`fetch`, `tavily`) | Web research specialist. Searches the web, navigates documentation, and extracts information from URLs. |
-In CLI mode, the `default` agent (with browser tools) is replaced by the `default cli mode` agent. In non-CLI mode, `default cli mode` is filtered out.
+When `enable_browser=False`, browser-dependent agents like `web-researcher` are not registered.
+
+
+**Deprecated names:** The following legacy names are deprecated (since v1.12.0) and will be removed in version 2.0.0:
+- `default` → use `general-purpose`
+- `default cli mode` → use `general-purpose`
+- `explore` → use `code-explorer`
+- `bash` → use `bash-runner`
+
### Registering Built-in Sub-Agents
@@ -10286,11 +10361,11 @@ Call `register_builtins_agents()` to register all built-in sub-agents. This is t
```python icon="python" focus={3-4, 6-7}
from openhands.tools.preset.default import register_builtins_agents
-# Register built-in sub-agents (default, explore, bash)
+# Register all built-in sub-agents (including web-researcher)
register_builtins_agents()
-# Or in CLI mode (swaps default for default cli mode — no browser)
-register_builtins_agents(cli_mode=True)
+# Or without browser-dependent agents (excludes web-researcher)
+register_builtins_agents(enable_browser=False)
```
@@ -10829,6 +10904,9 @@ Source: https://docs.openhands.dev/sdk/guides/agent-server/api-sandbox.md
> A ready-to-run example is available [here](#ready-to-run-example)!
+
+The [Runtime API](https://runtime.all-hands.dev/) (`runtime.all-hands.dev`) is designed primarily for **[benchmark evaluation at scale](https://github.com/OpenHands/benchmarks)**, not for building production applications. If you are building a production application with the SDK, use the **[OpenHands Cloud Workspace](/sdk/guides/agent-server/cloud-workspace)** instead, which provides fully managed sandbox environments with SaaS credential support.
+
The API-sandboxed agent server demonstrates how to use `APIRemoteWorkspace` to connect to a [OpenHands runtime API service](https://runtime.all-hands.dev/). This eliminates the need to manage your own infrastructure, providing automatic scaling, monitoring, and secure sandboxed execution.
@@ -15039,6 +15117,490 @@ Now that you understand custom visualizers, explore these related topics:
- **[Send Messages While Running](/sdk/guides/convo-send-message-while-running)** - Interactive conversations with real-time updates
- **[Pause and Resume](/sdk/guides/convo-pause-and-resume)** - Control agent execution flow with custom logic
+### Fork a Conversation
+Source: https://docs.openhands.dev/sdk/guides/convo-fork.md
+
+import RunExampleCode from "/sdk/shared-snippets/how-to-run-example.mdx";
+
+> A ready-to-run example is available [here](#ready-to-run-example)!
+
+## Overview
+
+`Conversation.fork()` deep-copies a conversation — events, agent config, workspace metadata — into a new conversation with its own ID. The fork starts in `idle` status and retains the full event memory of the source, so calling `run()` picks up right where the original left off.
+
+**Use cases:**
+- **CI debugging** — an agent produced a wrong patch; fork to debug without losing the original run's audit trail
+- **A/B testing** — fork at a given turn, change one variable, compare downstream outcomes
+- **Tool-change** — fork and swap in a different agent with new tools mid-conversation
+
+## Basic Usage
+
+### Create a fork
+
+```python icon="python" focus={6} wrap
+source = Conversation(agent=agent, workspace=workspace)
+source.send_message("Analyse the sales report.")
+source.run()
+
+# Fork the conversation with a title
+fork = source.fork(title="Follow-up exploration")
+
+# The fork has the same events — agent remembers the full history
+fork.send_message("Now focus on the EMEA region.")
+fork.run() # Continues from the source's state
+```
+
+### Source stays immutable
+
+Forking deep-copies events and state. Anything you do on the fork never touches the source:
+
+```python icon="python" wrap
+source_events_before = len(source.state.events)
+
+fork = source.fork()
+fork.send_message("Extra question")
+
+assert len(source.state.events) == source_events_before # unchanged
+```
+
+### Fork with a different agent
+
+Swap the agent on fork — useful for A/B testing models or adding/removing tools:
+
+```python icon="python" focus={4-8} wrap
+alt_llm = LLM(model="openai/gpt-4o", api_key=api_key, usage_id="alt")
+alt_agent = Agent(llm=alt_llm, tools=[Tool(name=TerminalTool.name)])
+
+fork = source.fork(
+ agent=alt_agent,
+ title="GPT-4o experiment",
+ tags={"variant": "B"},
+)
+fork.run() # Same history, different model
+```
+
+### Tags and metadata
+
+Forks support `title` and arbitrary `tags` for organization:
+
+```python icon="python" wrap
+fork = source.fork(
+ title="Debug investigation",
+ tags={"purpose": "debugging", "triggered_by": "ci-pipeline"},
+)
+
+print(fork.state.tags)
+# {'title': 'Debug investigation', 'purpose': 'debugging', 'triggered_by': 'ci-pipeline'}
+```
+
+### Metrics reset
+
+By default, cost/token stats start fresh on the fork. Pass `reset_metrics=False` to preserve them:
+
+```python icon="python" wrap
+# Cost starts at 0 on the fork (default)
+fork_fresh = source.fork()
+
+# Cost carries over from source
+fork_with_history = source.fork(reset_metrics=False)
+```
+
+## API Reference
+
+```python icon="python" wrap
+def fork(
+ self,
+ *,
+ conversation_id: ConversationID | None = None, # auto-generated if None
+ agent: AgentBase | None = None, # deep-copy of source agent if None
+ title: str | None = None, # sets tags["title"]
+ tags: dict[str, str] | None = None, # arbitrary metadata
+ reset_metrics: bool = True, # cost/tokens start fresh
+) -> Conversation:
+```
+
+| Parameter | Default | Description |
+|-----------|---------|-------------|
+| `conversation_id` | auto-generated UUID | ID for the forked conversation |
+| `agent` | deep-copy of source | Agent for the fork (swap model, tools, etc.) |
+| `title` | `None` | Sets `tags["title"]` on the fork |
+| `tags` | `None` | Arbitrary key-value metadata |
+| `reset_metrics` | `True` | Whether cost/token stats start at zero |
+
+**Returns:** A new `Conversation` with the same event history but independent state.
+
+## What Gets Copied
+
+| Component | Behavior |
+|-----------|----------|
+| **Events** | Deep-copied; source is never modified |
+| **Agent** | Deep-copied by default, or replaced via the `agent` kwarg |
+| **Workspace** | Shared (same working directory) |
+| **Agent state** | Deep-copied (custom runtime data accumulated during the conversation) |
+| **Activated knowledge skills** | Copied (list of skill names activated in the source) |
+| **Stats / Metrics** | Reset by default (`reset_metrics=True`); pass `False` to carry over |
+| **Tags** | Fresh from kwargs; source tags are **not** inherited |
+| **Execution status** | Always `idle` on the fork |
+| **Conversation ID** | New UUID (or explicit via `conversation_id`) |
+
+## Agent-Server REST Endpoint
+
+When using the [agent-server](/sdk/guides/agent-server/overview), forks are available via REST:
+
+```bash icon="terminal"
+POST /api/conversations/{id}/fork
+```
+
+**Request body** (all fields optional):
+
+```json
+{
+ "id": "custom-uuid-or-null",
+ "title": "Debug investigation",
+ "tags": {"purpose": "debugging"},
+ "reset_metrics": true
+}
+```
+
+**Response:** Standard `ConversationInfo` for the newly created fork.
+
+When you call `fork()` on a `RemoteConversation`, the SDK sends this request for
+you and returns a new `RemoteConversation` pointing at the server-side copy.
+Remote forks always reuse the server-managed agent configuration, so
+`RemoteConversation.fork(agent=...)` is intentionally unsupported.
+
+## Agent-Server Example
+
+
+This example is available on GitHub: [examples/02_remote_agent_server/11_conversation_fork.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/11_conversation_fork.py)
+
+
+```python icon="python" expandable examples/02_remote_agent_server/11_conversation_fork.py
+"""Fork a conversation through the agent server REST API.
+
+Demonstrates ``RemoteConversation.fork()`` which delegates to the server's
+``POST /api/conversations/{id}/fork`` endpoint. The fork deep-copies
+events and state on the server side, then returns a new
+``RemoteConversation`` pointing at the copy.
+
+Scenarios covered:
+ 1. Run a source conversation on the server
+ 2. Fork it — verify independent event histories
+ 3. Fork with a title and custom tags
+"""
+
+import os
+import subprocess
+import sys
+import tempfile
+import threading
+import time
+
+from pydantic import SecretStr
+
+from openhands.sdk import LLM, Agent, Conversation, RemoteConversation, Tool, Workspace
+from openhands.tools.terminal import TerminalTool
+
+
+# -----------------------------------------------------------------
+# Managed server helper (reused from example 01)
+# -----------------------------------------------------------------
+def _stream_output(stream, prefix, target_stream):
+ try:
+ for line in iter(stream.readline, ""):
+ if line:
+ target_stream.write(f"[{prefix}] {line}")
+ target_stream.flush()
+ except Exception as e:
+ print(f"Error streaming {prefix}: {e}", file=sys.stderr)
+ finally:
+ stream.close()
+
+
+class ManagedAPIServer:
+ """Context manager that starts and stops a local agent-server."""
+
+ def __init__(self, port: int = 8000, host: str = "127.0.0.1"):
+ self.port = port
+ self.host = host
+ self.process: subprocess.Popen[str] | None = None
+ self.base_url = f"http://{host}:{port}"
+
+ def __enter__(self):
+ print(f"Starting agent-server on {self.base_url} ...")
+ self.process = subprocess.Popen(
+ [
+ "python",
+ "-m",
+ "openhands.agent_server",
+ "--port",
+ str(self.port),
+ "--host",
+ self.host,
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ env={"LOG_JSON": "true", **os.environ},
+ )
+ assert self.process.stdout is not None
+ assert self.process.stderr is not None
+ threading.Thread(
+ target=_stream_output,
+ args=(self.process.stdout, "SERVER", sys.stdout),
+ daemon=True,
+ ).start()
+ threading.Thread(
+ target=_stream_output,
+ args=(self.process.stderr, "SERVER", sys.stderr),
+ daemon=True,
+ ).start()
+
+ import httpx
+
+ for _ in range(30):
+ try:
+ if httpx.get(f"{self.base_url}/health", timeout=1.0).status_code == 200:
+ print(f"Agent-server ready at {self.base_url}")
+ return self
+ except Exception:
+ pass
+ assert self.process.poll() is None, "Server exited unexpectedly"
+ time.sleep(1)
+ raise RuntimeError("Server failed to start in 30 s")
+
+ def __exit__(self, *args):
+ if self.process:
+ self.process.terminate()
+ try:
+ self.process.wait(timeout=5)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.wait()
+ time.sleep(0.5)
+ print("Agent-server stopped.")
+
+
+# -----------------------------------------------------------------
+# Config
+# -----------------------------------------------------------------
+api_key = os.getenv("LLM_API_KEY")
+assert api_key, "LLM_API_KEY must be set"
+
+llm = LLM(
+ model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
+ api_key=SecretStr(api_key),
+ base_url=os.getenv("LLM_BASE_URL"),
+)
+agent = Agent(llm=llm, tools=[Tool(name=TerminalTool.name)])
+
+# -----------------------------------------------------------------
+# Run
+# -----------------------------------------------------------------
+with ManagedAPIServer(port=8002) as server:
+ workspace_dir = tempfile.mkdtemp(prefix="fork_demo_")
+ workspace = Workspace(host=server.base_url, working_dir=workspace_dir)
+
+ # =============================================================
+ # 1. Source conversation
+ # =============================================================
+ source = Conversation(agent=agent, workspace=workspace)
+ assert isinstance(source, RemoteConversation)
+
+ source.send_message("Run `echo hello-from-source` in the terminal.")
+ source.run()
+
+ print("=" * 64)
+ print(" RemoteConversation.fork() — Agent-Server Example")
+ print("=" * 64)
+ print(f"\nSource conversation ID : {source.id}")
+ source_event_count = len(source.state.events)
+ print(f"Source events count : {source_event_count}")
+
+ # =============================================================
+ # 2. Fork and continue independently
+ # =============================================================
+ fork = source.fork(title="Follow-up fork")
+ assert isinstance(fork, RemoteConversation)
+
+ print("\n--- Fork created ---")
+ print(f"Fork ID : {fork.id}")
+ fork_event_count = len(fork.state.events)
+ print(f"Fork events (copied) : {fork_event_count}")
+
+ assert fork.id != source.id
+ # The fork copies all persisted events from the server-side EventLog.
+ # The source's client-side list may additionally contain transient
+ # WebSocket-only events (e.g. full-state snapshots) that are never
+ # persisted, so we only assert the fork has a non-trivial number of
+ # events rather than exact parity.
+ assert fork_event_count > 0
+
+ fork.send_message("Now run `echo hello-from-fork` in the terminal.")
+ fork.run()
+
+ print("\n--- After running fork ---")
+ print(f"Source events : {len(source.state.events)}")
+ print(f"Fork events (grew) : {len(fork.state.events)}")
+ assert len(fork.state.events) > fork_event_count
+
+ # =============================================================
+ # 3. Fork with tags
+ # =============================================================
+ fork_tagged = source.fork(
+ title="Tagged experiment",
+ tags={"purpose": "a/b-test"},
+ )
+ assert isinstance(fork_tagged, RemoteConversation)
+
+ print("\n--- Fork with tags ---")
+ print(f"Fork ID : {fork_tagged.id}")
+
+ fork_tagged.send_message(
+ "What command did you run earlier? Just tell me, no tools."
+ )
+ fork_tagged.run()
+
+ print(f"Fork events : {len(fork_tagged.state.events)}")
+
+ # =============================================================
+ # Summary
+ # =============================================================
+ print(f"\n{'=' * 64}")
+ print("All done — RemoteConversation.fork() works end-to-end.")
+ print("=" * 64)
+
+ # Cleanup
+ fork.close()
+ fork_tagged.close()
+ source.close()
+
+cost = llm.metrics.accumulated_cost
+print(f"EXAMPLE_COST: {cost}")
+```
+
+## Ready-to-run Example
+
+
+This example is available on GitHub: [examples/01_standalone_sdk/48_conversation_fork.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/48_conversation_fork.py)
+
+
+```python icon="python" expandable examples/01_standalone_sdk/48_conversation_fork.py
+"""Fork a conversation to branch off for follow-up exploration.
+
+``Conversation.fork()`` deep-copies a conversation — events, agent config,
+workspace metadata — into a new conversation with its own ID. The fork
+starts in ``idle`` status and retains full event memory of the source, so
+calling ``run()`` picks up right where the original left off.
+
+Use cases:
+ - CI agents that produced a wrong patch — engineer forks to debug
+ without losing the original run's audit trail
+ - A/B-testing prompts — fork at a given turn, change one variable,
+ compare downstream
+ - Swapping tools mid-conversation (fork-on-tool-change)
+"""
+
+import os
+
+from openhands.sdk import LLM, Agent, Conversation, Tool
+from openhands.tools.terminal import TerminalTool
+
+
+# -----------------------------------------------------------------
+# Setup
+# -----------------------------------------------------------------
+llm = LLM(
+ model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
+ api_key=os.getenv("LLM_API_KEY"),
+ base_url=os.getenv("LLM_BASE_URL", None),
+)
+
+agent = Agent(llm=llm, tools=[Tool(name=TerminalTool.name)])
+cwd = os.getcwd()
+
+# =================================================================
+# 1. Run the source conversation
+# =================================================================
+source = Conversation(agent=agent, workspace=cwd)
+source.send_message("Run `echo hello-from-source` in the terminal.")
+source.run()
+
+print("=" * 64)
+print(" Conversation.fork() — SDK Example")
+print("=" * 64)
+print(f"\nSource conversation ID : {source.id}")
+print(f"Source events count : {len(source.state.events)}")
+
+# =================================================================
+# 2. Fork and continue independently
+# =================================================================
+fork = source.fork(title="Follow-up fork")
+source_event_count = len(source.state.events)
+
+print("\n--- Fork created ---")
+print(f"Fork ID : {fork.id}")
+print(f"Fork events (copied) : {len(fork.state.events)}")
+print(f"Fork title : {fork.state.tags.get('title')}")
+
+assert fork.id != source.id
+assert len(fork.state.events) == source_event_count
+
+fork.send_message("Now run `echo hello-from-fork` in the terminal.")
+fork.run()
+
+# Source is untouched
+assert len(source.state.events) == source_event_count
+print("\n--- After running fork ---")
+print(f"Source events (unchanged): {source_event_count}")
+print(f"Fork events (grew) : {len(fork.state.events)}")
+
+# =================================================================
+# 3. Fork with a different agent (tool-change / A/B testing)
+# =================================================================
+alt_llm = LLM(
+ model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
+ api_key=os.getenv("LLM_API_KEY"),
+ base_url=os.getenv("LLM_BASE_URL", None),
+ usage_id="alt",
+)
+alt_agent = Agent(llm=alt_llm, tools=[Tool(name=TerminalTool.name)])
+
+fork_alt = source.fork(
+ agent=alt_agent,
+ title="Tool-change experiment",
+ tags={"purpose": "a/b-test"},
+)
+
+print("\n--- Fork with alternate agent ---")
+print(f"Fork ID : {fork_alt.id}")
+print(f"Fork tags : {dict(fork_alt.state.tags)}")
+
+fork_alt.send_message("What command did you run earlier? Just tell me, no tools.")
+fork_alt.run()
+
+print(f"Fork events : {len(fork_alt.state.events)}")
+
+# =================================================================
+# Summary
+# =================================================================
+print(f"\n{'=' * 64}")
+print("All done — fork() works end-to-end.")
+print("=" * 64)
+
+# Report cost
+cost = llm.metrics.accumulated_cost + alt_llm.metrics.accumulated_cost
+print(f"EXAMPLE_COST: {cost}")
+```
+
+
+
+## Next Steps
+
+- **[Persistence](/sdk/guides/convo-persistence)** — Save and restore conversation state
+- **[Pause and Resume](/sdk/guides/convo-pause-and-resume)** — Control execution flow
+- **[Agent Server](/sdk/guides/agent-server/overview)** — Deploy agents with the REST API
+
### Pause and Resume
Source: https://docs.openhands.dev/sdk/guides/convo-pause-and-resume.md
@@ -17121,8 +17683,8 @@ jobs:
# - one model will be randomly selected per review
llm-model: anthropic/claude-sonnet-4-5-20250929
llm-base-url: ''
- # Review style: roasted (other option: standard)
- review-style: roasted
+ # [DEPRECATED] review-style is no longer used; standard and roasted are merged
+ # review-style: roasted
# Extensions version to use (version tag or branch name)
extensions-version: main
# Secrets
@@ -17136,7 +17698,7 @@ jobs:
|-------|-------------|----------|---------|
| `llm-model` | LLM model to use | Yes | - |
| `llm-base-url` | LLM base URL (optional) | No | `''` |
-| `review-style` | Review style: 'standard' or 'roasted' | No | `roasted` |
+| `review-style` | **[DEPRECATED]** Previously chose between `standard` and `roasted`. Now ignored — the styles have been merged. | No | `roasted` |
| `extensions-version` | Git ref for extensions (tag, branch, or commit SHA) | No | `main` |
| `extensions-repo` | Extensions repository (owner/repo) | No | `OpenHands/extensions` |
| `llm-api-key` | LLM API key | Yes | - |
@@ -17147,8 +17709,8 @@ jobs:
- [PR Review Plugin](https://github.com/OpenHands/extensions/tree/main/plugins/pr-review) - Complete plugin with scripts and skills (in extensions repo)
- [Agent Script](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/scripts/agent_script.py) - Main review agent script
- [Prompt Template](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/scripts/prompt.py) - Review prompt template
-- [Workflow File](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/03_github_workflows/02_pr_review/workflow.yml) - Example workflow
-- [Composite Action](https://github.com/OpenHands/software-agent-sdk/blob/main/.github/actions/pr-review/action.yml) - Reusable GitHub Action
+- [Example Workflow](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/workflows/pr-review-by-openhands.yml) - Example workflow
+- [Composite Action](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/action.yml) - Reusable GitHub Action
### TODO Management
Source: https://docs.openhands.dev/sdk/guides/github-workflows/todo-management.md
@@ -27236,8 +27798,9 @@ Source: https://docs.openhands.dev/openhands/usage/advanced/configuration-option
This page documents the current V1 configuration model.
- Legacy config.toml / “runtime” configuration docs have been moved
- to the Legacy (V0) section of the Web tab.
+ OpenHands V0 configuration docs have been removed from this site. If you
+ arrived from an old bookmark, see the
+ [V0 documentation deprecation notice](/openhands/usage/v0-deprecated).
## Where configuration lives in V1
@@ -27284,13 +27847,15 @@ choose which sandbox provider to use:
See [Sandboxes overview](/openhands/usage/sandboxes/overview) for details.
-## Need legacy options?
+## Looking for removed V0 options?
-If you are looking for the old config.toml reference or V0 “runtime”
-providers, see:
+If you are looking for the old config.toml reference or V0
+“runtime” providers, start with these V1 pages instead:
-- Web → Legacy (V0) → V0 Configuration Options
-- Web → Legacy (V0) → V0 Runtime Configuration
+- [Sandboxes overview](/openhands/usage/sandboxes/overview)
+- [Docker sandbox](/openhands/usage/sandboxes/docker)
+- [Remote sandbox](/openhands/usage/sandboxes/remote)
+- [V0 documentation deprecation notice](/openhands/usage/v0-deprecated)
### Custom Sandbox
Source: https://docs.openhands.dev/openhands/usage/advanced/custom-sandbox-guide.md
@@ -27497,10 +28062,11 @@ _Example of CodeActAgent with `gpt-4-turbo-2024-04-09` performing a data science
Source: https://docs.openhands.dev/openhands/usage/api/v1.md
- OpenHands is in a transition period: legacy (V0) endpoints still exist alongside
- the new /api/v1 endpoints.
+ OpenHands V0 API documentation has been removed from this site.
- If you need the legacy OpenAPI reference, see the Legacy (V0) section in the Web tab.
+ If you arrived from an old bookmark or integration guide, see the
+ [V0 documentation deprecation notice](/openhands/usage/v0-deprecated) and use
+ the current /api/v1 endpoints below.
## Overview
@@ -27800,19 +28366,534 @@ Key aspects of the plugin system:
4. Initialization: Plugins are initialized asynchronously when the runtime starts and are accessible to actions
5. Usage: Plugins extend capabilities (e.g., Jupyter for IPython cells); the server exposes any web endpoints (ports) via host port mapping
-### Hooks
-Source: https://docs.openhands.dev/openhands/usage/customization/hooks.md
+### Creating Automations
+Source: https://docs.openhands.dev/openhands/usage/automations/creating-automations.md
-## Overview
+
+**Beta Feature**: Automations is currently in beta and available for **OpenHands Cloud** and **OpenHands Enterprise** users only.
+
-Hooks let you run custom shell scripts at key moments during an OpenHands session. They are configured per-repository
-via a `.openhands/hooks.json` file and work across **Cloud**, **CLI**, and **local GUI** setups. The hooks format is
-compatible with [Claude Code hooks](https://code.claude.com/docs/en/hooks), so you can reuse hook scripts across both tools.
+The easiest way to create an automation is to ask OpenHands directly. The Automation Skill handles all the details—you just describe what you want.
-Common use cases include:
-- **Blocking dangerous commands** before execution (e.g., preventing `rm -rf /`)
-- **Enforcing quality gates** before the agent finishes (e.g., requiring linting or tests to pass)
-- **Logging and auditing** tool usage for compliance
+## Prompt vs Plugin Automations
+
+There are two types of automations:
+
+
+
+ Most automations are prompt-based. Just describe the task in natural language:
+
+ ```
+ Create an automation called "Daily Standup Summary" that runs every weekday
+ at 9 AM Eastern. It should check our GitHub repo for PRs merged yesterday
+ and post a summary to #engineering on Slack.
+ ```
+
+ This is all you need for reports, monitoring, data syncs, and most common tasks.
+
+
+ For specialized capabilities, include one or more plugins from the [OpenHands extensions repository](https://github.com/OpenHands/extensions):
+
+ ```
+ Create an automation using the code-review plugin that runs every weekday
+ at 9 AM. It should review any Python files changed in the last 24 hours.
+ ```
+
+ Plugins provide additional skills, MCP configurations, or custom commands that extend what the automation can do.
+
+
+
+The agent will:
+1. Confirm the automation name and what it does
+2. Set up the schedule you requested
+3. Create the automation (with plugins if specified)
+
+Once created, it runs automatically on schedule.
+
+## What to Include in Your Request
+
+When asking OpenHands to create an automation, include:
+
+- **What it should do**: Describe the task clearly
+- **When it should run**: Daily, weekly, every hour, etc.
+- **Timezone** (optional): Defaults to UTC if not specified
+- **Name** (optional): The agent can suggest one based on your description
+- **Plugins** (optional): Mention specific plugins if you need extended capabilities
+
+## Writing Good Automation Prompts
+
+The prompt is what the AI agent executes each time the automation runs. Write it like you're giving instructions to a capable assistant.
+
+### Be Specific
+
+
+
+ ```
+ Generate a report
+ ```
+
+
+ ```
+ Generate a weekly status report that:
+ 1. Lists all GitHub PRs merged in the last 7 days
+ 2. Summarizes open issues by priority
+ 3. Formats everything as markdown
+ 4. Posts to the #team-updates Slack channel
+ ```
+
+
+
+### Include Where to Send Results
+
+Tell the automation what to do with its output:
+
+- "Post to the #alerts Slack channel" (requires [Slack MCP](/openhands/usage/cloud/slack-installation))
+- "Save to `reports/weekly-summary.md`"
+- "Create a GitHub issue with the findings" (automatic if you logged in with GitHub)
+- "Send a message via the configured notification service"
+
+
+Git providers you logged in with (GitHub, GitLab, Bitbucket) are automatically available. Other services like Slack require [MCP configuration](/openhands/usage/settings/mcp-settings).
+
+
+### Specify Error Handling
+
+For monitoring tasks, explain what should happen when things go wrong:
+
+```
+Check the health endpoint at https://api.example.com/health.
+If it returns anything other than 200 OK, send an alert to #ops
+with the status code and response body.
+If it's healthy, just log success without alerting.
+```
+
+## What Your Automation Can Access
+
+Each automation runs in a full OpenHands sandbox with:
+
+- **Terminal access**: Run any bash commands
+- **File operations**: Create, read, and modify files
+- **Your LLM**: Uses your configured model from settings
+- **Your secrets**: Access API keys stored in Settings > Secrets
+- **MCP integrations**: Use your configured MCP servers
+- **Network access**: Make HTTP requests, connect to APIs
+- **Git provider access**: Tokens from your Cloud login (GitHub, GitLab, or Bitbucket) are automatically included
+
+## Schedules
+
+Tell OpenHands when you want the automation to run in plain language:
+
+- "every weekday at 9 AM"
+- "every Monday morning"
+- "hourly"
+- "every 15 minutes"
+- "first day of each month"
+- "twice a day at 9 AM and 5 PM"
+
+The agent converts this to the appropriate cron schedule.
+
+
+If you're familiar with cron expressions, you can specify them directly: "Run on cron schedule `0 9 * * 1-5`"
+
+
+## After Creation
+
+Once your automation is created:
+
+- **It starts enabled** by default and will run on the next scheduled time
+- **You can view past runs** in the OpenHands UI
+- **Each run creates a conversation** you can review or continue
+- **You can disable, update, or delete it** anytime (see [Managing Automations](/openhands/usage/automations/managing-automations))
+
+## Next Steps
+
+- [Automations overview & examples](/openhands/usage/automations/overview)
+- [Manage your automations](/openhands/usage/automations/managing-automations)
+
+### Managing Automations
+Source: https://docs.openhands.dev/openhands/usage/automations/managing-automations.md
+
+
+**Beta Feature**: Automations is currently in beta and available for **OpenHands Cloud** and **OpenHands Enterprise** users only.
+
+
+You can manage your automations by asking OpenHands directly—just like you created them.
+
+## Viewing Your Automations
+
+```
+List my automations
+```
+
+```
+Show me the details of the "Daily Report" automation
+```
+
+## Enabling and Disabling
+
+Pause an automation without deleting it:
+
+```
+Disable the "Daily Report" automation
+```
+
+Turn it back on:
+
+```
+Enable the "Daily Report" automation
+```
+
+
+Disabling an automation keeps all its settings intact. Use this when you want to temporarily stop runs without losing your configuration.
+
+
+## Changing the Schedule
+
+```
+Change the "Daily Report" automation to run at 10 AM instead of 9 AM
+```
+
+```
+Update the "Weekly Cleanup" automation to run on Sundays at 2 AM UTC
+```
+
+## Running Manually
+
+Test an automation or run it outside its normal schedule:
+
+```
+Trigger the "Daily Report" automation now
+```
+
+```
+Run the "Health Check" automation immediately
+```
+
+This is useful for:
+- Testing a newly created automation
+- Running a report on-demand
+- Debugging issues
+
+## Viewing Past Runs
+
+```
+Show me recent runs of the "Daily Report" automation
+```
+
+Each run creates a conversation that automatically appears in your conversations list. You can:
+- **View in the OpenHands UI** to see what happened
+- **Continue** if you want to interact with the sandbox
+- **Debug** if something went wrong
+
+
+Automations are user-scoped, so all your automation runs appear alongside your regular conversations. Look for them in your conversations list after each scheduled run.
+
+
+### Run Statuses
+
+- **Pending**: Scheduled, waiting to start
+- **Running**: Currently executing
+- **Completed**: Finished successfully
+- **Failed**: Something went wrong—check the run details
+
+## Deleting Automations
+
+```
+Delete the "Old Report" automation
+```
+
+
+Deleting an automation is permanent. Consider disabling it instead if you might need it later.
+
+
+## Next Steps
+
+- [Automations overview & examples](/openhands/usage/automations/overview)
+- [Create new automations](/openhands/usage/automations/creating-automations)
+
+### Automations Overview
+Source: https://docs.openhands.dev/openhands/usage/automations/overview.md
+
+
+**Beta Feature**: Automations is currently in beta and available for **OpenHands Cloud** and **OpenHands Enterprise** users only.
+
+
+Automations let you schedule AI-powered tasks that run automatically—daily reports, health checks, data syncs, and more. Each automation runs a full OpenHands conversation on your chosen schedule, with access to your LLM settings, stored secrets, and integrations.
+
+Your git provider credentials are automatically available—if you logged into OpenHands Cloud with GitHub, GitLab, or Bitbucket, that access is included by default.
+
+## What Can Automations Do?
+
+- **Generate reports**: Daily standups, weekly summaries, or monthly metrics
+- **Monitor systems**: Check API health, SSL certificates, or uptime
+- **Sync data**: Pull from external APIs, update spreadsheets, or refresh dashboards
+- **Maintain code**: Run dependency checks, security scans, or cleanup tasks
+- **Send notifications**: Post updates to Slack, create GitHub issues, or send alerts
+
+
+Automations can only interact with services you've configured access to. For example, posting to Slack requires the [Slack MCP integration](/openhands/usage/cloud/slack-installation). Git providers you logged in with (GitHub, GitLab, Bitbucket) are automatically available.
+
+
+## Two Types of Automations
+
+When you ask OpenHands to create an automation, you can choose between:
+
+- **Prompt-based** (most common): Describe what the automation should do in natural language. Great for reports, monitoring, data syncs, and most tasks.
+
+- **Plugin-based**: Include one or more plugins that provide additional skills or capabilities. Use this when you need specialized tools from the [OpenHands extensions repository](https://github.com/OpenHands/extensions).
+
+Both types are created the same way—just describe what you want and OpenHands will guide you through the setup.
+
+## Creating Your First Automation
+
+Just ask OpenHands to create one:
+
+```
+Create an automation that runs every Monday at 9 AM and summarizes
+our open GitHub issues, then posts the summary to #engineering on Slack.
+```
+
+For plugin-based automations, mention the plugin:
+
+```
+Create an automation using the code-review plugin that runs daily
+and reviews any Python files changed in the last 24 hours.
+```
+
+The Automation Skill guides you through:
+1. Naming your automation
+2. Setting the schedule
+3. Choosing a timezone
+4. Confirming the task description (and plugins, if any)
+
+That's it—the system handles the rest.
+
+## How It Works
+
+When your automation runs:
+1. A fresh sandbox is created
+2. The OpenHands agent executes your prompt
+3. The conversation is saved so you can review it later
+4. You can even continue the conversation if needed
+
+Automations are user-scoped—each automation and its runs belong to you. Conversations created by your automations automatically appear in your conversations list, just like any other conversation you start.
+
+Your automation has access to everything a normal OpenHands conversation does: terminal, file editing, your configured LLM, stored secrets, and MCP integrations. Git provider tokens from your Cloud login (GitHub, GitLab, or Bitbucket) are automatically included.
+
+## Getting Started
+
+Before creating automations, complete this one-time setup:
+
+### 1. Create an OpenHands API Key
+
+Go to [Settings > API Keys](https://app.all-hands.dev/settings/api-keys) and create a new API key.
+
+### 2. Save the API Key as a Secret
+
+Copy the API key value and go to [Settings > Secrets](https://app.all-hands.dev/settings/secrets). Create a new secret with:
+- **Name**: `OPENHANDS_API_KEY`
+- **Value**: Your API key from step 1
+
+This allows the Automation Skill to create and manage automations on your behalf.
+
+### 3. Start a Conversation
+
+Open a new conversation in OpenHands and ask it to create an automation:
+
+```
+Create an automation that runs every Monday at 9 AM and summarizes
+our open GitHub issues, then posts to #engineering on Slack.
+```
+
+You can also list existing automations, enable/disable them, or trigger manual runs—all through conversation.
+
+## Prerequisites
+
+- **OpenHands Cloud or Enterprise account** (not available in open-source)
+- **Configured LLM** in your [settings](https://app.all-hands.dev/settings)
+- **Stored secrets** (optional) for any additional API keys your automations need (e.g., Slack tokens)
+
+---
+
+## Use Case Automations
+
+{/* BEGIN:use-case-automations — auto-generated from use-case frontmatter */}
+
+Each use case has a ready-to-use automation prompt. Click a card to see the full instructions.
+
+
+
+ Review open PRs daily for bugs, style issues, and security concerns.
+
+
+ Check for outdated packages weekly and report available updates.
+
+
+ Monitor API health, analyze errors, and alert your team automatically.
+
+
+ Scan dependencies for known CVEs, find hardcoded secrets, and alert your team on a schedule.
+
+
+
+{/* END:use-case-automations */}
+
+## General Automations
+
+Ready-to-use templates for common operational tasks.
+
+
+
+ Summarize PRs opened, merged, and reviewed daily.
+
+
+ Generate weekly GitHub activity and issue reports.
+
+
+ Check SSL expiry dates and alert before they lapse.
+
+
+ Remove stale temporary files and report what was cleaned.
+
+
+ Verify database backups exist and are recent.
+
+
+ Pull analytics data periodically and flag big changes.
+
+
+
+### Daily GitHub Summary
+
+```
+Create an automation called "Daily GitHub Summary" that runs every weekday at 9 AM Eastern.
+
+It should:
+1. Summarize PRs opened, merged, and reviewed in the last 24 hours
+2. List any PRs that have been open for more than 3 days
+3. Format as a clean markdown summary
+4. Post to the #engineering Slack channel
+```
+
+### Weekly Metrics Report
+
+```
+Create an automation called "Weekly Metrics" that runs every Monday at 9 AM.
+
+It should generate a weekly report covering:
+- GitHub activity (commits, PRs merged, issues closed)
+- Open issues grouped by priority
+- PRs awaiting review for more than 3 days
+
+Save the report to weekly-reports/ with the current date in the filename.
+```
+
+### SSL Certificate Monitor
+
+```
+Create an automation called "SSL Monitor" that runs daily at 8 AM.
+
+It should check SSL certificate expiry for these domains:
+- api.example.com
+- app.example.com
+- www.example.com
+
+If any certificate expires within 30 days, alert #devops with the domain and days remaining.
+```
+
+### Weekly Cleanup
+
+```
+Create an automation called "Weekly Cleanup" that runs every Sunday at 2 AM UTC.
+
+It should:
+1. Find and delete temporary files older than 7 days
+2. Create a summary of what was removed (file paths and sizes)
+3. Post the cleanup summary to #ops
+```
+
+### Backup Verification
+
+```
+Create an automation called "Backup Check" that runs daily at 6 AM.
+
+It should verify that database backups exist and were created within the last 24 hours.
+List the most recent backup for each database with its timestamp and size.
+If any backup is missing or stale, send an urgent alert to #alerts.
+```
+
+### Analytics Data Sync
+
+```
+Create an automation called "Analytics Sync" that runs every 6 hours.
+
+It should:
+1. Pull the latest data from our analytics API
+2. Update metrics.json with the new data
+3. Calculate week-over-week changes for key metrics
+4. If any metric changed by more than 20%, flag it in a summary message
+```
+
+---
+
+## Tips for Writing Good Prompts
+
+
+
+ Tell the automation exactly what to do:
+ - "Check X and if Y, then Z"
+ - "Generate a report and save it to..."
+ - "Fetch data, compare with expected values, and report differences"
+
+
+ Specify what should happen when things go wrong:
+ - "If the response is not 200..."
+ - "If any backup is missing..."
+ - "If the check fails, alert the team"
+
+
+ Be explicit about outputs:
+ - "Post to the #channel Slack channel"
+ - "Save to reports/ with the current date"
+ - "Create a GitHub issue with the findings"
+
+
+
+## Next Steps
+
+- [Creating Automations](/openhands/usage/automations/creating-automations) — More details on writing prompts
+- [Managing Automations](/openhands/usage/automations/managing-automations) — Update, disable, or delete automations
+- [Use Cases Overview](/openhands/usage/use-cases/overview) — Explore the full use case guides behind these automations
+
+### Hooks
+Source: https://docs.openhands.dev/openhands/usage/customization/hooks.md
+
+## Overview
+
+Hooks let you run custom shell scripts at key moments during an OpenHands session. They are configured per-repository
+via a `.openhands/hooks.json` file and work across **Cloud**, **CLI**, and **local GUI** setups. The hooks format is
+compatible with [Claude Code hooks](https://code.claude.com/docs/en/hooks), so you can reuse hook scripts across both tools.
+
+Common use cases include:
+- **Blocking dangerous commands** before execution (e.g., preventing `rm -rf /`)
+- **Enforcing quality gates** before the agent finishes (e.g., requiring linting or tests to pass)
+- **Logging and auditing** tool usage for compliance
- **Injecting context** into user prompts (e.g., appending git status)
## Hook Types
@@ -29652,7 +30733,7 @@ The Software Agent SDK provides composite GitHub Actions for common workflows:
- **[Automated PR Review](/openhands/usage/use-cases/code-review)** - Automatically review pull requests with inline comments
- **[SDK GitHub Workflows Guide](/sdk/guides/github-workflows/pr-review)** - Build custom GitHub workflows with the SDK
-For example, to set up automated PR reviews, see the [Automated Code Review](/openhands/usage/use-cases/code-review) guide which uses the real `OpenHands/software-agent-sdk/.github/actions/pr-review` composite action.
+For example, to set up automated PR reviews, see the [Automated Code Review](/openhands/usage/use-cases/code-review) guide which uses the `OpenHands/extensions/plugins/pr-review` composite action.
### What You Can Automate
@@ -31260,6 +32341,16 @@ That's it! You can now start using OpenHands with the local LLM server.
If you encounter any issues, let us know on [Slack](https://openhands.dev/joinslack).
+## Community-Reported Notes and Troubleshooting
+
+If OpenHands behaves like a plain chatbot, refuses to use tools or files, or has constant failed tool calls with a local model, the issue may be with the model itself rather than your setup. Even with a large context window, some local models may struggle with reliable tool use.
+
+**Community-reported working models:**
+- `qwen2.5-coder-14b-instruct` — reported to resolve chatbot-like behavior
+- `qwopus3.5-27b-v3 Q8_0` (and similar retrained qwopus variants) — reported to work well with tool calls
+
+If you're experiencing issues, try switching to one of these models before assuming the setup is broken.
+
## Advanced: Alternative LLM Backends
This section describes how to run local LLMs with OpenHands using alternative backends like Ollama, SGLang, or vLLM — without relying on LM Studio.
@@ -32020,7 +33111,8 @@ In some deployments, the provider selection is still controlled via the legacy
## Terminology note (V0 vs V1)
Older documentation refers to these environments as **runtimes**.
-Those legacy docs are now in the Legacy (V0) section of the Web tab.
+That V0 documentation has been removed from this site; if you followed an old
+link, see the [V0 documentation deprecation notice](/openhands/usage/v0-deprecated).
### Process Sandbox
Source: https://docs.openhands.dev/openhands/usage/sandboxes/process.md
@@ -32795,6 +33887,29 @@ To fix this:
vscode_port = 41234
```
+### User Skills Not Loading in Docker
+
+**Description**
+
+When running OpenHands via Docker, custom skills placed in `~/.openhands/skills/` or `~/.agents/skills/` on the host
+machine are not loaded. The skill loader logs show `'user': 0`.
+
+**Resolution**
+
+The agent-server container cannot see your host filesystem by default. Mount your local skills directory into the
+sandbox using the `SANDBOX_VOLUMES` environment variable:
+
+```bash
+-e SANDBOX_VOLUMES="$HOME/.agents/skills:/home/openhands/.agents/skills:ro"
+```
+
+
+ Mount into `~/.agents/skills` inside the container, not `~/.openhands/skills`. The latter would overwrite
+ the public skills cache and prevent built-in skills from loading.
+
+
+See [User Skills When Running OpenHands on Your Own](/overview/skills/org#user-skills-when-running-openhands-on-your-own) for the full Docker command.
+
### GitHub Organization Rename Issues
**Description**
@@ -33029,7 +34144,7 @@ The PR review workflow uses the OpenHands Software Agent SDK to analyze your cod
- `openhands-agent` is requested as a reviewer
2. **Analysis**: The agent receives the complete PR diff and uses two skills:
- - [**`/codereview`**](https://github.com/OpenHands/extensions/tree/main/skills/codereview) or [**`/codereview-roasted`**](https://github.com/OpenHands/extensions/tree/main/skills/codereview-roasted): Analyzes code for quality, security, and best practices
+ - [**`/codereview`**](https://github.com/OpenHands/extensions/tree/main/skills/code-review): Analyzes code for quality, security, data structures, and best practices with a focus on simplicity and pragmatism
- [**`/github-pr-review`**](https://github.com/OpenHands/extensions/tree/main/skills/github-pr-review): Posts structured inline comments via the GitHub API
3. **Output**: Review comments are posted directly on the PR with:
@@ -33037,15 +34152,6 @@ The PR review workflow uses the OpenHands Software Agent SDK to analyze your cod
- Specific line references
- Actionable suggestions with code examples
-### Review Styles
-
-Choose between two review styles:
-
-| Style | Description | Best For |
-|-------|-------------|----------|
-| **Standard** ([`/codereview`](https://github.com/OpenHands/extensions/tree/main/skills/codereview)) | Pragmatic, constructive feedback focusing on code quality, security, and best practices | Day-to-day code reviews |
-| **Roasted** ([`/codereview-roasted`](https://github.com/OpenHands/extensions/tree/main/skills/codereview-roasted)) | Linus Torvalds-style brutally honest review emphasizing "good taste", data structures, and simplicity | Critical code paths, learning opportunities |
-
## Quick Start
@@ -33074,10 +34180,9 @@ Choose between two review styles:
runs-on: ubuntu-latest
steps:
- name: Run PR Review
- uses: OpenHands/software-agent-sdk/.github/actions/pr-review@main
+ uses: OpenHands/extensions/plugins/pr-review@main
with:
llm-model: anthropic/claude-sonnet-4-5-20250929
- review-style: standard
llm-api-key: ${{ secrets.LLM_API_KEY }}
github-token: ${{ secrets.GITHUB_TOKEN }}
```
@@ -33118,7 +34223,7 @@ The workflow uses a reusable composite action from the Software Agent SDK that h
|-------|-------------|----------|---------|
| `llm-model` | LLM model to use | Yes | - |
| `llm-base-url` | LLM base URL (for custom endpoints) | No | `''` |
-| `review-style` | Review style: `standard` or `roasted` | No | `roasted` |
+| `review-style` | **[DEPRECATED]** Previously chose between `standard` and `roasted`. Now ignored — the styles have been merged. | No | `roasted` |
| `extensions-version` | Git ref for extensions (tag, branch, or commit SHA) | No | `main` |
| `extensions-repo` | Extensions repository (owner/repo) | No | `OpenHands/extensions` |
| `llm-api-key` | LLM API key | Yes | - |
@@ -33132,11 +34237,11 @@ Use `extensions-version` to pin to a specific version tag (e.g., `v1.0.0`) for p
### Repository-Specific Review Guidelines
-Create custom review guidelines for your repository by adding a skill file at `.agents/skills/code-review.md`:
+Add repo-specific review rules by creating a skill file at `.agents/skills/custom-codereview-guide.md`:
```markdown
---
-name: code-review
+name: custom-codereview-guide
description: Custom code review guidelines for this repository
triggers:
- /codereview
@@ -33176,8 +34281,12 @@ You are reviewing code for [Your Project Name]. Follow these guidelines:
- Tests should be in [your test directory]
```
+
+**Do not** name your skill `code-review`. The pr-review plugin ships its own `code-review` skill, and plugin skills override project skills with the same name. Use a different name (e.g. `custom-codereview-guide`) with the `/codereview` trigger so both skills are active — the plugin provides the review framework while your skill adds repo-specific rules.
+
+
-The skill file must use `/codereview` as the trigger to override the default review behavior. See the [software-agent-sdk's own code-review skill](https://github.com/OpenHands/software-agent-sdk/blob/main/.agents/skills/code-review.md) for a complete example.
+The skill file must use `/codereview` as the trigger so it activates alongside the default review behavior. See the [software-agent-sdk's own custom-codereview-guide](https://github.com/OpenHands/software-agent-sdk/blob/main/.agents/skills/custom-codereview-guide.md) for a complete example.
### Workflow Configuration
@@ -33186,14 +34295,12 @@ Customize the workflow by modifying the action inputs:
```yaml
- name: Run PR Review
- uses: OpenHands/software-agent-sdk/.github/actions/pr-review@main
+ uses: OpenHands/extensions/plugins/pr-review@main
with:
# Change the LLM model
llm-model: anthropic/claude-sonnet-4-5-20250929
# Use a custom LLM endpoint
llm-base-url: https://your-llm-proxy.example.com
- # Switch to "roasted" style for brutally honest reviews
- review-style: roasted
# Pin to a specific extensions version for stability
extensions-version: main
# Secrets
@@ -33262,10 +34369,30 @@ See real automated reviews in action on the OpenHands Software Agent SDK reposit
+## Automate This
+
+You can schedule daily code reviews using [OpenHands Automations](/openhands/usage/automations/overview).
+Copy this prompt into a new conversation to set one up:
+
+```
+Create an automation called "Daily Code Review" that runs every weekday at 9 AM.
+
+It should:
+1. Find all open PRs that have no reviews yet
+2. For each PR, review the diff for bugs, style issues, and security concerns
+3. Post a summary of findings as a comment on each PR
+
+Learn more at https://docs.openhands.dev/openhands/usage/use-cases/code-review
+```
+
+For inline review comments on every push, use the
+[pr-review plugin](https://github.com/OpenHands/extensions/tree/main/plugins/pr-review)
+as a GitHub Action instead.
+
## Related Resources
-- [PR Review Workflow Reference](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/02_pr_review) - Full workflow example and agent script
-- [Composite Action](https://github.com/OpenHands/software-agent-sdk/blob/main/.github/actions/pr-review/action.yml) - Reusable GitHub Action for PR reviews
+- [PR Review Plugin](https://github.com/OpenHands/extensions/tree/main/plugins/pr-review) - Full workflow example and agent script
+- [Composite Action](https://github.com/OpenHands/extensions/blob/main/plugins/pr-review/action.yml) - Reusable GitHub Action for PR reviews
- [Software Agent SDK](/sdk/index) - Build your own AI-powered workflows
- [GitHub Integration](/openhands/usage/cloud/github-installation) - Set up GitHub integration for OpenHands Cloud
- [Skills Documentation](/overview/skills) - Learn more about OpenHands skills
@@ -33547,6 +34674,23 @@ Create an upgrade plan that handles all these together,
addressing breaking changes in the correct order.
```
+## Automate This
+
+You can schedule weekly dependency checks using [OpenHands Automations](/openhands/usage/automations/overview).
+Copy this prompt into a new conversation to set one up:
+
+```
+Create an automation called "Dependency Checker" that runs every Monday at 8 AM.
+
+It should:
+1. Scan all package.json and requirements.txt files
+2. Check for outdated dependencies
+3. Create a report listing packages with available updates (grouped by major/minor/patch)
+4. Post the report to #engineering
+
+Learn more at https://docs.openhands.dev/openhands/usage/use-cases/dependency-upgrades
+```
+
## Related Resources
- [Vulnerability Remediation](/openhands/usage/use-cases/vulnerability-remediation) - Fix security vulnerabilities
@@ -33810,6 +34954,24 @@ Avoid these common incident response mistakes:
For production incidents, always follow your organization's incident response procedures. OpenHands is a tool to assist your investigation, not a replacement for proper incident management.
+## Automate This
+
+You can set up continuous health monitoring using [OpenHands Automations](/openhands/usage/automations/overview).
+Copy this prompt into a new conversation to set one up:
+
+```
+Create an automation called "API Health Monitor" that runs every 30 minutes.
+
+It should check https://api.example.com/health and:
+- If the response is not 200 OK, send an alert to #alerts with the status code and response body
+- If healthy, just log success without alerting anyone
+
+Learn more at https://docs.openhands.dev/openhands/usage/use-cases/incident-triage
+```
+
+For deeper error analysis with Datadog integration, see the
+[Datadog debugging workflow](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/04_datadog_debugging).
+
## Related Resources
- [OpenHands SDK Repository](https://github.com/OpenHands/software-agent-sdk) - Build custom AI agents
@@ -33821,6 +34983,8 @@ Source: https://docs.openhands.dev/openhands/usage/use-cases/overview.md
OpenHands supports a wide variety of software development tasks. Here are some of the key use cases where OpenHands can help accelerate your work.
+Each use case can be implemented in different ways—as a one-off conversation, a scheduled [automation](/openhands/usage/automations/overview), a [plugin](https://github.com/OpenHands/extensions), or through the [SDK](/sdk/index). Pick the approach that fits your workflow.
+
+## Automate Any Use Case
+
+Many use cases work best as scheduled automations. Browse ready-to-use automation templates on the [Automations Overview](/openhands/usage/automations/overview) page—just copy a prompt and paste it into OpenHands.
+
+
+
+ Ready-to-use prompts for vulnerability scans, code reviews, monitoring, and more.
+
+
+ Explore plugins in the OpenHands extensions repository for extended capabilities.
+
+
+ Build custom workflows and integrations using the Software Agent SDK.
+
+
+
### Spark Migrations
Source: https://docs.openhands.dev/openhands/usage/use-cases/spark-migrations.md
@@ -34297,6 +35477,27 @@ To build your own vulnerability remediation agent:
As agent capabilities continue to evolve, an increasing number of repetitive and time-consuming security tasks can be automated, enabling developers to focus on higher-level design, innovation, and problem-solving rather than routine maintenance.
+## Automate This
+
+You can run vulnerability scans on a schedule using [OpenHands Automations](/openhands/usage/automations/overview).
+Copy this prompt into a new conversation to set one up:
+
+```
+Create an automation called "Security Scan" that runs daily at 3 AM.
+
+It should run a security audit:
+1. Check for known vulnerabilities in dependencies
+2. Scan for hardcoded secrets or API keys
+3. Look for common security misconfigurations
+
+Create a detailed report and alert #security if any high or critical issues are found.
+
+Learn more at https://docs.openhands.dev/openhands/usage/use-cases/vulnerability-remediation
+```
+
+You can also use the [vulnerability-remediation plugin](https://github.com/OpenHands/extensions/tree/main/plugins/vulnerability-remediation)
+for automated fix PRs alongside the scan.
+
## Related Resources
- [Vulnerability Fixer Example](https://github.com/OpenHands/vulnerability-fixer) - Full implementation example
@@ -34304,6 +35505,32 @@ As agent capabilities continue to evolve, an increasing number of repetitive and
- [Dependency Upgrades](/openhands/usage/use-cases/dependency-upgrades) - Updating vulnerable dependencies
- [Prompting Best Practices](/openhands/usage/tips/prompting-best-practices) - Write effective prompts
+### V0 Documentation Deprecated
+Source: https://docs.openhands.dev/openhands/usage/v0-deprecated.md
+
+
+ OpenHands V0 documentation has been removed from this site.
+
+ If you arrived here from an old bookmark or link, use the current V1 docs below.
+
+
+## Where to Go Instead
+
+- **Runtime / sandbox docs**
+ - [Sandboxes overview](/openhands/usage/sandboxes/overview)
+ - [Docker sandbox](/openhands/usage/sandboxes/docker)
+ - [Remote sandbox](/openhands/usage/sandboxes/remote)
+ - [Process sandbox](/openhands/usage/sandboxes/process)
+- **Configuration docs**
+ - [Configuration Options](/openhands/usage/advanced/configuration-options)
+- **REST API docs**
+ - [REST API (V1)](/openhands/usage/api/v1)
+
+## Maintaining an Older Deployment
+
+If you are still operating a pre-V1 deployment, use documentation that is pinned
+to the version you have deployed rather than the current docs site.
+
## OpenHands Cloud
### Bitbucket Integration
@@ -35190,10 +36417,155 @@ Once you've connected your account, you can:
- [Learn about the Cloud UI](/openhands/usage/cloud/cloud-ui).
- [Install the OpenHands Slack app](/openhands/usage/cloud/slack-installation).
-### Jira Data Center Integration (Coming soon...)
-Source: https://docs.openhands.dev/openhands/usage/cloud/project-management/jira-dc-integration.md
+### Plugin Launcher
+Source: https://docs.openhands.dev/openhands/usage/cloud/plugin-launcher.md
+
+The OpenHands Cloud `https://app.all-hands.dev/launch` route lets you create shareable links that open OpenHands with one or more plugins already selected.
+
+This is useful for:
+
+- adding a "Try it" link or badge to a plugin README
+- sharing a pre-configured plugin in docs, issues, or Slack
+- building internal test pages for plugin development
+
+
+ `/launch` is a Cloud route, not a standalone REST endpoint. After the user opens the link and confirms the plugin configuration, OpenHands starts a conversation using the normal V1 conversation flow described in the [Cloud API guide](/openhands/usage/cloud/cloud-api).
+
+
+## Before You Start
+
+You will need:
+
+- an OpenHands Cloud account
+- a plugin or skill stored in a Git repository
+- the repository source, and optionally a branch/tag/commit and subdirectory path
+
+
+ Only share plugins and skills from sources you trust. The launch flow asks the user to trust the extension before it runs with the agent secrets configured in their account.
+
+
+## Step 1: Define the Plugin
+
+Create a JSON array of plugin definitions. Each item uses this shape:
+
+```json
+[
+ {
+ "source": "github:OpenHands/extensions",
+ "ref": "main",
+ "repo_path": "plugins/pr-review"
+ }
+]
+```
+
+The fields are:
+
+- `source` - where the plugin lives, such as `github:owner/repo` or a Git URL
+- `ref` - optional branch, tag, or commit
+- `repo_path` - optional subdirectory inside the repository
+- `parameters` - optional configuration values that OpenHands shows as editable inputs before launch
+
+
+ The same format works for skills. For example, a skill in the OpenHands extensions repo would use `"repo_path": "skills/github"`.
+
+
+## Step 2: Encode the Plugin Definition
+
+The `plugins` query parameter must be a base64-encoded version of your JSON array.
+
+```json
+[
+ {
+ "source": "github:OpenHands/extensions",
+ "ref": "main",
+ "repo_path": "plugins/pr-review"
+ }
+]
+```
+
+Convert that JSON into base64-encoded text, then use the encoded value as the `plugins` query parameter in your `/launch` URL.
+
+## Step 3: Add an Optional Starting Message
+
+If you want the launched conversation to start with a prompt, add a `message` query parameter.
+
+```text
+https://app.all-hands.dev/launch?plugins=W3sic291cmNlIjoiZ2l0aHViOk9wZW5IYW5kcy9leHRlbnNpb25zIiwicmVmIjoibWFpbiIsInJlcG9fcGF0aCI6InBsdWdpbnMvcHItcmV2aWV3In1d&message=/pr-review%20https%3A//github.com/OpenHands/OpenHands/pull/12699
+```
+
+In this example:
+
+- `plugins` loads the `pr-review` plugin from `OpenHands/extensions`
+- `message` pre-fills the initial task for the conversation
+
+## Step 4: Open the Launch URL
+
+When someone opens the link in OpenHands Cloud:
+
+1. They sign in if needed.
+2. OpenHands shows the plugins or skills from the URL.
+3. Any `parameters` values are shown as inputs that the user can review or edit.
+4. The user confirms they trust the extension.
+5. OpenHands starts the conversation with the selected plugin configuration.
+
+## Simple Format for Development
+
+For quick local or staging tests, you can use simpler query parameters instead of base64 encoding:
+
+```text
+https://app.all-hands.dev/launch?plugin_source=github:OpenHands/extensions&plugin_ref=main&plugin_repo_path=plugins/pr-review
+```
+
+This format is convenient for manual testing, but the encoded `plugins` format is better for production links because it also supports multiple plugins in one URL.
+
+## Next Steps
+
+- Use the [Cloud API guide](/openhands/usage/cloud/cloud-api) for authentication and conversation lifecycle details.
+- See the [REST API (V1) overview](/openhands/usage/api/v1) for the V1 endpoints behind Cloud conversations.
+
+### Jira Data Center Integration (Coming soon...)
+Source: https://docs.openhands.dev/openhands/usage/cloud/project-management/jira-dc-integration.md
+
+# Jira Data Center Integration
+
+## Overview
+
+The Jira Data Center integration enables you to use OpenHands to automatically implement requirements from Jira tickets. When you create a ticket with clear requirements and acceptance criteria, OpenHands can read the ticket, generate an implementation plan, and create a pull request in your linked repository.
+
+### How It Works
+
+Once configured, you can request OpenHands to work on a Jira ticket by:
+
+1. **Specify the Repository**: Include the repository location in either:
+ - The ticket body itself, or
+ - A comment on the ticket
+
+2. **Trigger OpenHands**: Activate the agent using one of these methods:
+ - Add an `openhands` label to the ticket
+ - Comment with: `@openhands please review these requirements, generate a plan, and then proceed with implementation`
+
+OpenHands will then read the ticket, understand the requirements, and generate a conversation that results in a pull request implementing the requested changes.
+
+### Example Ticket
+
+Here's an example of how to structure a Jira ticket for OpenHands:
+
+**Title:** Add SAML Support
+
+**Body:**
+```
+As an administrator for my web app, I want to configure SAML so I can provide secure access to my system.
+
+GitHub repository: AcmeCo/WebApp
-# Jira Data Center Integration
+AC:
+- Verify an administrator can configure SAML settings
+- Verify an end user can authenticate via SAML
+```
+
+After creating this ticket, you can either add the `openhands` label or comment with `@openhands please review these requirements, generate a plan, and then proceed with implementation` to start the automation process.
+
+---
## Platform Configuration
@@ -35320,6 +36692,45 @@ Source: https://docs.openhands.dev/openhands/usage/cloud/project-management/jira
# Jira Cloud Integration
+## Overview
+
+The Jira Cloud integration enables you to use OpenHands to automatically implement requirements from Jira tickets. When you create a ticket with clear requirements and acceptance criteria, OpenHands can read the ticket, generate an implementation plan, and create a pull request in your linked repository.
+
+### How It Works
+
+Once configured, you can request OpenHands to work on a Jira ticket by:
+
+1. **Specify the Repository**: Include the repository location in either:
+ - The ticket body itself, or
+ - A comment on the ticket
+
+2. **Trigger OpenHands**: Activate the agent using one of these methods:
+ - Add an `openhands` label to the ticket
+ - Comment with: `@openhands please review these requirements, generate a plan, and then proceed with implementation`
+
+OpenHands will then read the ticket, understand the requirements, and generate a conversation that results in a pull request implementing the requested changes.
+
+### Example Ticket
+
+Here's an example of how to structure a Jira ticket for OpenHands:
+
+**Title:** Add SAML Support
+
+**Body:**
+```
+As an administrator for my web app, I want to configure SAML so I can provide secure access to my system.
+
+Repository: AcmeCo/WebApp
+
+AC:
+- Verify an administrator can configure SAML settings
+- Verify an end user can authenticate via SAML
+```
+
+After creating this ticket, you can either add the `openhands` label or comment with `@openhands please review these requirements, generate a plan, and then proceed with implementation` to start the automation process.
+
+---
+
## Platform Configuration
### Step 1: Create Service Account
@@ -35846,7 +37257,11 @@ Get familiar with our architecture:
- **[Evaluation](https://github.com/OpenHands/benchmarks)** - Testing and benchmarks
### Pull Request Process
-We welcome all pull requests! Here's how we evaluate them:
+We welcome pull requests across our public repositories! Here's how we evaluate them:
+
+
+**Enterprise Directory Restriction:** We cannot accept pull requests for changes in the `enterprise/` directory of the OpenHands repository at this time, as this part of the codebase is commercially licensed. If you have feedback or suggestions for [OpenHands Enterprise](/enterprise/index), please [create an issue](https://github.com/OpenHands/OpenHands/issues) in the OpenHands repository instead.
+
#### Small Improvements
- Quick review and approval for obvious improvements
@@ -35959,7 +37374,7 @@ OpenHands is released under the **MIT License**, which means:
*Full license text: [LICENSE](https://github.com/OpenHands/OpenHands/blob/main/LICENSE)*
-**Special Note:** Content in the `enterprise/` directory has a separate license. See `enterprise/LICENSE` for details.
+**Special Note:** Content in the `enterprise/` directory has a separate license, and we cannot accept external pull requests for changes to this directory at this time. See `enterprise/LICENSE` for details.
## Ready to make your first contribution?
@@ -36557,14 +37972,55 @@ General skill file example for organization `Great-Co` located inside the `.agen
For GitLab organizations, the same skill would be located inside the `openhands-config` repository.
-## User Skills When Running Openhands on Your Own
+## User Skills When Running OpenHands on Your Own
-
- This works with CLI, headless and development modes. It does not work out of the box when running OpenHands using the docker command.
-
+When running OpenHands on your own, you can place skills in the `~/.agents/skills/` folder on your local
+system and OpenHands will always load them for all your conversations. Repo-level overrides live in `.agents/skills/`.
-When running OpenHands on your own, you can place skills in the `~/.agents/skills` folder on your local
-system and OpenHands will always load it for all your conversations. Repo-level overrides live in `.agents/skills`.
+
+
+ User skills from `~/.agents/skills/` are loaded automatically — no extra configuration needed.
+
+
+ When running OpenHands via Docker, the agent-server container cannot see your host filesystem by default.
+ You need to mount your local skills directory into the sandbox using the `SANDBOX_VOLUMES` environment variable:
+
+ ```bash
+ docker run -it --rm --pull=always \
+ -e SANDBOX_VOLUMES="$HOME/.agents/skills:/home/openhands/.agents/skills:ro" \
+ -e AGENT_SERVER_IMAGE_REPOSITORY=ghcr.io/openhands/agent-server \
+ -e AGENT_SERVER_IMAGE_TAG=1.15.0-python \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v ~/.openhands:/.openhands \
+ -p 3000:3000 \
+ --add-host host.docker.internal:host-gateway \
+ --name openhands-app \
+ docker.openhands.dev/openhands/openhands:1.6
+ ```
+
+
+ Mount into `~/.agents/skills` inside the container (not `~/.openhands/skills`). Mounting
+ into `~/.openhands/skills` would overwrite the public skills cache and prevent built-in
+ skills from loading.
+
+
+ You can store your skills in any host directory (e.g., `~/my-skills/`) and mount them
+ to `~/.agents/skills` in the sandbox:
+
+ ```bash
+ -e SANDBOX_VOLUMES="$HOME/my-skills:/home/openhands/.agents/skills:ro"
+ ```
+
+ If you also need to mount a workspace, use a comma-separated list:
+
+ ```bash
+ -e SANDBOX_VOLUMES="$HOME/project:/workspace:rw,$HOME/.agents/skills:/home/openhands/.agents/skills:ro"
+ ```
+
+ See the [SANDBOX_VOLUMES documentation](/openhands/usage/sandboxes/docker#using-sandbox_volumes) for more details
+ on the mount format.
+
+
### Global Skills
Source: https://docs.openhands.dev/overview/skills/public.md
@@ -36793,20 +38249,432 @@ Enterprise customers receive:
- [SDK Documentation](/sdk/index) — Build custom agents with the OpenHands SDK
- [Pricing](https://openhands.dev/pricing) — Compare all OpenHands plans
+### Enterprise vs. Open Source
+Source: https://docs.openhands.dev/enterprise/enterprise-vs-oss.md
+
+This page describes the key differences between **OpenHands Local GUI** (open source) for individual developers and small teams running the Local GUI on their own machines, and **OpenHands Enterprise** for organizations that need advanced collaboration, integrations, and management capabilities.
+
+## Feature Comparison
+
+The table below highlights the key differences between the OpenHands Local GUI and OpenHands Enterprise offerings:
+
+| Feature | Local GUI | OpenHands Enterprise |
+|---------|-------------------|----------------------|
+| **Full breadth of agent functionality (sub-agents, MCP, skills, model agnosticism)** | ✅ | ✅ |
+| **Where does the agent run?** | Local dev machines | Scalable, runtime sandboxes |
+| **Scalability** *Run multiple concurrent agent conversations* | Limited by machine | Unlimited, on-demand |
+| **'@OpenHands' in Slack and Jira** *Important for real-time resolution of bugs and feedback* | ❌ | ✅ |
+| **'@OpenHands' in GitHub, GitLab, Bitbucket** *Important for real-time resolution of PR comments and failing tests* | ❌ | ✅ |
+| **Multiple agent conversations in one place** *Give users visibility into all agent conversations* | ✅ | ✅ |
+| **Share conversations** *Unlock collaboration use cases* | ❌ | ✅ |
+| **Remote monitoring of agent conversations** *Enable Human-in-the-Loop operations for running agents* | ❌ Requires access to machine where agent is running | ✅ Monitor remotely from OpenHands Enterprise UI |
+| **Multi-user management and RBAC** *Roll out to several users and teams* | ❌ | ✅ |
+| **Automations** *Create scheduled and event-based workflows* | ❌ | ✅ |
+| **SAML** | ❌ | ✅ |
+| **REST APIs** | ❌ | ✅ |
+
+## When to Choose Each Option
+
+### OpenHands Local GUI
+
+The OpenHands Local GUI is ideal for:
+
+- Individual developers exploring AI-assisted coding
+- Small teams with basic requirements
+- Self-hosted environments where you manage your own infrastructure
+- Running OpenHands locally on your own machine
+
+### OpenHands Enterprise
+
+OpenHands Enterprise is the right choice when you need:
+
+- **Team collaboration** — Share conversations and manage multiple users from a single platform
+- **Platform integrations** — Invoke OpenHands directly from Slack, Jira, GitHub, GitLab, or Bitbucket
+- **Scalability** — Run unlimited parallel agent conversations without local resource constraints
+- **Enterprise security** — SAML authentication, RBAC, and centralized audit logs
+- **Remote monitoring** — Track agent progress in real-time from anywhere
+
+## Getting Started
+
+
+
+ Get started with OpenHands on your local machine using Docker or the CLI launcher.
+
+
+ Discuss your organization's requirements and get a customized deployment plan for OpenHands Enterprise.
+
+
+
+### Kubernetes Installation
+Source: https://docs.openhands.dev/enterprise/k8s-install.md
+
+OpenHands Enterprise can be deployed into an existing Kubernetes cluster using Helm.
+This approach gives you full control over the deployment and is ideal for teams with
+Kubernetes expertise who want to integrate OpenHands into their existing infrastructure.
+
+
+ If you prefer a simpler installation, see the [Quick Start](/enterprise/quick-start)
+ guide for VM-based deployment.
+
+
+## When to Use This Approach
+
+Choose the Kubernetes installation path when you:
+
+- Have an existing Kubernetes cluster you want to deploy into
+- Need fine-grained control over resource allocation and scaling
+- Want to integrate with existing infrastructure (external PostgreSQL, Redis, S3)
+- Have a platform team familiar with Helm and Kubernetes operations
+- Need to comply with specific infrastructure policies or constraints
+
+## Architecture Overview
+
+OpenHands Enterprise consists of several components deployed as Kubernetes workloads:
+
+
+
+### Core Components
+
+| Component | Description |
+|-----------|-------------|
+| **OpenHands Server** | Main application server handling UI, API, and agent orchestration |
+| **Runtime API** | Manages sandbox lifecycle—provisioning, scaling, and cleanup |
+| **Runtimes (Sandboxes)** | Isolated containers where agents execute code |
+| **Keycloak** | Identity and access management |
+| **LiteLLM Proxy** | Routes requests to your LLM provider(s) |
+| **PostgreSQL** | Persistent storage for application data |
+| **Redis** | Caching and session management |
+
+### Supporting Services
+
+| Component | Description |
+|-----------|-------------|
+| **Conversation Bucket** | S3-compatible storage for conversation history |
+| **Image Loader** | Pre-loads runtime container images on nodes |
+
+## Guides
+
+
+ Configure memory, CPU, and storage for optimal performance.
+
+
+## Request Access
+
+Kubernetes-based installation is currently available to select customers on request.
+If you're interested in deploying OpenHands Enterprise into your own Kubernetes cluster,
+please contact our team to discuss your requirements.
+
+
+ Get in touch with our team to request access to Kubernetes installation.
+
+
+### Resource Limits
+Source: https://docs.openhands.dev/enterprise/k8s-install/resource-limits.md
+
+This guide explains how to configure resource limits for OpenHands Enterprise
+components. Proper resource configuration ensures stable operation and prevents
+issues like OOMKills and pod evictions.
+
+## Values File Structure
+
+All configuration examples in this guide show keys that belong in your `site-values.yaml`
+file. The examples show the complete path from the root of the file.
+
+
+ Create a `site-values.yaml` file to store your custom configuration. Pass it to Helm
+ with `-f site-values.yaml` when installing or upgrading.
+
+
+## Understanding Kubernetes Resources
+
+Kubernetes uses two key resource settings:
+
+- **Requests**: The minimum resources guaranteed to a pod. The scheduler uses this
+ to place pods on nodes with sufficient capacity.
+- **Limits**: The maximum resources a pod can use. Exceeding memory limits causes
+ an OOMKill; exceeding CPU limits causes throttling.
+
+
+ If a pod uses significantly more memory than its request (but below its limit),
+ it becomes a candidate for eviction during node pressure. Set requests close to
+ actual usage for production workloads.
+
+
+## Application Server Resources
+
+The OpenHands application server (deployment name: `openhands`) handles the UI, API,
+and agent orchestration. Configure its resources under the `deployment` section in
+your values file.
+
+### Default Configuration
+
+```yaml
+# site-values.yaml
+
+# ============================================================================
+# Application Server (OpenHands deployment)
+# ============================================================================
+# Root-level key: deployment
+# Controls the main OpenHands server pod resources
+# ============================================================================
+deployment:
+ replicas: 1
+ resources:
+ requests:
+ memory: 1200Mi
+ cpu: 100m
+ limits:
+ memory: 3Gi
+```
+
+### Recommended Production Configuration
+
+For production workloads, increase memory and add replicas for redundancy:
+
+```yaml
+# site-values.yaml
+
+deployment: # Root-level key
+ replicas: 2
+ resources:
+ requests:
+ memory: 2560Mi # 2.5Gi - aligns with typical usage
+ cpu: 100m
+ limits:
+ memory: 4Gi # Buffer against OOMKill
+```
+
+### When to Adjust
+
+Increase resources if you observe:
+
+| Symptom | Metric to Check | Action |
+|---------|----------------|--------|
+| Pod restarts | `RESTARTS` column in `kubectl get pods` | Increase `limits.memory` |
+| High memory usage | `kubectl top pods` shows >80% of limit | Increase `limits.memory` |
+| Evictions during node pressure | Pod events show eviction | Increase `requests.memory` to match actual usage |
+| Slow response times | Application latency metrics | Add replicas or increase CPU |
+
+### Horizontal Pod Autoscaling
+
+For automatic scaling based on load, enable the HorizontalPodAutoscaler:
+
+```yaml
+# site-values.yaml
+
+deployment: # Root-level key
+ replicas: 2 # Minimum baseline
+ resources:
+ requests:
+ memory: 2560Mi
+ cpu: 200m # Increase for HPA to use as scaling signal
+ limits:
+ memory: 4Gi
+
+autoscaling: # Root-level key (separate from deployment)
+ enabled: true
+ minReplicas: 2
+ maxReplicas: 5
+ targetCPUUtilizationPercentage: 80
+ targetMemoryUtilizationPercentage: 80
+```
+
+## Sandbox Resources
+
+Sandboxes (also called runtimes) are the isolated containers where agents execute code.
+Each conversation runs in its own sandbox pod. Configure these via environment variables
+in the `runtime-api.env` section.
+
+### Available Settings
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `MEMORY_REQUEST` | `3072Mi` | Minimum memory guaranteed per sandbox |
+| `MEMORY_LIMIT` | `3072Mi` | Maximum memory per sandbox |
+| `CPU_REQUEST` | `500m` | Minimum CPU guaranteed (500m = 0.5 cores) |
+| `CPU_LIMIT` | (none) | Maximum CPU per sandbox |
+| `EPHEMERAL_STORAGE_SIZE` | `10Gi` | Temporary storage per sandbox |
+
+### Default Configuration
+
+```yaml
+# site-values.yaml
+
+# ============================================================================
+# Runtime API (Sandbox Manager)
+# ============================================================================
+# Root-level key: runtime-api
+# This is a subchart that manages sandbox pod lifecycle.
+# The env section passes environment variables to the runtime-api container,
+# which uses them when creating sandbox pods.
+# ============================================================================
+runtime-api:
+ env:
+ MEMORY_REQUEST: "3072Mi"
+ MEMORY_LIMIT: "3072Mi"
+ CPU_REQUEST: "500m"
+ EPHEMERAL_STORAGE_SIZE: "10Gi"
+```
+
+### High-Resource Configuration
+
+For workloads that require more resources (large codebases, memory-intensive builds):
+
+```yaml
+# site-values.yaml
+
+runtime-api: # Root-level key (subchart configuration)
+ env:
+ MEMORY_REQUEST: "8192Mi"
+ MEMORY_LIMIT: "8192Mi"
+ CPU_REQUEST: "2000m"
+ CPU_LIMIT: "4000m"
+ EPHEMERAL_STORAGE_SIZE: "50Gi"
+```
+
+### Resource Format
+
+- **Memory**: Use `Mi` suffix (mebibytes). Examples: `1024Mi`, `4096Mi`, `8192Mi`
+- **CPU**: Use millicores. `1000m` = 1 CPU core. Examples: `500m`, `2000m`, `4000m`
+- **Storage**: Use `Gi` suffix (gibibytes). Examples: `10Gi`, `50Gi`, `100Gi`
+
+
+ Changes to sandbox resources only affect **new sandboxes**. Existing running
+ sandboxes keep their original limits until stopped and restarted.
+
+
+## Applying Changes
+
+### 1. Update your values file
+
+Edit `site-values.yaml` with your desired configuration:
+
+```yaml
+# site-values.yaml
+#
+# This file contains your custom overrides for the OpenHands Helm chart.
+# All keys shown here are root-level keys in the values hierarchy.
+
+# ============================================================================
+# Application Server Resources
+# ============================================================================
+deployment:
+ replicas: 2
+ resources:
+ requests:
+ memory: 2560Mi
+ cpu: 100m
+ limits:
+ memory: 4Gi
+
+# ============================================================================
+# Sandbox Resources (via Runtime API subchart)
+# ============================================================================
+runtime-api:
+ env:
+ MEMORY_REQUEST: "8192Mi"
+ MEMORY_LIMIT: "8192Mi"
+ CPU_REQUEST: "2000m"
+ CPU_LIMIT: "4000m"
+ EPHEMERAL_STORAGE_SIZE: "50Gi"
+```
+
+### 2. Apply with Helm upgrade
+
+```bash
+helm upgrade openhands \
+ oci://ghcr.io/all-hands-ai/helm-charts/openhands \
+ -f site-values.yaml \
+ -n openhands
+```
+
+## Verifying Changes
+
+### Check application server resources
+
+```bash
+kubectl get deployment openhands -n openhands \
+ -o jsonpath='{.spec.template.spec.containers[0].resources}' | jq
+```
+
+### Check replica count
+
+```bash
+kubectl get deployment openhands -n openhands \
+ -o jsonpath='{.spec.replicas}'
+```
+
+### Check runtime-api environment variables
+
+Verify the sandbox resource settings are configured in the runtime-api deployment:
+
+```bash
+kubectl get deployment runtime-api -n openhands \
+ -o jsonpath='{.spec.template.spec.containers[0].env}' | \
+ jq '.[] | select(.name | test("MEMORY|CPU|STORAGE"))'
+```
+
+## Monitoring Resource Usage
+
+### Current resource consumption
+
+```bash
+kubectl top pods -n openhands
+```
+
+### Resource usage over time
+
+For production deployments, we recommend integrating with a monitoring solution
+(Prometheus/Grafana, Datadog, etc.) to track:
+
+- Memory usage vs. limits (to predict OOMKills)
+- Memory usage vs. requests (to predict evictions)
+- CPU throttling events
+- Pod restart counts
+
+## Next Steps
+
+
+
+ Return to the Kubernetes installation overview.
+
+
+ Learn more about OpenHands Enterprise features.
+
+
+
### Quick Start
Source: https://docs.openhands.dev/enterprise/quick-start.md
-This guide walks you through trialing OpenHands Enterprise on AWS. You'll provision
-infrastructure with Terraform, configure GitHub for user authentication, and set up
-Anthropic as your LLM provider.
+This guide walks you through trialing OpenHands Enterprise on your own infrastructure.
+You'll provision infrastructure (AWS Terraform or a manual VM setup), configure
+GitHub for user authentication, and set up Anthropic as your LLM provider.
-## Prerequisites
+## Who This Is For
+
+This guide is **not** for single-user local laptop installs. It is for a **30-day trial of OpenHands Enterprise** on a
+**dedicated VM/server** on your own infrastructure. The deployment requires DNS records, network, and compute setup before installation.
+
+If you want to use OpenHands immediately without infrastructure setup:
+
+- Use OpenHands Cloud (SaaS)
+- Run OpenHands open-source locally using Docker, CLI or SDK
+
+### Accounts and Credentials
Before you begin, make sure you have the following ready:
- **Anthropic API key** from the [Anthropic Console](https://console.anthropic.com/)
- **A GitHub account** with permission to create GitHub Apps
-- **An AWS account** with permissions to create EC2, VPC, and Route53 resources
+- **An AWS account** with permissions to create EC2, VPC, and Route53 resources (**if using the AWS with Terraform path**)
## Provision Infrastructure
@@ -36843,7 +38711,7 @@ You will need a VM to host OpenHands Enterprise. Choose one of the options below
| Port | Protocol | Purpose |
|------|----------|---------|
- | 80 | TCP | HTTP |
+ | 80 | TCP | HTTP ingress/redirect |
| 443 | TCP | HTTPS |
| 30000 | TCP | Admin Console |
@@ -36860,8 +38728,8 @@ You will need a VM to host OpenHands Enterprise. Choose one of the options below
- `charts.r9.all-hands.dev`
- `updates.r9.all-hands.dev`
- `github.com`
- - `docker.io`
- - `docker.dev`
+ - `traefik.github.io`
+ - `registry-1.docker.io`
- `ghcr.io`
@@ -36908,8 +38776,10 @@ You will need a VM to host OpenHands Enterprise. Choose one of the options below
| `runtime-api.` | `runtime-api.openhands.example.com` |
| `*.runtime.` | `*.runtime.openhands.example.com` |
- **Obtain a TLS certificate** with SANs (Subject Alternative Names) for all of the above domains,
- then copy the certificate (`.pem` or `.crt`) and private key (`.pem` or `.key`) to the VM.
+ **Obtain a TLS certificate signed by a well-known certificate authority (CA) such as Let's Encrypt**, with SANs
+ (Subject Alternative Names) for all of the above domains, then copy the certificate
+ (`.pem` or `.crt`) and private key (`.pem` or `.key`) to the VM. Self-signed certificates
+ are not supported for the OpenHands application.
If you don't provide TLS certificates during installation, the Admin Console will use a
@@ -36919,11 +38789,105 @@ You will need a VM to host OpenHands Enterprise. Choose one of the options below
+## Preflight Validation
+
+All items below must be completed before running the installer:
+
+- VM meets CPU, memory, disk, and OS requirements
+- DNS records are created and resolve from the VM
+- Inbound ports are open: `80`, `443`, and `30000`
+- Outbound domains are reachable from the VM
+- GitHub App prerequisites are prepared
+
+
+ Do not run the installer until preflight checks pass.
+
+
+### DNS checks
+
+Run the checks below on the target VM before opening the installer dashboard.
+
+Export your base domain:
+
+```bash
+export BASE_DOMAIN="openhands.example.com"
+```
+Test DNS:
+```bash
+for h in \
+ "${BASE_DOMAIN}" \
+ "app.${BASE_DOMAIN}" \
+ "auth.app.${BASE_DOMAIN}" \
+ "llm-proxy.${BASE_DOMAIN}" \
+ "runtime-api.${BASE_DOMAIN}"; do
+ echo "[DNS] $h"
+ getent hosts "$h" || nslookup "$h"
+done
+```
+
+Expected: each hostname above resolves to your VM's public IP address.
+
+Test that a runtime wildcard hostname resolves:
+
+```bash
+getent hosts "test.runtime.${BASE_DOMAIN}" || nslookup "test.runtime.${BASE_DOMAIN}"
+```
+
+Expected: `test.runtime.${BASE_DOMAIN}` resolves to the same target as `${BASE_DOMAIN}`.
+
+### Outbound connectivity checks
+
+```bash
+urls=(
+ "https://replicated.app"
+ "https://proxy.replicated.com/v2/"
+ "https://images.r9.all-hands.dev/v2/"
+ "https://install.r9.all-hands.dev"
+ "https://charts.r9.all-hands.dev"
+ "https://updates.r9.all-hands.dev"
+ "https://github.com"
+ "https://traefik.github.io/charts/index.yaml"
+ "https://registry-1.docker.io/v2/"
+ "https://ghcr.io/v2/"
+)
+
+for u in "${urls[@]}"; do
+ # HTTP 000 means connection failure (DNS failure, timeout, or blocked network path).
+ code=$(curl -sSIL --max-time 15 -o /dev/null -w "%{http_code}" "$u" || true)
+ if [ "$code" = "000" ]; then
+ echo "FAIL $u"
+ else
+ echo "OK $u (HTTP $code)"
+ fi
+done
+```
+
+Any HTTP response code other than `000` is acceptable for reachability checks
+(for example `200`, `301`, `302`, `401`, `403`, `405`).
+
+If any check fails, stop and resolve before continuing:
+- DNS failures: Verify records are created, point to the right target, and have finished propagating
+- Outbound connectivity failures: Check firewall egress rules, proxy settings, and TLS inspection policies
+
+## Reasons for Requirements
+
+| Requirement | Why It Exists |
+|------------|----------------|
+| `443/TCP` inbound | Primary HTTPS entrypoint for users and service hostnames |
+| `30000/TCP` inbound | Replicated/KOTS Admin Console for install and configuration |
+| `80/TCP` inbound | HTTP entrypoint used for ingress/redirect behavior |
+| `*.runtime.` DNS + cert SAN | Runtime sandboxes are addressed by dynamic runtime-specific hostnames |
+| `replicated.app`, `proxy.replicated.com` | Replicated control-plane/license/install paths |
+| `images.r9...`, `charts.r9...`, `updates.r9...`, `install.r9...` | Vendor distribution image/chart/update/install endpoints |
+| `traefik.github.io` | Embedded cluster ingress chart repository |
+| `ghcr.io`, `registry-1.docker.io` | Container image pulls for platform components |
+| `github.com` | GitHub App setup/auth/webhooks and downloading public agent skills |
+
## Run the Installer
### 1. Access the Installer Dashboard
-[Register for a free 30-day trial](https://install.r9.all-hands.dev/openhands/signup), then
+After preflight validation checks have passed, [register for a free 30-day trial](https://install.r9.all-hands.dev/openhands/signup), then
log in to the installer dashboard. You will see the dashboard below.
Click **"View install guide"** in the Install tile.
@@ -36945,6 +38909,8 @@ The install guide provides commands to run on your VM. SSH into your VM and exec
3. **Extract the installation assets** -- run the `tar` command shown (this includes your license file)
4. **Install** -- run the install command shown
+If the install command fails after preflight checks pass, run `sudo ./openhands support-bundle` and share the resulting bundle with support.
+
**We recommend providing your TLS certificates during installation.** If you used the
Terraform module, the certificates are in your home directory:
@@ -37021,80 +38987,11 @@ configure a GitHub App.
#### Create a GitHub App
-1. Go to [github.com/settings/apps](https://github.com/settings/apps) and click **New GitHub App**.
-
-2. Set a unique **GitHub App name** (e.g., `ACME Corp OpenHands`).
-
-3. Set the **Homepage URL** to `https://app.`.
-
-4. Under **Identifying and authorizing users**:
- - Set the **Callback URL** to:
- ```
- https://auth.app./realms/allhands/broker/github/endpoint
- ```
- - Check the box for **Request user authorization (OAuth) during installation**
-
-5. Under **Webhook**:
- - Set the **Webhook URL** to:
- ```
- https://app./integration/github/events
- ```
- - Generate a webhook secret:
- ```bash
- export WEBHOOK_SECRET=$(openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c 32)
- echo $WEBHOOK_SECRET
- ```
- - Paste the generated value into the **Secret** field
-
-
- Save the webhook secret value -- you will need to enter it in the Admin Console configuration.
-
-
-6. Under **Permissions**, configure the following:
-
- **Repository permissions:**
-
- | Permission | Access |
- |-----------|--------|
- | Actions | Read and write |
- | Commit statuses | Read and write |
- | Contents | Read and write |
- | Issues | Read and write |
- | Pull requests | Read and write |
- | Webhooks | Read and write |
- | Workflows | Read and write |
-
- **Organization permissions:**
-
- | Permission | Access |
- |-----------|--------|
- | Events | Read-only |
-
- **Account permissions:**
-
- | Permission | Access |
- |-----------|--------|
- | Email addresses | Read-only |
-
-7. Click **Create GitHub App**.
-
-8. On the GitHub App page, under **Client secrets**, click **Generate a new client secret**.
- Save this value.
-
-9. Under **Private keys**, click **Generate a private key**. The `.pem` file downloads
- automatically -- note its location.
+Run our [script](https://github.com/All-Hands-AI/OpenHands-Cloud/tree/main/scripts/create_github_app) to create a GitHub App configured for your install.
#### Map GitHub App values to Admin Console
-Go back to the Installer Admin Console in your browser and enter the following values:
-
-| GitHub App Value | Admin Console Field |
-|-----------------|-------------------|
-| Client ID (shown on app page) | GitHub OAuth Client ID |
-| Client secret (from step 8) | GitHub OAuth Client Secret |
-| App ID (shown on app page) | GitHub App ID |
-| Webhook secret (from step 5) | GitHub App Webhook Secret |
-| Private key file (from step 9) | GitHub App Private Key (file upload) |
+Go back to the Installer Admin Console in your browser and enter the values from the Create GitHub App script output. For the private key, upload the file from the `keys` directory of the script location.
After filling in all fields, click **Continue** at the bottom of the page.
diff --git a/llms.txt b/llms.txt
index d03640a75..51174e62d 100644
--- a/llms.txt
+++ b/llms.txt
@@ -33,6 +33,7 @@ from the OpenHands Software Agent SDK.
- [Exception Handling](https://docs.openhands.dev/sdk/guides/llm-error-handling.md): Provider‑agnostic exceptions raised by the SDK and recommended patterns for handling them.
- [FAQ](https://docs.openhands.dev/sdk/faq.md): Frequently asked questions about the OpenHands SDK
- [File-Based Agents](https://docs.openhands.dev/sdk/guides/agent-file-based.md): Define specialized sub-agents as simple Markdown files with YAML frontmatter — no Python code required.
+- [Fork a Conversation](https://docs.openhands.dev/sdk/guides/convo-fork.md): Branch off an existing conversation for follow-up exploration without contaminating the original.
- [Getting Started](https://docs.openhands.dev/sdk/getting-started.md): Install the OpenHands SDK and build AI agents that write software.
- [GPT-5 Preset (ApplyPatchTool)](https://docs.openhands.dev/sdk/guides/llm-gpt5-preset.md): Use the GPT-5 preset to build an agent that swaps the standard FileEditorTool for ApplyPatchTool.
- [Hello World](https://docs.openhands.dev/sdk/guides/hello-world.md): The simplest possible OpenHands agent - configure an LLM, create an agent, and complete a task.
@@ -109,12 +110,14 @@ from the OpenHands Software Agent SDK.
- [API Keys Settings](https://docs.openhands.dev/openhands/usage/settings/api-keys-settings.md): View your OpenHands LLM key and create API keys to work with OpenHands programmatically.
- [Application Settings](https://docs.openhands.dev/openhands/usage/settings/application-settings.md): Configure application-level settings for OpenHands.
- [Automated Code Review](https://docs.openhands.dev/openhands/usage/use-cases/code-review.md): Set up automated PR reviews using OpenHands and the Software Agent SDK
+- [Automations Overview](https://docs.openhands.dev/openhands/usage/automations/overview.md): Create scheduled tasks that run automatically in OpenHands Cloud and Enterprise.
- [AWS Bedrock](https://docs.openhands.dev/openhands/usage/llms/aws-bedrock.md): OpenHands uses LiteLLM to make calls to AWS Bedrock models. You can find their documentation on using Bedrock as a provider [here](https://docs.litellm.ai/docs/providers/bedrock).
- [Azure](https://docs.openhands.dev/openhands/usage/llms/azure-llms.md): OpenHands uses LiteLLM to make calls to Azure's chat models. You can find their documentation on using Azure as a provider [here](https://docs.litellm.ai/docs/providers/azure).
- [Backend Architecture](https://docs.openhands.dev/openhands/usage/architecture/backend.md)
- [COBOL Modernization](https://docs.openhands.dev/openhands/usage/use-cases/cobol-modernization.md): Modernizing legacy COBOL systems with OpenHands
- [Configuration Options](https://docs.openhands.dev/openhands/usage/advanced/configuration-options.md): How to configure OpenHands V1 (Web UI, env vars, and sandbox settings).
- [Configure](https://docs.openhands.dev/openhands/usage/run-openhands/gui-mode.md): High level overview of configuring the OpenHands Web interface.
+- [Creating Automations](https://docs.openhands.dev/openhands/usage/automations/creating-automations.md): Learn how to create scheduled automations using the Automation Skill.
- [Custom LLM Configurations](https://docs.openhands.dev/openhands/usage/llms/custom-llm-configs.md): OpenHands supports defining multiple named LLM configurations in your `config.toml` file. This feature allows you to use different LLM configurations for different purposes, such as using a cheaper model for tasks that don't require high-quality responses, or using different models with different parameters for specific agents.
- [Custom Sandbox](https://docs.openhands.dev/openhands/usage/advanced/custom-sandbox-guide.md): This guide is for users that would like to use their own custom Docker image for the runtime.
- [Debugging](https://docs.openhands.dev/openhands/usage/developers/debugging.md)
@@ -134,6 +137,7 @@ from the OpenHands Software Agent SDK.
- [LiteLLM Proxy](https://docs.openhands.dev/openhands/usage/llms/litellm-proxy.md): OpenHands supports using the [LiteLLM proxy](https://docs.litellm.ai/docs/proxy/quick_start) to access various LLM providers.
- [Local LLMs](https://docs.openhands.dev/openhands/usage/llms/local-llms.md): When using a Local LLM, OpenHands may have limited functionality. It is highly recommended that you use GPUs to serve local models for optimal experience.
- [Main Agent and Capabilities](https://docs.openhands.dev/openhands/usage/agents.md)
+- [Managing Automations](https://docs.openhands.dev/openhands/usage/automations/managing-automations.md): List, update, enable, disable, and delete your automations.
- [Model Context Protocol (MCP)](https://docs.openhands.dev/openhands/usage/settings/mcp-settings.md): This page outlines how to configure and use the Model Context Protocol (MCP) in OpenHands, allowing you
- [Moonshot AI](https://docs.openhands.dev/openhands/usage/llms/moonshot.md): How to use Moonshot AI models with OpenHands
- [OpenAI](https://docs.openhands.dev/openhands/usage/llms/openai-llms.md): OpenHands uses LiteLLM to make calls to OpenAI's chat models. You can find their documentation on using OpenAI as a provider [here](https://docs.litellm.ai/docs/providers/openai).
@@ -156,6 +160,7 @@ from the OpenHands Software Agent SDK.
- [Troubleshooting](https://docs.openhands.dev/openhands/usage/troubleshooting/troubleshooting.md)
- [Tutorial Library](https://docs.openhands.dev/openhands/usage/get-started/tutorials.md): Centralized hub for OpenHands tutorials and examples
- [Use Cases Overview](https://docs.openhands.dev/openhands/usage/use-cases/overview.md): Explore how OpenHands can help with common software development challenges
+- [V0 Documentation Deprecated](https://docs.openhands.dev/openhands/usage/v0-deprecated.md): OpenHands V0 documentation has been removed from this site; use the current V1 docs instead.
- [Vulnerability Remediation](https://docs.openhands.dev/openhands/usage/use-cases/vulnerability-remediation.md): Using OpenHands to identify and fix security vulnerabilities in your codebase
- [WebSocket Connection](https://docs.openhands.dev/openhands/usage/developers/websocket-connection.md)
- [When to Use OpenHands](https://docs.openhands.dev/openhands/usage/essential-guidelines/when-to-use-openhands.md): Guidance on when OpenHands is the right tool for your task
@@ -171,6 +176,7 @@ from the OpenHands Software Agent SDK.
- [Jira Cloud Integration](https://docs.openhands.dev/openhands/usage/cloud/project-management/jira-integration.md): Complete guide for setting up Jira Cloud integration with OpenHands Cloud, including service account creation, API token generation, webhook configuration, and workspace integration setup.
- [Jira Data Center Integration (Coming soon...)](https://docs.openhands.dev/openhands/usage/cloud/project-management/jira-dc-integration.md): Complete guide for setting up Jira Data Center integration with OpenHands Cloud, including service account creation, personal access token generation, webhook configuration, and workspace integration setup.
- [Linear Integration (Coming soon...)](https://docs.openhands.dev/openhands/usage/cloud/project-management/linear-integration.md): Complete guide for setting up Linear integration with OpenHands Cloud, including service account creation, API key generation, webhook configuration, and workspace integration setup.
+- [Plugin Launcher](https://docs.openhands.dev/openhands/usage/cloud/plugin-launcher.md): Use the OpenHands Cloud `/launch` route to open a conversation with plugins or skills pre-configured from a Git repository.
- [Project Management Tool Integrations (Coming soon...)](https://docs.openhands.dev/openhands/usage/cloud/project-management/overview.md): Overview of OpenHands Cloud integrations with project management platforms including Jira Cloud, Jira Data Center, and Linear. Learn about setup requirements, usage methods, and troubleshooting.
- [Slack Integration](https://docs.openhands.dev/openhands/usage/cloud/slack-installation.md): This guide walks you through installing the OpenHands Slack app.
@@ -191,5 +197,8 @@ from the OpenHands Software Agent SDK.
## Other
+- [Enterprise vs. Open Source](https://docs.openhands.dev/enterprise/enterprise-vs-oss.md): Compare OpenHands Enterprise and Open Source offerings to choose the right option for your team
+- [Kubernetes Installation](https://docs.openhands.dev/enterprise/k8s-install.md): Deploy OpenHands Enterprise into your own Kubernetes cluster using Helm
- [OpenHands Enterprise](https://docs.openhands.dev/enterprise.md): Run AI coding agents on your own infrastructure with complete control
- [Quick Start](https://docs.openhands.dev/enterprise/quick-start.md): Get started with a 30-day trial of OpenHands Enterprise.
+- [Resource Limits](https://docs.openhands.dev/enterprise/k8s-install/resource-limits.md): Configure memory, CPU, and storage for OpenHands Enterprise components
diff --git a/openhands/usage/advanced/configuration-options.mdx b/openhands/usage/advanced/configuration-options.mdx
index 2508be3f0..68f52dd99 100644
--- a/openhands/usage/advanced/configuration-options.mdx
+++ b/openhands/usage/advanced/configuration-options.mdx
@@ -6,8 +6,9 @@ description: How to configure OpenHands V1 (Web UI, env vars, and sandbox settin
This page documents the current V1 configuration model.
- Legacy config.toml / “runtime” configuration docs have been moved
- to the Legacy (V0) section of the Web tab.
+ OpenHands V0 configuration docs have been removed from this site. If you
+ arrived from an old bookmark, see the
+ [V0 documentation deprecation notice](/openhands/usage/v0-deprecated).
## Where configuration lives in V1
@@ -54,10 +55,12 @@ choose which sandbox provider to use:
See [Sandboxes overview](/openhands/usage/sandboxes/overview) for details.
-## Need legacy options?
+## Looking for removed V0 options?
-If you are looking for the old config.toml reference or V0 “runtime”
-providers, see:
+If you are looking for the old config.toml reference or V0
+“runtime” providers, start with these V1 pages instead:
-- Web → Legacy (V0) → V0 Configuration Options
-- Web → Legacy (V0) → V0 Runtime Configuration
+- [Sandboxes overview](/openhands/usage/sandboxes/overview)
+- [Docker sandbox](/openhands/usage/sandboxes/docker)
+- [Remote sandbox](/openhands/usage/sandboxes/remote)
+- [V0 documentation deprecation notice](/openhands/usage/v0-deprecated)
diff --git a/openhands/usage/api/v1.mdx b/openhands/usage/api/v1.mdx
index 52e10fa90..f0ed3e7e4 100644
--- a/openhands/usage/api/v1.mdx
+++ b/openhands/usage/api/v1.mdx
@@ -4,10 +4,11 @@ description: Overview of the current V1 REST endpoints used by the Web app.
---
- OpenHands is in a transition period: legacy (V0) endpoints still exist alongside
- the new /api/v1 endpoints.
+ OpenHands V0 API documentation has been removed from this site.
- If you need the legacy OpenAPI reference, see the Legacy (V0) section in the Web tab.
+ If you arrived from an old bookmark or integration guide, see the
+ [V0 documentation deprecation notice](/openhands/usage/v0-deprecated) and use
+ the current /api/v1 endpoints below.
## Overview
diff --git a/openhands/usage/sandboxes/overview.mdx b/openhands/usage/sandboxes/overview.mdx
index da2801b19..84a726c99 100644
--- a/openhands/usage/sandboxes/overview.mdx
+++ b/openhands/usage/sandboxes/overview.mdx
@@ -41,4 +41,5 @@ In some deployments, the provider selection is still controlled via the legacy
## Terminology note (V0 vs V1)
Older documentation refers to these environments as **runtimes**.
-Those legacy docs are now in the Legacy (V0) section of the Web tab.
+That V0 documentation has been removed from this site; if you followed an old
+link, see the [V0 documentation deprecation notice](/openhands/usage/v0-deprecated).
diff --git a/openhands/usage/v0-deprecated.mdx b/openhands/usage/v0-deprecated.mdx
new file mode 100644
index 000000000..28f492ffe
--- /dev/null
+++ b/openhands/usage/v0-deprecated.mdx
@@ -0,0 +1,27 @@
+---
+title: V0 Documentation Deprecated
+description: OpenHands V0 documentation has been removed from this site; use the current V1 docs instead.
+---
+
+
+ OpenHands V0 documentation has been removed from this site.
+
+ If you arrived here from an old bookmark or link, use the current V1 docs below.
+
+
+## Where to Go Instead
+
+- **Runtime / sandbox docs**
+ - [Sandboxes overview](/openhands/usage/sandboxes/overview)
+ - [Docker sandbox](/openhands/usage/sandboxes/docker)
+ - [Remote sandbox](/openhands/usage/sandboxes/remote)
+ - [Process sandbox](/openhands/usage/sandboxes/process)
+- **Configuration docs**
+ - [Configuration Options](/openhands/usage/advanced/configuration-options)
+- **REST API docs**
+ - [REST API (V1)](/openhands/usage/api/v1)
+
+## Maintaining an Older Deployment
+
+If you are still operating a pre-V1 deployment, use documentation that is pinned
+to the version you have deployed rather than the current docs site.
diff --git a/openhands/usage/v0/advanced/V0_configuration-options.mdx b/openhands/usage/v0/advanced/V0_configuration-options.mdx
deleted file mode 100644
index 3a1eedcb5..000000000
--- a/openhands/usage/v0/advanced/V0_configuration-options.mdx
+++ /dev/null
@@ -1,446 +0,0 @@
----
-title: Configuration Options
-description: This page outlines all available configuration options for OpenHands, allowing you to customize its
- behavior and integrate it with other services.
----
-
- This page documents **legacy OpenHands V0** behavior. For the current V1
- sandbox model, see [Sandboxes (V1)](/openhands/usage/sandboxes/overview).
-
-
-
-
- These settings are only available in [Local GUI](/openhands/usage/run-openhands/local-setup). OpenHands Cloud uses a web-based settings interface.
-
-
-
- In GUI Mode, any settings applied through the Settings UI will take precedence.
-
-
-
- **Looking for Environment Variables?** All configuration options can also be set using environment variables.
- See the [Environment Variables Reference](/openhands/usage/environment-variables) for a complete list with examples.
-
-
-## Location of the `config.toml` File
-
-When running OpenHands in CLI, headless, or development mode, you can use a project-specific `config.toml` file for configuration, which must be
-located in the same directory from which the command is run. Alternatively, you may use the `--config-file` option to
-specify a different path to the `config.toml` file.
-
-## Core Configuration
-
-The core configuration options are defined in the `[core]` section of the `config.toml` file.
-
-Core configuration options can be set as environment variables by converting to uppercase. For example:
-- `debug` → `DEBUG`
-- `cache_dir` → `CACHE_DIR`
-- `runtime` → `RUNTIME`
-
-### Workspace
-- `workspace_base` **(Deprecated)**
- - Type: `str`
- - Default: `"./workspace"`
- - Description: Base path for the workspace. **Deprecated: Use `SANDBOX_VOLUMES` instead.**
-
-- `cache_dir`
- - Type: `str`
- - Default: `"/tmp/cache"`
- - Description: Cache directory path
-
-### Debugging and Logging
-- `debug`
- - Type: `bool`
- - Default: `false`
- - Description: Enable debugging
-
-- `disable_color`
- - Type: `bool`
- - Default: `false`
- - Description: Disable color in terminal output
-
-### Trajectories
-- `save_trajectory_path`
- - Type: `str`
- - Default: `"./trajectories"`
- - Description: Path to store trajectories (can be a folder or a file). If it's a folder, the trajectories will be saved in a file named with the session id name and .json extension, in that folder.
-
-- `replay_trajectory_path`
- - Type: `str`
- - Default: `""`
- - Description: Path to load a trajectory and replay. If given, must be a path to the trajectory file in JSON format. The actions in the trajectory file would be replayed first before any user instruction is executed.
-
-### File Store
-- `file_store_path`
- - Type: `str`
- - Default: `"/tmp/file_store"`
- - Description: File store path
-
-- `file_store`
- - Type: `str`
- - Default: `"memory"`
- - Description: File store type
-
-- `file_uploads_allowed_extensions`
- - Type: `list of str`
- - Default: `[".*"]`
- - Description: List of allowed file extensions for uploads
-
-- `file_uploads_max_file_size_mb`
- - Type: `int`
- - Default: `0`
- - Description: Maximum file size for uploads, in megabytes
-
-- `file_uploads_restrict_file_types`
- - Type: `bool`
- - Default: `false`
- - Description: Restrict file types for file uploads
-
-- `file_uploads_allowed_extensions`
- - Type: `list of str`
- - Default: `[".*"]`
- - Description: List of allowed file extensions for uploads
-
-### Task Management
-- `max_budget_per_task`
- - Type: `float`
- - Default: `0.0`
- - Description: Maximum budget per task (0.0 means no limit)
-
-- `max_iterations`
- - Type: `int`
- - Default: `100`
- - Description: Maximum number of iterations
-
-### Sandbox Configuration
-- `volumes`
- - Type: `str`
- - Default: `None`
- - Description: Volume mounts in the format 'host_path:container_path[:mode]', e.g. '/my/host/dir:/workspace:rw'. Multiple mounts can be specified using commas, e.g. '/path1:/workspace/path1,/path2:/workspace/path2:ro'
-
-- `workspace_mount_path_in_sandbox` **(Deprecated)**
- - Type: `str`
- - Default: `"/workspace"`
- - Description: Path to mount the workspace in the sandbox. **Deprecated: Use `SANDBOX_VOLUMES` instead.**
-
-- `workspace_mount_path` **(Deprecated)**
- - Type: `str`
- - Default: `""`
- - Description: Path to mount the workspace. **Deprecated: Use `SANDBOX_VOLUMES` instead.**
-
-- `workspace_mount_rewrite` **(Deprecated)**
- - Type: `str`
- - Default: `""`
- - Description: Path to rewrite the workspace mount path to. You can usually ignore this, it refers to special cases of running inside another container. **Deprecated: Use `SANDBOX_VOLUMES` instead.**
-
-### Miscellaneous
-- `run_as_openhands`
- - Type: `bool`
- - Default: `true`
- - Description: Run as OpenHands
-
-- `runtime`
- - Type: `str`
- - Default: `"docker"`
- - Description: Runtime environment
-
-- `default_agent`
- - Type: `str`
- - Default: `"CodeActAgent"`
- - Description: Name of the default agent
-
-- `jwt_secret`
- - Type: `str`
- - Default: `uuid.uuid4().hex`
- - Description: JWT secret for authentication. Please set it to your own value.
-
-## LLM Configuration
-
-The LLM (Large Language Model) configuration options are defined in the `[llm]` section of the `config.toml` file.
-
-To use these with the docker command, pass in `-e LLM_