OpenHands 源码解析 · 第 6 讲
OpenHands 源码解析系列 第 6 讲:沙箱生命周期 (Docker/K8s/Remote) 基于 OpenHands 源码 · 2026-08-02 一、沙箱在 OpenHands 中的角色 OpenHands 的 Agent 不直接在宿主机上执行命令,而是运行在 沙箱 (Sandbox) 中。沙箱提供隔离的执行环境,Agent 的所有文件系统操作、命令执行、代码编译都在沙箱内完成。 📦 源码位置 openhands/app_server/sandbox/ 核心文件:17 个 Python 模块,约 3500 行代码 OpenHands 实现了 三种沙箱后端 ,通过统一的 SandboxService 抽象层切换: 🔹 DockerSandboxService — 本地 Docker 容器,适合开发环境 🔹 RemoteSandboxService — K8s 集群远程运行时,适合生产部署 🔹 ProcessSandboxService — 进程级隔离,适合测试/轻量场景 二、SandboxService 抽象层 所有沙箱实现共享同一个抽象基类。源码: 📄 openhands/app_server/sandbox/sandbox_service.py (第 112-173 行) class SandboxService(ABC): """Service for accessing sandboxes in which conversations may be run.""" @abstractmethod async def search_sandboxes( self, page_id: str | None = None, limit: int = 100, ) -> SandboxPage: """Search for sandboxes.""" @abstractmethod async def get_sandbox(self, sandbox_id: str) -> SandboxInfo | None: """Get a single sandbox. Return None if the sandbox was not found.""" @abstractmethod async def get_sandbox_by_session_api_key( self, session_api_key: str ) -> SandboxInfo | None: """Get a single sandbox by session API key.""" @abstractmethod async def start_sandbox( self, sandbox_spec_id: str | None = None, sandbox_id: str | None = None ) -> SandboxInfo: """Begin the process of starting a sandbox.""" @abstractmethod async def resume_sandbox(self, sandbox_id: str) -> bool: """Begin the process of resuming a sandbox.""" @abstractmethod async def pause_sandbox(self, sandbox_id: str) -> bool: """Begin the process of pausing a sandbox.""" @abstractmethod async def delete_sandbox(self, sandbox_id: str) -> bool: """Begin the process of deleting a sandbox (which may involve stopping it).""" 设计要点: 🔹 所有方法都是 async ,支持高并发 🔹 search_sandboxes 返回分页结果 SandboxPage 🔹 通过 SandboxServiceInjector 注入,依赖注入框架自动选择后端 三、沙箱状态机 沙箱有五种状态,定…
阅读全文:OpenHands 源码解析 第 6 讲