Sandbox 为什么是 AI 中台的必选项:运行时隔离与 AI 架构演进
约 6247 字大约 21 分钟
2026-05-17
只要 AI 开始真正执行工具、脚本和外部调用,系统就会立刻从"生成文本"变成"执行动作"。一旦进入这个阶段,很多过去还能靠提示词约束的问题就会失效:模型可能会访问不该访问的网络、读写不该读写的目录、执行不该执行的脚本,或者在长链路里因为某个工具失控而把整个服务拖垮。
这就是为什么 AI 中台一旦进入可执行阶段,Sandbox 就不再是锦上添花,而是必选项。联犀在这一点上的做法并不是把所有执行都留在主服务里,而是把控制面和执行面拆开:aisvr 负责控制面,sandbox 负责实际运行循环,再通过容器级和容器内两层约束构建安全边界。
为什么 AI 运行时不能直接塞进主服务
很多系统在早期做 AI 能力时,会把"执行工具"简单理解成在现有服务进程里多跑一段脚本或多发几个 HTTP 请求。这在功能验证阶段当然方便,但问题也非常直接:主服务的稳定性和执行任务的风险被绑在了一起。
一旦运行时直接驻留在主服务里,工具执行和业务控制面就共享了同一个进程空间、同一套文件系统视野和同一组网络能力。模型如果触发了重型脚本、失控子进程、危险地址访问或异常长尾任务,首当其冲被拖垮的就是整个 AI 中台入口。换句话说,执行面不再是某种附加能力,而是反向成为主服务的风险源。
这也是联犀把执行层抽成独立 sandbox 服务的根本原因。aisvr 保留主数据模型、会话生命周期、Skill 元数据、知识加载、记忆编排和 HTTP/RPC 入口,sandbox 则专门承载 Agent 的工具 dispatch、脚本执行和 SSE 事件输出。
把执行层独立出来,带来的好处不只是安全。它让 AI 中台第一次拥有了一个可独立治理的执行平面:会话控制和任务执行可以分开管理,执行失败不会污染主控制面,平台能够围绕"启动、探活、停止、重建"来定义 AI 执行环境,而不是把执行过程揉进一个常驻服务线程里。
更重要的是,独立执行面让安全隔离终于有了抓手。联犀的 Sandbox 不是单点保护,而是两层结构:第一层是容器级隔离,把 sandbox 本身从主服务里隔开;第二层是容器内约束,通过 cgroup 限制资源、通过 netns + iptables + SOCKS5 限制网络、通过最小化挂载限制文件系统访问。容器解决的是宿主边界和生命周期问题,容器内约束解决的是任务边界和运行细节问题。两层都在,平台才不会把所有安全希望压在某一个开关上。
AI 中台的本质:让应用不必重复造轮子
当前很多团队做 AI 功能时,常见的做法是:每个业务应用各自接入 LLM、各自管理 Prompt、各自实现工具调用、各自处理记忆和会话。结果是客服系统有一套 AI 代码,设备管理系统又有一套,能源管理平台再有一套——能力同质化严重,重复建设成本极高,而且安全隔离水平参差不齐。
联犀 AI 中台的设计思路完全不同。它不是"又一个调用大模型的服务",而是一套可复用的 AI 执行基础设施:
- 应用只需要告诉中台"我要哪个 Agent 的哪个 Clone",剩下的事情——模型路由、工具编排、记忆加载、运行隔离——全部由中台处理
- 新的业务线不需要从零搭建 ReAct 循环、不需要自己管理容器生命周期、不需要重复做网络隔离
- 安全能力(Sandbox、网络限制、资源限制)统一由中台提供,而不是每个应用各自实现一套参差不齐的隔离方案
AgentGroup 是这个思路的关键组织单元。平台可以预先建设好几类标准分组——用户交互分组、设备分组、告警联动分组——每个分组都配备好对应的 Skills、MCP 工具和知识库。业务应用只需要申请一个 Agent、创建一个 Clone,就立刻拥有了完整的 AI 能力,而不需要关心底层执行细节。
这样,AI 能力从"每个应用自己开发"变成了"平台统一供给、应用按需接入"。
选型背后的数据:多种沙盒方案的资源消耗对比
Sandbox 不是抽象概念,它的工程价值直接体现在资源效率和可落地性上。联犀在确定当前方案之前,曾对七种代码执行/沙盒隔离方案做过系统的内存占用与部署复杂度横向对比,数据如下。
七方方案单实例内存对比
| 方案 | 单实例内存 | 5实例总计 | 15GB 可跑(估算) | 隔离级别 | 启动时间 |
|---|---|---|---|---|---|
| claw (Go 静态链接) | 2–3 MB | ~12 MB | ~5000+ | Docker 进程级 | <1s |
| Docker + Python | 15 MB | ~75 MB | ~560 | 进程级 | ~2s |
| OpenSandbox (docker runtime) | 18 MB | ~91 MB | ~467 | 进程级(Docker) | ~3s |
| CubeSandbox Alpine | 76 MB | — | ~98 | 硬件 VM | ~5s |
| microsandbox (libkrun) | 83 MB | ~415 MB | ~91 | 硬件 VM | <5s |
| CubeSandbox Ubuntu 512MB | 359 MB | — | ~20 | 硬件 VM | ~30s |
| CubeSandbox Ubuntu 2GB | 611 MB | — | ~12 | 硬件 VM | ~30s |
注:15GB 可跑数为估算值,未扣除系统开销和 Server 本身内存。
关键发现:
- claw(Go 静态链接) 是极致轻量的代表:单实例 RssAnon 仅 1.56MB,6 容器总和 17.65MB。它牺牲了多语言支持,但在 AI Agent 纯运行时节点的场景下密度极高。
- Docker / OpenSandbox 属于同一量级(15–18MB),OpenSandbox 的高约 20% 来自 cgroup 限制和容器配置的额外开销。OpenSandbox 的定位是沙盒编排平台(不是 VMM),默认 docker runtime 与标准 Docker 基本一致。
- VM 级轻量方案(CubeSandbox Alpine / microsandbox) 落在 75–85MB 区间。CubeSandbox Alpine 的内存分解为:hypervisor shim ~4MB、Guest OS 内核/页表 ~20MB、http.server ~15MB、envd ~43MB。Alpine 版启动后几乎瞬间稳定,没有 Ubuntu 版 25 秒持续增长的问题。
- VM 级标准方案(CubeSandbox Ubuntu) 因 systemd + 完整服务启动,内存从 50MB 增长到 610MB,需 25–30 秒才能稳定。换 Alpine 后内存从 359MB 降到 76MB,省了 79%。
同口径 PSS 实测(Python / Node 运行时)
| 场景 | 10 个总内存 | 单个平均 |
|---|---|---|
| 宿主机 Python idle | 32.473 MiB | 3.247 MiB |
| 容器内 Python idle | 30.227 MiB | 3.023 MiB |
| 宿主机 Node idle | 92.146 MiB | 9.215 MiB |
| 容器内 Node idle | 105.684 MiB | 10.568 MiB |
结论:Python 作为主控 runtime 更省资源;Node 可用,但 idle 成本更高;容器化后 idle 成本仍在可接受范围。10 个空闲容器总内存仅约 7.164 MiB,说明容器壳成本很低,"每 clone 一个容器"不会因空壳先拖垮资源。
容器启停延迟
| 指标 | 结果 |
|---|---|
| 启动平均 | 173.92 ms |
| 启动 P95 | 176.34 ms |
| 停止平均 | 158.09 ms |
| 停止 P95 | 164.87 ms |
这组数据说明 Session 驱动 runtime 启停在延迟上可接受,启停不是当前方案的主要瓶颈。
为什么最终选择了容器级而非 VM 级
从上面的数据可以清晰看出:联犀的 AI Agent 执行面需要支撑大量并发的轻量运行循环,而不是少量重型的完整 Linux 环境。VM 级隔离虽然更强,但单实例 76MB 起步、300MB+ 的常态消耗,在"一个 Agent 对应一个 Sandbox、一个 Sandbox 内可能运行多个 Clone"的架构下,密度和成本都无法接受。
claw(Go 静态链接)2–3MB 的单实例内存,配合 Docker 容器级隔离,在"足够安全"和"足够轻量"之间取得了当前阶段的最佳平衡。这也是下文讨论资源隔离机制时,默认以 Docker + cgroup 两层限制为基线的原因。
核心术语:AgentGroup、Agent、Clone、Sandbox
在讨论隔离机制之前,有必要先理清联犀 AI 中台的四个核心概念。它们构成了从"业务分组"到"执行隔离"的完整链路。
AgentGroup(助手分组)
AgentGroup 是按业务场景对 Agent 进行分组的逻辑单元。不同业务有不同的能力诉求,因此需要不同的配置边界。联犀当前典型的分组类型包括:
- 用户交互分组:面向终端用户的对话助手,比如客服、导购、个人助理。每个用户可以获得自己的专属 Clone。
- 设备分组:面向物联网设备的智能体,比如小智语音助手。每个物理设备对应一个 Clone,拥有该设备的物模型知识和控制权限。
- 告警联动分组:面向自动化运维场景,负责接收告警、分析根因、触发联动动作。
每个 AgentGroup 可以配置自己的 SystemPrompt、LLM 模型、MCP 服务列表和 Skill 列表。Agent 加入分组后,默认继承这些配置,也可以在自己的级别做覆盖。
Agent(智能体)
Agent 是执行能力的定义单元。它描述了一个智能体能做什么:使用哪些 Skill、调用哪些 MCP 工具、遵循什么样的系统提示词。Agent 必须属于一个 AgentGroup,从而确定自己的业务归属和默认能力集。
在运行时架构中,一个 Sandbox 对应一个 Agent。也就是说,Sandbox 是 Agent 的执行载体,Agent 的所有运行循环都在其对应的 Sandbox 容器中发生。
Clone(数字分身)
Clone 是 Agent 的"实例化"产物。一个 Agent 可以有多个 Clone,每个 Clone 拥有独立的记忆、人设和会话历史。
举例来说,一个"客服 Agent"可能有上千个 Clone,每个 Clone 服务一个具体的用户。这些 Clone 共享同一个 Agent 的 Skill 和工具能力,但各自记住不同用户的偏好、历史和上下文。同样,一个"小智设备 Agent"可能有几十个 Clone,每个 Clone 对应家里的一台空调、一盏灯或一把智能锁。
Sandbox(沙箱执行环境)
Sandbox 是 Agent 的独立执行容器。它负责:
- 承载 Agent 的运行循环(ReAct 循环、tool dispatch)
- 执行 Skill 中的脚本(Python、Node、Shell)
- 输出 SSE 事件流(text_delta、tool_call_start、done 等)
- 施加资源限制(CPU、内存、进程数)
- 施加网络隔离(受限 netns、iptables、SOCKS5 代理)
- 管理工作空间(workspace 挂载与隔离)
一个 Sandbox 容器内,多个 Clone 通过工作空间目录实现文件级隔离,而不是每个 Clone 独占一个容器。这大大减少了容器数量,同时仍保持了 clone 之间的边界。
Sandbox 与 Agent、Clone 的架构关系
这四个概念按"业务分组 → 能力定义 → 实例分化 → 执行隔离"的层次组织起来:
关键设计要点:
- AgentGroup 决定业务边界:不同分组的 Agent 不会共享配置,设备分组的 Agent 不会意外加载客服分组的 Skill。
- Agent 决定执行容器:一个 Agent 对应一个 Sandbox 容器,容器生命周期跟随 Agent 的启停管理。
- Clone 决定隔离粒度:同一个 Sandbox 内的多个 Clone,通过各自独立的 workspace 目录实现文件隔离,通过各自的会话上下文实现逻辑隔离。
- 控制面保持真相源:无论 Sandbox 如何启停重建,Agent、Clone、Session、Memory 的权威状态始终保留在
aisvr和数据库中。
AgentGroup 按业务分组的隔离逻辑
AgentGroup 的存在不只是为了方便管理,它实际上定义了不同业务场景下的安全边界和能力边界。
不同分组的典型差异:
| 维度 | 用户交互分组 | 设备分组 | 告警联动分组 |
|---|---|---|---|
| 典型 Clone 数量 | 多(按用户) | 中(按设备) | 少(按规则) |
| 主要 Skill 类型 | 查询、对话、推荐 | 控制、状态读取、联动 | 分析、决策、通知 |
| MCP 服务 | 业务系统 API | 物模型、设备接入 | 告警平台、通知通道 |
| 知识库内容 | 产品文档、用户手册 | 设备规格、故障码 | 运维 SOP、历史案例 |
| 网络访问策略 | 受限出网 | 内网设备服务 + 受限出网 | 内部运维网络 + 通知网关 |
| SystemPrompt 风格 | 亲切、服务导向 | 指令精确、口语化 | 严谨、结构化 |
这种分组隔离的意义在于:一个设备分组的 Clone 永远不会因为配置错误而调用到客服分组的工单 MCP,也不会因为知识库混用而向用户输出设备内部的技术故障码。每个业务场景在自己的 AgentGroup 内闭环运行,能力边界清晰可控。
资源隔离的实现机制
资源限制不是配几个数字就能了事,关键在于"谁来执行限制"和"限制失效时怎么办"。联犀的资源隔离同样分为两层,每层都有明确的职责和降级策略。
第一层:Docker 容器级资源限制
aisvr 通过 Docker Engine API 创建 sandbox 容器时,通过 HostConfig 施加整体资源上限:
| 资源 | 默认值 | 配置字段 | 说明 |
|---|---|---|---|
| 内存 | 3072 MB | ContainerMemoryMB | 硬限制,超限时触发 OOM |
| CPU | 2 核(200%) | ContainerCPUQuota | 按百分比配置,200 = 2 核 |
| 进程数 | 512 | ContainerPidsLimit | 防止容器内 fork bomb |
这一层是"兜底"——无论容器内部发生什么,单个 Agent 的 sandbox 容器最多只能消耗上述资源,不会拖垮宿主机。
第二层:容器内 cgroup v2 进程级限制
sandbox 容器内部,每个任务子进程进一步通过 cgroup v2 施加更细粒度的限制:
| 资源 | 默认值 | 限制方式 | 说明 |
|---|---|---|---|
| CPU | 25%(0.25 核) | cpu.max | quota + period 模式,如 25000 100000 |
| 内存 | 256 MB | memory.max | 硬限制,同时 memory.swap.max = 0 禁用 swap |
| 进程数 | 32 | pids.max | 单任务进程树上限 |
实现方式:任务启动时动态创建子 cgroup(如 /sys/fs/cgroup/sandbox_<父PID>_<子PID>),将任务进程写入 cgroup.procs,任务结束后清理并删除 cgroup。
降级策略:cgroup 不可用时回退到 prlimit
Docker 环境下,容器内的 /sys/fs/cgroup 通常为只读挂载,无法创建子 cgroup。此时系统会自动降级:
- 检测机制:任务启动前尝试创建测试 cgroup 目录,若返回
EROFS(只读文件系统)则判定 cgroup 不可用 - 降级行为:使用系统
prlimit命令包装执行,通过--as限制虚拟地址空间、通过--nproc限制进程数 - 当前策略:由于 Docker 容器级限制已提供足够兜底,prlimit 降级方案主要保留结构,以便在裸机或 K8s 环境下 cgroup 可写时启用更精细的任务级限制
aisvr 内嵌执行路径的资源限制
除 Docker sandbox 容器外,aisvr 还内嵌了 PicoSandboxRunner 执行路径(直接启动 picoclaw 子进程)。该路径同样实现了 ResourceLimiter,默认限制为 CPU 50%、内存 512 MB、进程数 64,并通过相同的 cgroup v2 + prlimit 降级机制生效。
文件大小与 workspace 配额
除运行时资源外,平台还对持久化数据施加限制:
| 限制项 | 默认值 | 说明 |
|---|---|---|
| 单文件大小 | 100 MB | 防止单个产物膨胀 |
| Workspace 总大小 | 1 GB | 通过目录遍历计算总占用 |
| 任务超时 | 300 秒(5 分钟) | 防止长链路任务挂死 |
关键设计要点:
- 容器级限制是"硬 ceiling",无论如何不会突破
- cgroup 进程级限制是"软 partition",在单容器多任务场景下防止某个任务独占资源
- 降级机制保证即使环境受限(如 Docker),资源隔离也不会完全失效
- 所有限制都有日志记录,便于排查"为什么任务被杀"或"为什么执行慢"
文件系统隔离:Clone 级 workspace 边界
AI 一旦能够执行脚本,就天然会与文件系统打交道。
如果 workspace 只是一个方便写文件的目录,这件事看起来没什么问题;但如果 workspace 没有边界,风险就会非常现实:不同 Clone 之间的产物可能互相可见,某个执行任务可能读取到不该读取的内容,甚至把敏感文件误当作工具输入。
联犀在这里采用的策略很清楚:同一个 Sandbox 内的多个 Clone,各自对应独立的宿主持久子目录,容器侧只挂载当前 Clone 需要访问的那一份 workspace,而不是把整个 Agent 的 workspace 根目录暴露给所有 Clone。
宿主机: <WorkspaceRoot>/<agentID>/<cloneID>/
容器内: /workspace这样做带来的收益非常明确。
首先,Clone 之间的文件天然隔离,不需要靠运行时再做二次约定。同一 Agent 下的"张三助手"和"李四助手"不会在文件系统层面互相看到对方的产物。
其次,执行环境被销毁后,工作目录仍然可保留,平台既保留了运行期隔离,也保留了必要的持久化能力。
最后,控制面可以更清楚地理解某个 Clone 当前到底对应哪一份执行上下文,而不是在共享目录里猜测。
这也是 AI 运行时和传统脚本执行器的一个重要差别。AI 工具链不是偶尔跑一段运维脚本,而是会长期围绕某个 Clone、某个会话、某个业务对象反复执行。workspace 因此不只是临时目录,而是运行语义的一部分。
网络隔离为什么必须默认严格
对 AI 运行时来说,网络边界往往比 CPU 边界更危险。
因为模型具备持续尝试外部调用的能力,而网络访问一旦放开,后果通常不是"这次请求慢一点",而是内网探测、元数据访问、错误外呼、意外泄漏甚至横向利用。
联犀在这部分采取的是较强的默认约束:任务进程进入受限 netns,只允许通过受控 SOCKS5 代理口出网,并对内网地址、元数据地址和黑名单目标做专门限制。
这个设计思路非常重要,因为它说明平台的默认立场不是"先全放开,再按需补黑名单",而是"先把边界收紧,再决定哪些访问值得被放行"。
这类策略对 AI 特别关键。传统后端请求通常由开发者显式决定目标地址,而 AI 工具调用很多时候是模型根据上下文临时选择的。如果没有一个后端级的网络隔离层,安全边界最后只能依赖 prompt 或业务逻辑的临时兜底,这在工程上是不够的。
对应的开源执行面仓库
这一篇最直接对应的开源补充仓库,就是 unitedrhino/sandbox。
这个仓库不是简单的示例工程,而是联犀当前 AI Agent 安全执行面的独立仓库形态。里面能直接看到这篇文章讨论的很多能力都已经被做成明确事实:
- 独立执行服务本身
readyz / runtime/start / runtime/stream / runtime/stop这类运行时接口- cgroup / prlimit 资源限制策略
CLONE_NEWNET、iptables、SOCKS5 白名单等网络隔离实现- Clone 级 workspace 与 smoke 测试脚本
仓库地址:
这说明 Sandbox 在联犀里不是某个文档上的安全愿景,而是已经具备独立仓库边界的执行面能力。对外讨论这套设计时,把 unitedrhino/sandbox 仓库一并放进视野里,会更容易理解为什么我们说它不是"主服务里的一个小模块",而是一层可以独立演进、独立验证、独立发布的安全执行基础设施。
控制面与执行面的分离,也是在做故障隔离
Sandbox 的价值并不只在安全层面,它还同时改善了故障控制。
一套成熟的 AI 中台不仅要防止"错误地执行",还要防止"执行失败后把整个服务拖死"。把 sandbox 作为独立执行面之后,很多故障可以被自然限制在更小范围内:
- 单个 Clone 的运行循环出错,不必直接影响所有会话入口
- 某个任务超时或进程异常,可以围绕该 Sandbox 做停止和重建
- 容器生命周期管理成为可操作对象,而不是只能在主进程里猜状态
对于 AI 平台来说,这种故障隔离能力非常实际。因为工具执行、脚本运行和外部调用的失败模式,远比普通 HTTP API 丰富得多。只有当平台能把失败控制在执行面里,控制面才能继续稳定承担会话管理、知识加载、记忆编排和入口路由等职责。
Sandbox 的边界:它不是万能安全神话
当然,Sandbox 也不是"有了就绝对安全"。
它能解决的是执行环境边界问题,但它并不会自动替平台完成工具级语义校验、租户级授权判断或业务级幂等控制。换句话说,Sandbox 负责把运行时关进笼子里,但笼子里允许执行什么、哪些工具可以被调用、哪些 endpoint 被视为可信,仍然需要平台其他层一起定义。
这也是联犀同时保留 MCP 安全模型、租户 scope、白名单、超时和速率控制的原因。真正可靠的 AI 安全体系,不会把希望押注在单一机制上,而是让运行时隔离、工具约束和业务权限各自承担自己的职责。
总结
AI 中台进入"可执行"阶段之后,真正的挑战就不再只是模型能力,而是执行环境是否可控、AI 能力是否可被业务快速复用。
联犀的设计本质上同时回答了这两个问题。
第一个问题:怎样让 AI 执行能力真正具备可上线条件?
答案不是"把模型限制得更保守",而是把控制面和执行面拆开,把容器边界和任务边界同时收紧,把 workspace、网络和资源变成平台明确治理的对象。双层 Sandbox 隔离(容器级 + 进程级)让 AI 的工具调用、脚本执行和外部访问都有了工程上可验证的安全边界。
第二个问题:怎样让 AI 能力不被锁死在单个应用里?
答案是通过 AgentGroup 按业务场景预建能力模板,通过 Agent 定义可复用的执行配置,通过 Clone 实现实例级隔离和记忆独立。客服系统、设备管理平台、能源管理系统——这些业务应用不需要各自从零搭建一套 AI 运行时,只需要接入中台、申请一个 Agent、创建一个 Clone,就立刻获得完整的对话、记忆、工具调用和安全隔离能力。
换句话说,联犀 AI 中台的目标不是做一个"更好的聊天机器人",而是做一套可复用、可治理、可安全上线的 AI 执行基础设施——让 AI 能力从"每个应用重复开发"变成"平台统一供给、业务按需接入"。
更新日志
2026/5/29 00:13
查看所有更新日志
3a4f0-新增第19篇博客文章,重构全部博客为目录+README结构于386f7-docs(blog): 在 Sandbox 博客文章中补充多种沙盒方案资源消耗对比数据于51fb4-更新博客:Sandbox 运行时架构演进与 AI 中台价值于43ef3-docs(blog): 新增后端与架构系列技术博客 18 篇,更新原有 7 篇于
