菜单

运行时实现

相关源文件

目的与范围

本文档详细介绍了OpenHands中的各种运行时实现,它们为执行代理操作提供了沙盒环境。每个运行时实现都提供了适合不同部署场景(从本地开发到安全生产环境)的特定行为和优势。

有关运行时镜像如何构建和配置的信息,请参阅运行时构建。有关在沙盒中运行的操作执行服务器的详细信息,请参阅操作执行服务器

运行时系统架构

OpenHands中的运行时系统充当代理操作的执行环境。它提供了一个标准化的接口,用于在不同执行平台上的操作,如运行shell命令、读/写文件、浏览网站和执行代码。

运行时类层次结构

来源:openhands/runtime/impl/docker/docker_runtime.py63 openhands/runtime/impl/remote/remote_runtime.py37 openhands/runtime/impl/modal/modal_runtime.py28 openhands/runtime/impl/runloop/runloop_runtime.py22 tests/runtime/conftest.py14-19

运行时接口

来源:openhands/runtime/base.py89-624

基本运行时组件

运行时基类

The Runtime 基类定义了所有运行时实现必须满足的接口。它处理

  1. 事件流订阅和处理
  2. 插件管理
  3. 环境变量设置
  4. 文件操作
  5. 操作执行路由

核心功能包括

  • 从事件流处理代理操作
  • 管理运行时环境的生命周期
  • 提供文件操作、shell命令和浏览器交互的标准接口
  • 处理存储库克隆和设置

来源:openhands/runtime/base.py89-624

ActionExecutionClient

The ActionExecutionClient 类作为与操作执行服务器通信的运行时实现的基础。该服务器在沙盒内运行,并执行实际的命令。

主要职责

  • 与操作执行服务器的 HTTP 通信
  • 身份验证和会话管理
  • 错误处理与重试
  • 超时管理

来源:openhands/runtime/impl/action_execution/action_execution_client.py(从运行时实现的导入推断)

运行时实现细节

DockerRuntime

The DockerRuntime 在本地机器上的 Docker 容器内执行操作,提供隔离性,同时保持对本地资源的访问。

DockerRuntime 架构

主要实现细节

  • 容器名称遵循模式:openhands-runtime-{sid}
  • 使用 docker.from_env() 初始化 Docker 客户端
  • 端口范围:执行服务器(30000-39999),VSCode(40000-49999),应用程序(50000-59999)
  • 通过 use_host_network 配置支持主机网络模式
  • 通过 maybe_build_runtime_container_image() 构建运行时镜像
  • 当启用 DEBUG_RUNTIME 时,通过 LogStreamer 类进行日志流式传输
  • 暂停/恢复功能会将环境变量保存在 .bashrc

核心方法

  • init_container():创建并启动 Docker 容器
  • _attach_to_container():附加到现有容器
  • wait_until_alive():轮询容器状态并重试
  • _process_volumes():处理卷挂载配置

来源:openhands/runtime/impl/docker/docker_runtime.py63-543

RemoteRuntime

The RemoteRuntime 通过 REST API 连接到远程执行环境,提供基于云的沙盒执行。

RemoteRuntime 架构

主要实现细节

  • 需要 config.sandbox.api_key 进行身份验证
  • 使用 RemoteRuntimeBuilder 进行自定义镜像构建
  • 运行时生命周期:/start/runtime/{id} 轮询 → 就绪状态
  • 使用 X-Session-API-Key 标头进行会话管理
  • 支持运行时类:sysbox-runcgvisor (默认)
  • Pod 状态监控:readypendingrunningfailedcrashloopbackoff

核心方法

  • _start_or_attach_to_runtime():主初始化逻辑
  • _check_existing_runtime():按会话 ID 查找现有运行时
  • _build_runtime():使用运行时构建器创建自定义镜像
  • _start_runtime():POST 到 /start,包含运行时配置
  • _resume_runtime():POST 到 /resume 以恢复暂停的运行时
  • _wait_until_alive_impl():轮询运行时状态直到就绪

错误处理

  • 当启用了 keep_runtime_alive 时,在收到 503 响应时自动恢复
  • 具有指数退避的重试逻辑,用于网络错误
  • 云环境的资源因子缩放

来源:openhands/runtime/impl/remote/remote_runtime.py37-596

ModalRuntime

The ModalRuntime 利用 Modal 的云平台进行无服务器执行环境。

主要功能

  • 与 Modal 云平台集成
  • 创建和管理 Modal 沙盒
  • 构建自定义运行时镜像
  • 设置安全隧道以访问操作执行服务器
  • 支持环境变量管理
  • 提供 VSCode 集成

来源:openhands/runtime/impl/modal/modal_runtime.py28-283

CLIRuntime

The CLIRuntime 使用直接的 shell 命令在主机系统上执行操作,具有工作区限制和简化的执行。

CLIRuntime 架构

主要实现细节

  • 使用 bash -c 执行命令
  • 强制执行工作区目录限制
  • 不支持交互式输入,如 C-c 中断
  • 对于不支持的操作(浏览、IPython),返回 ErrorObservation
  • 简单的超时机制,无交互式进程管理
  • 工作目录保持为绝对主机路径

