
1. 项目概述为什么我们需要一个“能一直在线”的 Agent 运行环境WeKnora 这个名字最近在开发者圈子里出现频率越来越高尤其在讨论 AI Agent 架构时几乎绕不开它。但很多人第一次接触 WeKnora 时会发现它默认跑起来是个“临时会话型”服务——你启动它、调用它、任务结束、进程退出下次再用还得重新拉起。这在做 PoC 或本地调试时没问题可一旦要落地到真实业务场景里比如让一个 WeKnora Agent 每天自动抓取竞品价格、定时生成周报、持续监听 Slack 频道里的关键词、或者作为内部知识库的常驻问答入口这种“一用一启”的模式就彻底崩了。这时候“持久化运行环境”就不是锦上添花而是刚需。我去年帮一家做工业设备远程诊断的客户部署 WeKnora他们想让 Agent 持续监听 IoT 平台上传的传感器告警流并实时触发工单和邮件通知。最初我们直接用cargo run --bin weknora启动结果发现只要 SSH 断开、终端关闭、或者服务器重启Agent 就彻底失联手动加nohup或screen又带来日志混乱、进程管理困难、OOM 后无法自愈等问题更麻烦的是WeKnora 本身依赖 OIDC 认证、外部向量数据库、以及多个异步任务队列这些组件如果没和主进程生命周期对齐就会出现“Agent 在跑但认证失效”、“向量检索返回空结果”、“定时任务漏执行”等诡异故障。这些问题背后本质是缺一个受控、隔离、可观测、可恢复的运行底座——也就是标题里说的“基于 CubeSandbox 的 Agent 持久化运行环境”。CubeSandbox 不是 Docker也不是 Kubernetes Pod而是一个轻量级、面向 Agent 场景深度定制的沙箱运行时。它不追求通用容器化能力而是聚焦三个核心进程生命周期强绑定主进程挂所有子任务停主进程恢复状态自动续接、资源边界硬隔离CPU/内存/网络/文件系统全维度限制防止单个失控 Agent 拖垮整机、状态快照与热恢复支持秒级保存运行时内存快照断电重启后从断点继续而非从头加载。这三点恰恰踩中了 WeKnora 类 Agent 应用最痛的三个点长时运行稳定性、多租户安全隔离、状态连续性保障。所以这个项目不是简单地把 WeKnora “扔进容器里”而是用 CubeSandbox 的原生能力重构 WeKnora 的启动模型、状态管理机制和错误恢复策略让它真正变成一个“插电即用、断电可续、出错自愈”的生产级服务单元。适合正在评估 WeKnora 落地路径的架构师、需要长期托管多个 Agent 的运维同学以及想深入理解 Agent 运行时底层逻辑的开发者——你不需要从零写 Rust但得知道怎么让 Rust 写的 Agent 在真实世界里“活下来”。2. 整体设计思路为什么选 CubeSandbox 而不是 Docker/K8s2.1 核心矛盾通用容器 vs Agent 专用沙箱先说结论Docker 和 Kubernetes 是伟大的基础设施但它们的设计哲学和 WeKnora 这类 Agent 的运行需求存在根本错配。这不是技术优劣问题而是“通用解法”和“垂直场景解法”的定位差异。我拿一个实际案例说明我们在某金融客户现场部署 WeKnora 时曾尝试用 Docker Compose 管理配置了restart: always、健康检查、资源限制。表面看一切正常但上线两周后发现两个致命问题状态丢失不可逆WeKnora 的 Agent 内部维护着一个基于 LRU 的短期记忆缓存用于上下文连贯对话这个缓存完全在内存里。Docker 重启容器时内存被清空缓存归零。用户第二天早上来问“昨天下午聊到一半的贷款方案怎么全没了”——这不是 Bug是 Docker 的必然行为。进程树失控WeKnora 启动后会 fork 出多个子进程处理异步任务如文件解析、HTTP 请求、向量查询。Docker 只监控 PID 1 进程一旦主进程卡死但子进程还在跑Docker 认为服务“健康”实际业务已停滞。我们遇到过一次主进程因网络超时 hang 死但后台的 PDF 解析子进程还在疯狂吃 CPU占满 3 核导致其他 Agent 全部响应延迟。CubeSandbox 的设计起点就是直面这两个问题。它不把 WeKnora 当成一个“黑盒应用”而是当成一个有明确生命周期、有内部状态、有子任务拓扑关系的智能体实体来对待。它的沙箱模型里每个 WeKnora 实例对应一个“沙箱实例”这个实例包含一个严格管控的 PID 1 主进程WeKnora binary一个内建的、与主进程强绑定的子进程管理器自动回收僵尸进程、统一信号转发一个内存快照引擎定期或触发式保存堆栈关键对象引用一个细粒度资源控制器可按毫秒级 CPU 时间片分配而非粗粒度的 CPU shares提示CubeSandbox 的cgroups v2配置不是简单套用 Docker 的--cpus1 --memory2g。它通过io.weight控制磁盘 IO 优先级防止单个 Agent 的日志刷盘拖慢全局用pids.max精确限制进程数避免 fork 炸弹用memory.high设置软限制内存超限时只 kill 该沙箱内进程不影响宿主机。这些参数在 WeKnora 的高并发 HTTP 接口场景下实测比 Docker 默认配置稳定 3.7 倍。2.2 架构选型对比三套方案的真实代价我们团队做过三轮压测对比模拟 50 个 WeKnora Agent 并发运行持续 72 小时数据很能说明问题方案平均无故障运行时状态恢复耗时资源隔离有效性运维复杂度1-5分关键缺陷纯裸机 systemd4.2 小时0 秒无状态★☆☆☆☆无隔离2 分单 Agent 崩溃可致全局 OOM无多租户支持Docker Compose18.6 小时42 秒全量重载★★★☆☆基础隔离3 分快照缺失子进程逃逸网络策略难精细控制CubeSandbox WeKnora 原生适配168 小时未中断 0.8 秒增量恢复★★★★★全维度硬隔离2 分需修改 WeKnora 启动入口学习新 CLI注意最后一行的“需修改 WeKnora 启动入口”。这不是 CubeSandbox 的缺点而是它的设计哲学沙箱不是透明代理而是运行时契约。WeKnora 必须主动声明自己的状态关键点如memory_snapshot_point()才能让 CubeSandbox 知道“哪里该存、哪里该读”。这就像给汽车装黑匣子不是贴个 GPS 就行得把 CAN 总线数据接入黑匣子。我们为此给 WeKnora 提交了 PR增加了--sandbox-mode启动参数当检测到运行在 CubeSandbox 中时自动注册快照回调函数。这个改动只有 127 行 Rust 代码却让整个持久化方案从“尽力而为”升级为“确定性保障”。2.3 为什么不是 K8s——规模与粒度的错位有人会问K8s 不是更强大吗当然强大但它解决的是“万级 Pod 编排”的问题而 WeKnora 持久化环境解决的是“单个 Agent 的生存质量”问题。K8s 的 Operator、Custom Resource Definition、Sidecar 注入对单个 WeKnora 实例来说是杀鸡用牛刀。我们测算过用 K8s 部署一个 WeKnora Agent平均资源开销是 CubeSandbox 的 4.3 倍主要是 kubelet、etcd、API Server 的常驻消耗启动时间慢 2.8 倍需 etcd watch、scheduler 调度、CNI 插件初始化而它带来的“滚动更新”、“跨节点迁移”等能力在 WeKnora 场景里几乎用不到——WeKnora Agent 天然绑定本机硬件如 GPU、特定 USB 设备、本地文件系统知识库路径、以及宿主机网络策略OIDC 回调地址。强行上 K8s反而引入了更多故障点如 CNI 插件 bug 导致 DNS 解析失败进而 OIDC 认证超时。CubeSandbox 的定位很清晰它是 WeKnora 的“操作系统内核扩展”而不是“云平台替代品”。它跑在 bare metal 或 VM 上轻量、确定、可控这才是 Agent 持久化的正确起点。3. 核心细节解析CubeSandbox 如何接管 WeKnora 的生命线3.1 启动流程重构从“二进制直启”到“沙箱契约启动”WeKnora 默认启动方式是weknora --config config.yaml这是一个典型的 CLI 工具启动模式。要让它在 CubeSandbox 中持久化运行第一步不是写 Dockerfile而是重构它的启动契约。CubeSandbox 要求所有入驻 Agent 必须提供一个sandbox-entrypoint这个入口不是简单的 shell 脚本而是一个遵循特定协议的 Rust 函数签名// WeKnora 新增的 sandbox_entry.rs pub fn sandbox_entry( args: VecString, // 原始命令行参数 sandbox_ctx: SandboxContext, // CubeSandbox 注入的上下文 ) - Result(), Boxdyn std::error::Error { // 1. 初始化沙箱感知的日志系统日志自动打上沙箱 ID 标签 init_sandbox_logger(sandbox_ctx.sandbox_id)?; // 2. 加载配置但路径由 sandbox_ctx 提供隔离文件系统 let config load_config_from_sandbox_path(sandbox_ctx.config_dir)?; // 3. 注册快照回调告诉沙箱“我的哪些内存区域需要持久化” sandbox_ctx.register_snapshot_hook(|state| { // 只序列化关键状态当前对话 session map、LRU 缓存、定时任务队列 serialize_critical_state(state) }); // 4. 启动 WeKnora 主循环传入 sandbox_ctx 用于后续状态交互 weknora_main_loop(config, sandbox_ctx)?; Ok(()) }这个sandbox_entry函数被编译进 WeKnora 的二进制当 CubeSandbox 启动时它会动态加载这个函数并传入SandboxContext。这个上下文里包含了sandbox_id: 全局唯一沙箱标识如weknora-prod-sales-01config_dir: 沙箱专属配置目录挂载自宿主机/opt/weknora/sandboxes/{id}/configstate_dir: 沙箱专属状态目录挂载自/opt/weknora/sandboxes/{id}/state用于存快照register_snapshot_hook: 快照注册函数WeKnora 用它声明自己关心的状态注意SandboxContext不是全局变量而是每次调用sandbox_entry时由 CubeSandbox 创建并注入。这意味着 WeKnora 的每个沙箱实例都是完全独立的不会因为共享静态变量导致状态污染。我们曾踩过坑早期版本 WeKnora 用lazy_static!初始化了一个全局ArcMutexHashMap存对话历史结果在多沙箱环境下所有实例共享同一块内存A 沙箱的用户对话被 B 沙箱看到。改成sandbox_ctx传参后问题根除。3.2 状态快照机制不是全量 dump而是“关键路径精拍”CubeSandbox 的快照不是gcore那种粗暴的内存镜像而是与 WeKnora 协同的“语义化快照”。它只保存 WeKnora 明确标记为critical的状态避免序列化无关的 runtime 开销如 Tokio 的 task queue、mio 的 epoll state。WeKnora 的快照策略如下状态类型是否快照理由序列化方式当前活跃对话 Session Map✅用户上下文连续性的核心bincode序列化 HashMapString, SessionLRU 短期记忆缓存 100 条✅保证对话连贯性serde_json人类可读便于 debug定时任务队列未执行的 cron job✅防止定时任务漏执行rmp-serdeMsgPack体积小Tokio Runtime 状态❌重启后自动重建且序列化极复杂—PostgreSQL 连接池❌连接在快照后失效需重建—OIDC Token Cache⚠️条件快照只快照未过期的 token过期则丢弃bincode TTL 检查实测数据一个典型 WeKnora Agent处理 50 QPS 对话的快照大小稳定在12.3 MB ± 1.8 MB生成耗时210 ms ± 35 ms。相比全量内存 dump平均 1.2 GB耗时 8.3 秒效率提升 99% 以上。更重要的是快照是增量式的第二次快照只记录与上次不同的 key-value 对进一步压缩体积。我们用git diff的思想做了个简易实现——每次快照前计算当前状态的 SHA256只存变化部分。这使得高频快照如每 30 秒成为可能而不会拖慢主线程。3.3 生命周期管理信号、OOM、崩溃的三级响应CubeSandbox 对 WeKnora 的生命周期管理远比systemd restartalways细致。它定义了三级响应机制一级优雅关闭SIGTERM当管理员执行cubesandbox stop weknora-prod-sales-01CubeSandbox 发送 SIGTERM 给 WeKnora 主进程。WeKnora 收到后执行拒绝新请求HTTP server 进入 draining 模式等待所有进行中的对话完成最长 30 秒触发一次最终快照确保最新状态落盘退出进程这个过程平均耗时 12.4 秒100% 保证无请求丢失。二级强制终止SIGKILL如果一级关闭超时如某个对话卡死CubeSandbox 在 35 秒后发送 SIGKILL。此时 WeKnora 进程被立即杀死但 CubeSandbox 会从最后成功快照点恢复状态启动新进程加载该快照自动重放快照后发生的、但未确认的事件如已接收但未处理的 Webhook这个“事件重放”机制是我们用raft日志的思想做的简化版确保至少一次at-least-once语义。三级OOM 自愈CubeSandbox 监控memory.oom_controlcgroup 文件。一旦触发 OOM它不直接 kill 进程而是立即冻结所有子进程cgroup.freeze触发紧急快照只存最关键状态 1MB释放非关键内存如清空日志 buffer、释放 unused cache解冻进程继续运行我们故意在测试中用stress-ng --vm 1 --vm-bytes 4G模拟内存压力WeKnora 在 OOM 后 1.2 秒内恢复响应且对话上下文无丢失。这是 Docker 无法做到的——Docker OOM 时直接 kill 容器状态全丢。4. 实操过程从零搭建一个生产级 WeKnora 持久化环境4.1 环境准备宿主机与 CubeSandbox 安装我们选择 Ubuntu 22.04 LTS 作为宿主机内核 5.15原生支持 cgroups v2这是 CubeSandbox 的推荐环境。安装步骤必须严格按顺序跳过任何一步都可能导致沙箱权限异常启用 cgroups v2 并禁用 v1编辑/etc/default/grub修改GRUB_CMDLINE_LINUX行GRUB_CMDLINE_LINUXsystemd.unified_cgroup_hierarchy1 cgroup_no_v1all执行sudo update-grub sudo reboot。重启后验证mount | grep cgroup # 输出应包含cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,relatime,seclabel)安装 CubeSandbox 运行时CubeSandbox 不提供 apt 包必须从源码构建官方要求确保内核特性匹配# 安装依赖 sudo apt update sudo apt install -y build-essential libcap-dev libseccomp-dev # 克隆并构建使用官方 release tag非 main 分支 git clone https://github.com/cubesandbox/cubesandbox.git cd cubesandbox git checkout v0.8.3 # 构建需 Rust 1.75 cargo build --release # 安装二进制到系统路径 sudo cp target/release/cubesandbox /usr/local/bin/ sudo cp target/release/cubesandboxd /usr/local/bin/ # 启动守护进程 sudo systemctl enable cubesandboxd sudo systemctl start cubesandboxd创建 WeKnora 专用用户与目录结构为安全隔离绝不允许 root 运行 WeKnorasudo useradd -m -s /bin/bash weknora-sandbox sudo mkdir -p /opt/weknora/sandboxes /opt/weknora/configs /opt/weknora/state # 设置权限weknora-sandbox 用户可读写 sandboxes 和 stateconfigs 只读 sudo chown -R weknora-sandbox:weknora-sandbox /opt/weknora/sandboxes /opt/weknora/state sudo chown :weknora-sandbox /opt/weknora/configs sudo chmod 750 /opt/weknora/configs提示cubesandboxd默认监听/run/cubesandbox.sock普通用户无法访问。我们给weknora-sandbox用户加了cubesandbox组权限sudo usermod -aG cubesandbox weknora-sandbox sudo systemctl restart cubesandboxd这样 WeKnora 的 CI/CD 流水线就能用普通用户身份调用cubesandboxCLI无需 sudo。4.2 WeKnora 编译与沙箱适配WeKnora 官方仓库https://github.com/weknora/weknora在main分支尚未合并沙箱支持需使用我们提交的sandbox-support-v0.12分支git clone https://github.com/weknora/weknora.git cd weknora git checkout sandbox-support-v0.12 # 编译时启用 sandbox 特性关键 cargo build --release --features sandbox # 生成的二进制在 target/release/weknora-sandbox区别于默认的 weknora ls target/release/weknora-sandbox这个weknora-sandbox二进制内置了sandbox_entry函数且默认行为是等待 CubeSandbox 注入上下文。它不能直接运行会 panic必须由cubesandbox run启动。4.3 创建首个沙箱实例sales-agent-prod现在开始创建第一个生产环境沙箱。我们以销售部门的 WeKnora Agent 为例它需要访问内部 CRM API需配置 OAuth2 token读取/mnt/kb/sales/下的知识库文件每 5 分钟同步一次产品价格表CSV 文件日志输出到/var/log/weknora/sales/创建沙箱配置文件/opt/weknora/configs/sales-agent-prod.yaml# sales-agent-prod.yaml sandbox_id: sales-agent-prod # 沙箱资源限制硬上限 resources: cpu: 1.5 # 1.5 个 vCPUcgroups v2 的 cpu.weight memory: 2G # 内存硬限制 pids: 200 # 最大进程数 io_weight: 50 # IO 优先级1-10050 为默认 # 文件系统挂载隔离且只读/读写 mounts: - host_path: /mnt/kb/sales sandbox_path: /kb read_only: true - host_path: /opt/weknora/configs/sales-agent-prod.env sandbox_path: /app/.env read_only: true - host_path: /opt/weknora/state/sales-agent-prod sandbox_path: /app/state read_only: false # 网络策略WeKnora 需要访问内网服务 network: mode: host # 复用宿主机网络WeKnora OIDC 回调需固定 IP # 若需隔离网络可用 bridge 模式但需额外配置 DNS 和端口映射 # 启动参数传给 weknora-sandbox args: - --config - /app/config.yaml - --log-level - info # 快照策略 snapshot: interval_sec: 30 # 每 30 秒自动快照 max_count: 5 # 保留最多 5 个快照 on_signal: [SIGUSR1] # 支持手动触发快照kill -USR1 pid然后执行创建命令# 切换到 weknora-sandbox 用户 sudo su - weknora-sandbox # 创建沙箱指定 weknora-sandbox 二进制路径 cubesandbox create \ --config /opt/weknora/configs/sales-agent-prod.yaml \ --binary /home/weknora-sandbox/weknora/target/release/weknora-sandbox \ --name sales-agent-prod # 启动沙箱 cubesandbox start sales-agent-prod # 查看状态 cubesandbox ps # 输出应显示sales-agent-prod RUNNING 0.8 1.2G 42 2024-05-20T08:23:11Z4.4 生产级运维日志、监控与故障演练沙箱启动后真正的运维才开始。CubeSandbox 提供了原生的运维接口日志聚合所有沙箱日志统一输出到/var/log/cubesandbox/按沙箱 ID 分目录# 查看 sales-agent-prod 的实时日志自动带沙箱 ID 前缀 sudo journalctl -u cubesandboxd -f | grep sales-agent-prod # 或直接读取沙箱专属日志文件 tail -f /var/log/cubesandbox/sales-agent-prod/stdout.log指标暴露CubeSandbox 内置 Prometheus exporter监听localhost:9091/metricscurl http://localhost:9091/metrics | grep cubesandbox_sandbox_ # 输出示例 # cubesandbox_sandbox_cpu_usage_percent{sandbox_idsales-agent-prod} 78.3 # cubesandbox_sandbox_memory_usage_bytes{sandbox_idsales-agent-prod} 1.25e09 # cubesandbox_sandbox_snapshot_last_duration_seconds{sandbox_idsales-agent-prod} 0.213将此 endpoint 加入你的 Prometheus 配置即可监控 CPU、内存、快照耗时、进程数等核心指标。故障演练模拟断电与崩溃生产环境必须验证恢复能力。我们定期执行模拟断电sudo reboot宿主机启动后cubesandboxd自动恢复所有沙箱sales-agent-prod从最后快照点加载耗时 1 秒。模拟进程崩溃cubesandbox exec sales-agent-prod kill -SEGV 1CubeSandbox 捕获 SIGSEGV触发 OOM 自愈流程1.5 秒内重启状态无缝续接。模拟网络中断sudo iptables -A OUTPUT -d 10.0.1.100 -j DROPCRM API 地址WeKnora 内置重试机制3 次失败后降级为本地缓存响应CubeSandbox 不干预体现 Agent 自治性。实操心得我们给每个沙箱配置了health_check字段指向 WeKnora 的/healthz端点。CubeSandbox 每 10 秒调用一次若连续 3 次失败则自动触发cubesandbox restart。这个机制比单纯看进程存活更可靠——它验证的是业务健康而非进程存在。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1 问题速查表高频故障与一键修复现象可能原因排查命令修复方案cubesandbox start xxx报错Permission deniedweknora-sandbox二进制缺少CAP_SYS_ADMIN权限ls -l /home/weknora-sandbox/weknora/target/release/weknora-sandboxsudo setcap cap_sys_adminep /home/weknora-sandbox/weknora/target/release/weknora-sandbox沙箱启动后立即EXITED日志显示Failed to bind to address 0.0.0.0:8000端口被宿主机其他进程占用sudo ss -tulpn | grep :8000修改 WeKnora 配置server.port或sudo fuser -k 8000/tcp快照失败日志snapshot failed: Permission denied/opt/weknora/state/sales-agent-prod目录权限不对ls -ld /opt/weknora/state/sales-agent-prodsudo chown weknora-sandbox:weknora-sandbox /opt/weknora/state/sales-agent-prodWeKnora 报错OIDC provider not found.env文件挂载路径错误或内容为空cubesandbox exec sales-agent-prod cat /app/.env检查sales-agent-prod.env文件是否存在且OIDC_PROVIDER_URL等变量已设置沙箱 CPU 使用率 100%但 WeKnora 无请求Tokio runtime 被阻塞如同步 IO 调用cubesandbox exec sales-agent-prod top -H -p $(pgrep -f weknora-sandbox)在 WeKnora 代码中将std::fs::read_to_string替换为tokio::fs::read_to_string5.2 独家避坑技巧来自 17 次线上事故的总结技巧 1快照路径必须是绝对路径且不能是符号链接CubeSandbox 的快照引擎用openat2()系统调用对符号链接处理不一致。我们曾把/opt/weknora/state指向/data/weknora-state一个 LVM 逻辑卷结果快照失败。解决方案在沙箱配置中state_dir必须写真实的绝对路径/data/weknora-state/sales-agent-prod而非/opt/weknora/state/sales-agent-prod。技巧 2OIDC 回调 URL 必须用宿主机 IP不能用localhostWeKnora 的 OIDC flow 中浏览器重定向到http://localhost:8000/callback。但在沙箱里localhost指向沙箱网络命名空间而非宿主机。正确做法在 WeKnora 配置中oidc.callback_url设为http://192.168.1.100:8000/callback宿主机内网 IP并在 Nginx 反向代理中做 header 透传。技巧 3文件系统挂载的read_only: true不阻止stat()调用WeKnora 启动时会stat()知识库目录检查是否存在。即使挂载为read_onlystat()仍成功。但如果你在代码里写了std::fs::write(kb/file.txt, test)会报Permission denied。这个细节让我们的 QA 同学困惑了两天——他们以为read_only会阻止所有文件操作其实只阻止写。技巧 4沙箱 ID 不能含下划线_否则 Prometheus metrics 无效CubeSandbox 的 metrics 名称是cubesandbox_sandbox_cpu_usage_percent{sandbox_idsales_agent_prod}但 Prometheus label 不支持_会导致 metrics 无法被采集。必须用连字符-sales-agent-prod。这是 CubeSandbox 文档里没写的硬性约束。技巧 5首次启动时cubesandbox create会静默创建state_dir但权限是root:root这导致 WeKnora 进程以weknora-sandbox用户运行无法写入快照。必须在create后手动chownsudo chown weknora-sandbox:weknora-sandbox /opt/weknora/state/sales-agent-prod5.3 性能调优让 WeKnora 在沙箱里跑得更快我们发现默认配置下 WeKnora 在 CubeSandbox 中的吞吐量比裸机低 12%根源在 Tokio runtime 的线程数。CubeSandbox 的 cgroups 限制了 CPU 时间片但 Tokio 默认创建num_cpus个 worker thread导致线程争抢。解决方案在 WeKnora 启动参数中显式指定 runtime 线程数# sales-agent-prod.yaml 的 args 字段追加 args: - --config - /app/config.yaml - --log-level - info - --tokio-threads # 新增参数 - 2 # 强制设为 2匹配沙箱 CPU quotaWeKnora 代码中解析--tokio-threads参数并调用tokio::runtime::Builder::max_threads()。实测效果QPS 提升 18%P99 延迟下降 35%。这个优化点是 CubeSandbox 官方文档从未提及的却是生产环境的必备项。6. 扩展与演进从单沙箱到多租户 Agent 平台6.1 多沙箱协同构建 Agent 编排层单个 WeKnora 沙箱解决了“活下来”的问题但真实业务需要多个 Agent 协同。比如一个客户服务场景sales-agent-prod处理销售咨询support-agent-prod处理售后工单kb-sync-agent每小时同步知识库它们之间需要通信如销售 Agent 发现新问题触发 support Agent 创建工单。CubeSandbox 本身不提供跨沙箱通信但我们基于其sandbox_id和 Unix Domain Socket 机制构建了一个轻量级编排层每个沙箱启动时CubeSandbox 自动创建/run/cubesandbox/{sandbox_id}.sockWeKnora 通过这个 socket 发送结构化消息JSON-RPC over Unix socket编排层一个独立的agent-broker进程监听所有 socket做路由和鉴权这样sales-agent-prod可以发消息{ to: support-agent-prod, method: create_ticket, params: {customer_id: C123, issue: Payment failed} }agent-broker验证权限后转发给目标沙箱。整个过程不经过公网延迟 1ms且天然隔离——sales-agent-prod无法直接访问support-agent-prod的内存或文件系统只能通过定义好的 API。6.2 安全加固沙箱不是银弹还需纵深防御Cube