DeerFlow Backend Sandbox 执行环境分析
本文档分析了在 deer-flow 后端体系中,代码沙箱执行环境(Sandbox)的架构设计与实现原理。沙箱主要用于让 AI 或用户安全、隔离地执行代码块(Shell 命令、读写文件等)。
1. 核心抽象设计 (Core Abstractions)
Section titled “1. 核心抽象设计 (Core Abstractions)”后端的沙箱系统被设计为一个标准的面向对象接口体系,具有极高的解耦和可替换性:
1.1 Sandbox (执行层基类)
Section titled “1.1 Sandbox (执行层基类)”定义在 packages/harness/deerflow/sandbox/sandbox.py。
它是一个标准的接口层,规定了所有沙箱必须提供以下能力:
execute_command(command):执行终端命令。read_file(path)/write_file(path, content)/update_file:文本与二进制文件的 I/O 操作。list_dir(path, max_depth):目录遍历。
1.2 SandboxProvider (生命周期、路由与缓存引擎)
Section titled “1.2 SandboxProvider (生命周期、路由与缓存引擎)”定义在 sandbox_provider.py,但在 aio_sandbox_provider.py 中有极其高级的实现。
它是单例管理器,负责沙箱生命周期的调度:
acquire:获取或新建一个特定线程的沙箱空间。在 AIO Provider 中,它实现了一个极致的三层缓存架构:- 第一层 (In-process cache):极速复用当前进程已挂载的活跃沙箱。
- 第二层 (Warm pool):将释放的沙箱置于“保暖池”(容器不销毁,只解除绑定),以便同一个 Thread 再次申请时“零冷启动”秒速复用。
- 第三层 (Cross-process Discovery):通过确定性哈希 ID(Deterministic ID)和跨进程文件锁(File Lock),让不同进程甚至不同 Pod 能够发现彼此启动的共享底层沙箱,解决多进程冲突。
get:根据 ID 提取已挂载的沙箱实例并在后台自动续签闲置过期时间 (Idle Timeout)。release:将闲置沙箱退回到保暖池,只有超过系统限定副本数(Replicas)或超时时才会真正执行销毁任务。
2. 具体实现机制 (Concrete Implementations)
Section titled “2. 具体实现机制 (Concrete Implementations)”目前系统中存在两种截然不同的沙箱实现策略:
2.1 本地宿主机伪沙箱 (LocalSandbox)
Section titled “2.1 本地宿主机伪沙箱 (LocalSandbox)”定义在 sandbox/local/local_sandbox.py。
这是一种非容器化的轻量级实现形式,直接在后端进程宿主机通过原生进程执行命令。
- 执行原理:底层使用了 Python 原生的
subprocess.run(command, shell=True)来直接执行 Bash/Zsh 脚本,这代表着它并没有真正的物理隔离,执行的是宿主机的直接命令。 - 智能路径映射机制(Path Mapping):为了让从外部或者习惯了容器化路径的工具能够平滑运行,它包含了一个精妙的正则拦截系统。
- 它在内存里维护了一套映射表(如把虚拟容器路径
/mnt/skills映射到真实的宿主物理路径/Users/...)。 - 在把用户的命令喂给
subprocess.run执行之前,它会先通过正则,把命令里出现的虚拟路径全部**替换(Resolve)**成真实的绝对路径。 - 当真实命令吐出 Output 日志时,它又会把这些真实的、可能泄漏隐私的绝对物理路径,全部**反向替换(Reverse Resolve)**回虚拟容器路径。实现了对大模型视角下的“路径伪装隔离”。
- 它在内存里维护了一套映射表(如把虚拟容器路径
2.2 容器化云原生沙箱 (AioSandbox 与 SandboxBackend)
Section titled “2.2 容器化云原生沙箱 (AioSandbox 与 SandboxBackend)”定义在社区模块 community/aio_sandbox/ 下。这是一套真正的物理级别的容器化隔离方案,被拆分为执行者(AioSandbox)和驱动引擎(SandboxBackend)两个维度:
- 执行器 (
AioSandbox) 通信隔离:所有的execute_command并不是本地 Subprocess,而是被转化为长超时的 HTTP REST API,发送给内部运行了agent-infra/sandbox服务的 Docker 容器。 - 底层驱动引擎 (
SandboxBackend):负责产生并调度这些隔离容器。它支持两种模式:RemoteSandboxBackend:连接远程 K8s / K3s 的 Provisioner,动态生成远端 Pod。LocalContainerBackend:直接按需在物理机上启动新的 Docker 容器,并分配闲置端口。特别地,在 macOS 系统下,它会优先检测并采用苹果官方原生支持的轻量级虚拟化方案 (Apple Container),仅在找不到时降级回退给 Docker。此设计极大优化了 Mac 上的 I/O 与执行速度。- 请求将指令发往由
agent-infra/sandbox提供的一个运行在大后方的 Docker 容器内部服务(默认为 HTTP API 监听)。 - 由该远程 Docker 容器内部安全地执行这些指令代码,并将结果 JSON(通常包含
result.data.output)返回给后端的AioSandbox包装实例。
3. 架构总结
Section titled “3. 架构总结”通过这套抽象实现,当 AI 大模型提出如 在命令行执行 python script.py 的需求时:
- 系统不需重构大模型逻辑,即可通过配置自由决定是采用零成本的本地直连替换(
LocalSandbox),还是高规格的容器 HTTP 远程直连(AioSandbox)。 - 两套底层驱动均共享同一个上层执行接口,达到了业务代码的高度复用。