行为差异

  • 多个换行符分隔的命令在单个 bash -c 调用中执行
  • 命令之间没有持久的 shell 会话
  • 有限的进程交互能力
  • 代理尝试使用不支持的功能时的错误处理

用例:

  • 通过受控环境进行自动化测试
  • 简单的命令执行,没有完整的沙盒开销
  • 需要最少运行时设置的开发场景

来源:tests/runtime/test_bash.py56-76 tests/runtime/conftest.py14 tests/runtime/test_bash.py358-394

DaytonaRuntime

The DaytonaRuntime 集成了 Daytona 平台,该平台提供安全的开发环境。

主要功能

  • 创建和管理 Daytona 工作区
  • 建立安全隧道进行通信
  • 支持会话创建和管理
  • 提供 VSCode 集成
  • 处理工作区启动和配置

来源:tests/runtime/conftest.py15

RunloopRuntime

The RunloopRuntime 使用 Runloop 的 Devbox 作为执行环境。

主要功能

  • 创建和管理 Runloop Devbox
  • 设置安全通信隧道
  • 配置资源分配
  • 提供 VSCode 集成
  • 处理环境设置

来源:openhands/runtime/impl/runloop/runloop_runtime.py22-192

LocalRuntime

The LocalRuntime 直接在本地机器上执行操作,不进行容器化,主要用于开发和测试。

LocalRuntime 架构

主要实现细节

  • 无容器化:直接在主机系统上运行
  • 为每个会话创建临时工作区目录
  • 使用 subprocess.Popen 启动操作执行服务器
  • 直接文件系统访问,无沙盒
  • 通过 find_available_tcp_port() 进行端口分配
  • 进程生命周期通过 Python 子进程管理

核心方法

  • 进程启动和关闭管理
  • 端口分配和绑定
  • 临时目录创建和清理
  • 直接文件系统操作

安全警告:

  • 与主机系统隔离
  • 完全文件系统访问
  • 可以在主机上执行任意命令
  • 仅适用于开发和测试环境

来源: tests/runtime/conftest.py17 tests/runtime/test_bash.py18

运行时选择与配置

沙箱配置

运行时行为通过 SandboxConfig 类进行配置,该类包含以下设置:

选项描述默认
remote_runtime_api_url远程运行时 API 的 URLhttp://:8000
local_runtime_url本地运行时的 URLhttp://
base_container_image构建运行时的基础镜像nikolaik/python-nodejs:python3.12-nodejs22
runtime_container_image要使用的预构建运行时镜像
keep_runtime_alive会话结束后保持运行时活动
pause_closed_runtimes暂停而非停止运行时True
timeout操作执行的超时时间120
enable_auto_lint启用文件的自动 linting
platform构建镜像的平台
remote_runtime_class远程执行的运行时类(默认为 gvisor)
enable_gpu启用 GPU 支持
remote_runtime_resource_factor资源缩放因子1

来源: openhands/core/config/sandbox_config.py6-101

运行时生命周期管理

运行时生命周期由 AgentSession 类管理,该类负责:

  1. 基于配置初始化运行时
  2. 建立到沙箱的连接
  3. 如果指定,则克隆仓库
  4. 插件设置和环境配置
  5. 优雅关闭和资源清理

来源: openhands/server/session/agent_session.py255-335 openhands/server/session/agent_session.py185-209

运行时选择

运行时在会话初始化期间根据配置进行选择

来源: tests/runtime/conftest.py125-141

安全考量

不同的运行时实现提供不同级别的安全隔离

运行时隔离级别备注
DockerRuntime基于容器的隔离,可选 GPU/设备访问
RemoteRuntime非常高远程执行,具有可配置的隔离(sysbox/gvisor)
ModalRuntime非常高无服务器环境,具有托管隔离
DaytonaRuntime专门构建的安全执行环境
RunloopRuntime托管执行环境
LocalRuntime直接在主机上运行,无隔离
CLIRuntime直接主机执行,仅有工作区约束

选择运行时时,请考虑

  • 所需的代码隔离级别
  • 资源需求
  • 网络访问需求
  • 持久性要求
  • 开发与生产用途
  • 所需的交互功能(IPython、浏览器自动化)

常见的运行时命令执行流程

尽管实现方式不同,但所有运行时在执行操作的流程上都相似

来源: openhands/runtime/base.py242-311

运行时插件支持

所有运行时都支持用于扩展功能的插件

  • VSCode 集成用于开发
  • Jupyter/IPython 用于交互式代码执行
  • 浏览器自动化
  • 基于用例的其他工具

插件在运行时启动期间初始化,并通过 plugins 参数进行配置。

来源: openhands/runtime/base.py104-129

结论

OpenHands 运行时系统提供了一个灵活的架构,用于在各种环境中执行代理操作。通过支持多种运行时实现,它可以适应不同的部署场景、安全需求和资源限制,同时为代理交互保持一致的接口。

运行时的选择取决于具体用例,选项范围从本地开发环境到安全的云解决方案,每种都有其自身的优点和缺点,涉及设置复杂性、隔离性和资源管理。