Runtime-backend docs update (arch) - cron agent run (#10423)

Co-authored-by: OpenHands-GPT-5 <openhands@all-hands.dev>
This commit is contained in:
Engel Nyst 2025-08-18 02:04:31 +02:00 committed by GitHub
parent 277064720c
commit e2343c0927
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 123 additions and 42 deletions

View File

@ -2,55 +2,102 @@
title: Backend Architecture
---
<div style={{ textAlign: 'center' }}>
<img src="https://github.com/All-Hands-AI/OpenHands/assets/16201837/97d747e3-29d8-4ccb-8d34-6ad1adb17f38" alt="OpenHands System Architecture Diagram Jul 4 2024" />
<p><em>OpenHands System Architecture Diagram (July 4, 2024)</em></p>
</div>
This is a high-level overview of the system architecture. The system is divided into two main components: the frontend and the backend. The frontend is responsible for handling user interactions and displaying the results. The backend is responsible for handling the business logic and executing the agents.
# Frontend architecture
# System overview
![system_architecture.svg](/static/img/system_architecture.svg)
```mermaid
flowchart LR
U["User"] --> FE["Frontend (SPA)"]
FE -- "HTTP/WS" --> BE["OpenHands Backend"]
BE --> ES["EventStream"]
BE --> ST["Storage"]
BE --> RT["Runtime Interface"]
BE --> LLM["LLM Providers"]
subgraph Runtime
direction TB
RT --> DRT["Docker Runtime"]
RT --> LRT["Local Runtime"]
RT --> RRT["Remote Runtime"]
DRT --> AES["Action Execution Server"]
LRT --> AES
RRT --> AES
AES --> Bash["Bash Session"]
AES --> Jupyter["Jupyter Plugin"]
AES --> Browser["BrowserEnv"]
end
```
This Overview is simplified to show the main components and their interactions. For a more detailed view of the backend architecture, see the Backend Architecture section below.
# Backend Architecture
_**Disclaimer**: The backend architecture is a work in progress and is subject to change. The following diagram shows the current architecture of the backend based on the commit that is shown in the footer of the diagram._
![backend_architecture.svg](/static/img/backend_architecture.svg)
```mermaid
classDiagram
class Agent {
<<abstract>>
+sandbox_plugins: list[PluginRequirement]
}
class CodeActAgent {
+tools
}
Agent <|-- CodeActAgent
class EventStream
class Observation
class Action
Action --> Observation
Agent --> EventStream
class Runtime {
+connect()
+send_action_for_execution()
}
class ActionExecutionClient {
+_send_action_server_request()
}
class DockerRuntime
class LocalRuntime
class RemoteRuntime
Runtime <|-- ActionExecutionClient
ActionExecutionClient <|-- DockerRuntime
ActionExecutionClient <|-- LocalRuntime
ActionExecutionClient <|-- RemoteRuntime
class ActionExecutionServer {
+/execute_action
+/alive
}
class BashSession
class JupyterPlugin
class BrowserEnv
ActionExecutionServer --> BashSession
ActionExecutionServer --> JupyterPlugin
ActionExecutionServer --> BrowserEnv
Agent --> Runtime
Runtime ..> ActionExecutionServer : REST
```
<details>
<summary>Updating this Diagram</summary>
<div>
The generation of the backend architecture diagram is partially automated.
The diagram is generated from the type hints in the code using the py2puml
tool. The diagram is then manually reviewed, adjusted and exported to PNG
and SVG.
We maintain architecture diagrams inline with Mermaid in this MDX.
## Prerequisites
- Running python environment in which openhands is executable
(according to the instructions in the README.md file in the root of the repository)
- [py2puml](https://github.com/lucsorel/py2puml) installed
## Steps
1. Autogenerate the diagram by running the following command from the root of the repository:
`py2puml openhands openhands > docs/architecture/backend_architecture.puml`
2. Open the generated file in a PlantUML editor, e.g. Visual Studio Code with the PlantUML extension or [PlantText](https://www.planttext.com/)
3. Review the generated PUML and make all necessary adjustments to the diagram (add missing parts, fix mistakes, improve positioning).
_py2puml creates the diagram based on the type hints in the code, so missing or incorrect type hints may result in an incomplete or incorrect diagram._
4. Review the diff between the new and the previous diagram and manually check if the changes are correct.
_Make sure not to remove parts that were manually added to the diagram in the past and are still relevant._
5. Add the commit hash of the commit that was used to generate the diagram to the diagram footer.
6. Export the diagram as PNG and SVG files and replace the existing diagrams in the `docs/architecture` directory. This can be done with (e.g. [PlantText](https://www.planttext.com/))
Guidance:
- Edit the Mermaid blocks directly (flowchart/classDiagram).
- Quote labels and edge text for GitHub preview compatibility.
- Keep relationships concise and reflect stable abstractions (agents, runtime client/server, plugins).
- Verify accuracy against code:
- openhands/runtime/impl/action_execution/action_execution_client.py
- openhands/runtime/impl/docker/docker_runtime.py
- openhands/runtime/impl/local/local_runtime.py
- openhands/runtime/action_execution_server.py
- openhands/runtime/plugins/*
- Build docs locally or view on GitHub to confirm diagrams render.
</div>
</details>

View File

@ -52,7 +52,7 @@ graph TD
2. Image Building: OpenHands builds a new Docker image (the "OH runtime image") based on the user-provided image. This new image includes OpenHands-specific code, primarily the "runtime client"
3. Container Launch: When OpenHands starts, it launches a Docker container using the OH runtime image
4. Action Execution Server Initialization: The action execution server initializes an `ActionExecutor` inside the container, setting up necessary components like a bash shell and loading any specified plugins
5. Communication: The OpenHands backend (`openhands/runtime/impl/eventstream/eventstream_runtime.py`) communicates with the action execution server over RESTful API, sending actions and receiving observations
5. Communication: The OpenHands backend (client: `openhands/runtime/impl/action_execution/action_execution_client.py`; runtimes: `openhands/runtime/impl/docker/docker_runtime.py`, `openhands/runtime/impl/local/local_runtime.py`) communicates with the action execution server over RESTful API, sending actions and receiving observations
6. Action Execution: The runtime client receives actions from the backend, executes them in the sandboxed environment, and sends back observations
7. Observation Return: The action execution server sends execution results back to the OpenHands backend as observations
@ -72,7 +72,7 @@ Check out the [relevant code](https://github.com/All-Hands-AI/OpenHands/blob/mai
### Image Tagging System
OpenHands uses a three-tag system for its runtime images to balance reproducibility with flexibility.
Tags may be in one of 2 formats:
The tags are:
- **Versioned Tag**: `oh_v{openhands_version}_{base_image}` (e.g.: `oh_v0.9.9_nikolaik_s_python-nodejs_t_python3.12-nodejs22`)
- **Lock Tag**: `oh_v{openhands_version}_{16_digit_lock_hash}` (e.g.: `oh_v0.9.9_1234567890abcdef`)
@ -119,18 +119,52 @@ This tagging approach allows OpenHands to efficiently manage both development an
2. The system can quickly rebuild images when minor changes occur (by leveraging recent compatible images)
3. The **lock** tag (e.g., `runtime:oh_v0.9.3_1234567890abcdef`) always points to the latest build for a particular base image, dependency, and OpenHands version combination
## Volume mounts: named volumes and overlay
OpenHands supports both bind mounts and Docker named volumes in SandboxConfig.volumes:
- Bind mount: "/abs/host/path:/container/path[:mode]"
- Named volume: "volume:<name>:/container/path[:mode]" or any non-absolute host spec treated as a named volume
Overlay mode (copy-on-write layer) is supported for bind mounts by appending ":overlay" to the mode (e.g., ":ro,overlay").
To enable overlay COW, set SANDBOX_VOLUME_OVERLAYS to a writable host directory; per-container upper/work dirs are created under it. If SANDBOX_VOLUME_OVERLAYS is unset, overlay mounts are skipped.
Implementation references:
- openhands/runtime/impl/docker/docker_runtime.py (named volumes in _build_docker_run_args; overlay mounts in _process_overlay_mounts)
- openhands/core/config/sandbox_config.py (volumes field)
## Runtime Plugin System
The OpenHands Runtime supports a plugin system that allows for extending functionality and customizing the runtime environment. Plugins are initialized when the runtime client starts up.
The OpenHands Runtime supports a plugin system that allows for extending functionality and customizing the runtime environment. Plugins are initialized when the action execution server starts up inside the runtime.
Check [an example of Jupyter plugin here](https://github.com/All-Hands-AI/OpenHands/blob/ecf4aed28b0cf7c18d4d8ff554883ba182fc6bdd/openhands/runtime/plugins/jupyter/__init__.py#L21-L55) if you want to implement your own plugin.
## Ports and URLs
*More details about the Plugin system are still under construction - contributions are welcomed!*
- Host port allocation uses file-locked ranges for stability and concurrency:
- Main runtime port: find_available_port_with_lock on configured range
- VSCode port: SandboxConfig.sandbox.vscode_port if provided, else find_available_port_with_lock in VSCODE_PORT_RANGE
- App ports: two additional ranges for plugin/web apps
- DOCKER_HOST_ADDR (if set) adjusts how URLs are formed for LocalRuntime/Docker environments.
- VSCode URL is exposed with a connection token from the action execution server endpoint /vscode/connection_token and rendered as:
- Docker/Local: http://localhost:{port}/?tkn={token}&folder={workspace_mount_path_in_sandbox}
- RemoteRuntime: scheme://vscode-{host}/?tkn={token}&folder={workspace_mount_path_in_sandbox}
References:
- openhands/runtime/impl/docker/docker_runtime.py (port ranges, locking, DOCKER_HOST_ADDR, vscode_url)
- openhands/runtime/impl/local/local_runtime.py (vscode_url factory)
- openhands/runtime/impl/remote/remote_runtime.py (vscode_url mapping)
- openhands/runtime/action_execution_server.py (/vscode/connection_token)
Examples:
- Jupyter: openhands/runtime/plugins/jupyter/__init__.py (JupyterPlugin, Kernel Gateway)
- VS Code: openhands/runtime/plugins/vscode/* (VSCodePlugin, exposes tokenized URL)
- Agent Skills: openhands/runtime/plugins/agent_skills/*
Key aspects of the plugin system:
1. Plugin Definition: Plugins are defined as Python classes that inherit from a base `Plugin` class
2. Plugin Registration: Available plugins are registered in an `ALL_PLUGINS` dictionary
2. Plugin Registration: Available plugins are registered in `openhands/runtime/plugins/__init__.py` via `ALL_PLUGINS`
3. Plugin Specification: Plugins are associated with `Agent.sandbox_plugins: list[PluginRequirement]`. Users can specify which plugins to load when initializing the runtime
4. Initialization: Plugins are initialized asynchronously when the runtime client starts
5. Usage: The runtime client can use initialized plugins to extend its capabilities (e.g., the JupyterPlugin for running IPython cells)
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