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: + +![OpenHands Enterprise Architecture](./images/architecture.svg) + +### 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_