Blade Agent 沙盒化架构分析

提案:将整个智能体(含 LLM 调用)完全运行在 Docker 沙盒内

2026-06-17

现状:分裂的执行模型

Host 端(主机进程)

  • LLM 调用 & 流式解析
  • Tool dispatch & Hook 管道
  • Session 管理 & 历史持久化
  • Compaction(上下文压缩)
  • Fork / Resume 子智能体
  • Skill 解析 & 语义搜索
  • Memory 注入
  • Projection 构建 → WebSocket 推流

约 17,000 行核心代码

沙盒端(Docker 容器)

  • Bash 命令执行
  • 文件读写操作
  • 技能 Runner 执行
  • 依赖安装(pip / npm)

无状态执行器,通过 docker exec 桥接

Host (Python)                          Sandbox (Docker)
┌─────────────────────┐                ┌──────────────────┐
│  ChatOrchestrator   │                │                  │
│  ├─ agent_loop()    │  docker exec   │  bash / file /   │
│  ├─ LLM Client  ───────────────────▶│  skill runner    │
│  ├─ Tool Registry   │  ◀─────────── │                  │
│  ├─ Session Mgr     │   stdout/exit  │                  │
│  └─ SocketBridge ──▶│ WebSocket      └──────────────────┘
└─────────────────────┘

提案:全沙盒化

Host (精简)                            Sandbox (Docker)
┌─────────────────────┐                ┌──────────────────────┐
│  容器管理            │  docker exec   │  完整 agent 进程      │
│  事件流转发          │  ◀──stdout──── │  ├─ agent_loop()     │
│  WebSocket 推流      │                │  ├─ LLM Client      │
│  持久化存储?        │                │  ├─ Tool Registry    │
└─────────────────────┘                │  ├─ Session Mgr?    │
                                       │  ├─ Skill 系统       │
                                       │  └─ 本地 bash/file   │
                                       └──────────────────────┘

核心想法:host 退化为「容器管理 + 事件转发」,智能体决策和工具执行都在同一个进程内完成。

问题一:能否大幅简化项目?

+ 能简化的部分

模块 代码量 原因
SessionExecutionRuntime ~800 行 session routing 层不再需要
SandboxProvider / DockerSandboxProvider ~3000 行 Docker exec 桥接全部消除
BashToolProvider / FileToolProvider 部分简化 直接用 subprocess / os,无需代理
tool_host/ IO 隔离约束 不再需要强制走 runtime protocol

预估可消除约 ~3,800 行桥接代码(占总量 ~20%)

- 无法简化的部分(核心业务逻辑)

模块 代码量 原因
agent_loop() ~1,100 行 核心循环逻辑,跟执行位置无关
ChatOrchestrator ~1,000 行 编排、prompt 构建、compaction、memory
Session 管理 ~1,500 行 历史持久化、分支、rewind
Skill 系统 ~3,500 行 语义搜索、解析、adapter 缓存
LLM Client ~800 行 模型适配、流式处理、image 压缩
Engine 组装 (mixins) ~4,000 行 fork/resume、background、replay
Hook & Event & Projection ~1,000+ 行 业务管道,不随执行位置变化

约 ~13,000 行业务代码不会因架构变更而简化(占总量 ~80%)

20% 可消除
可消除:sandbox 桥接层
不变:核心业务逻辑

问题二:能否让智能体更轻巧?

关键问题:复杂性不会消失,只是搬家

Host 确实变轻了,但容器内进程接管了全部复杂性。而且会引入新的问题:

1

状态持久化悖论

Session index (SQLite)、history (JSONL) 目前在 host 管理。如果 agent 在容器内,要么容器维护状态(容器销毁 = 数据丢失),要么 RPC 回传到 host —— 又回到了「桥接」模式,只是方向反了。

2

多用户隔离开销

目前一个 host 进程服务所有用户,session routing 隔离。每个 session 一个容器内 agent 进程 → 容器调度 + 内存开销显著增加。

3

API Key 安全边界

LLM API key 需要注入到每个容器。当前只有 host 进程持有密钥,安全边界清晰。容器化后,每个沙盒都是攻击面。

4

事件流通道

目前 host 内存中 EventHandler → SocketBridge,零延迟。容器化后需要新的事件通道(stdout JSON lines / Unix socket / gRPC),增加序列化开销和调试复杂度。

5

全局资源访问

Compaction、Memory、Skill Registry 等需要全局资源。要么部署进容器(镜像膨胀),要么 API 回调 host(又是 RPC 桥接,只是方向反了)。

桥接方向对比

现在:  Host ──docker exec──▶ Sandbox     (工具执行桥接)
提案:  Host ◀──RPC/stdout── Sandbox      (状态/资源桥接)

桥接层并没有消失,只是换了方向和内容。

问题三:嵌入式部署可能性

嵌入式的诉求是合理的,但正确的路径不是「搬进容器」,而是做一个可独立运行的 agent binary

容器化方案(不适合嵌入式)

  • 依赖 Docker daemon
  • 容器镜像体积大(当前 sandbox ~2GB)
  • 冷启动慢
  • 资源开销高(内存 768MB+)
  • 嵌入式设备通常跑不了 Docker

CLI Agent 方案(适合嵌入式)

  • core + 精简 host 打包为单进程
  • stdin/stdout 做事件通道
  • 工具直接本地执行(无 Docker)
  • 轻量级,可跑在 ARM/嵌入式
  • 类似 Claude Code CLI 的模式

结论

不建议走「整个 agent 跑在沙盒里」这条路

  1. 1. 收益有限 — 只消除 ~20% 的桥接代码,但引入新的事件通道、状态同步、安全管理复杂性,净效果可能为负
  2. 2. 核心复杂性无法回避 — orchestrator / session / skill / compaction / hook 跟执行位置无关
  3. 3. 架构倒退 — 当前 host 有状态 + 容器无状态 是清晰的职责分离;全沙盒化会混淆边界

替代建议

A

简化项目 → 精简 Engine mixin 架构

Engine 的 4,000 行 mixin 是真正的复杂性根源。将 Engine 从「上帝对象 + mixin 拼装」重构为「组合式服务」,效果远大于搬迁执行位置。

B

轻巧化 → 把 core 做成独立 SDK

core 只包含 loop + protocols(类似 Anthropic Agent SDK)。host 变成「BladeAI 的一种实现」。第三方可以用 core 接自己的 LLM / 工具 / 存储。

C

嵌入式 → CLI Agent 模式

core + 精简 host(去掉 Docker / Server)打包为单进程,stdin/stdout 事件流。可跑在 ARM / 嵌入式设备。工具执行直接本地,无需容器。