一个能执行
rm -rf /、能DROP TABLE、能给全公司发群邮件的 AI,一旦跑偏,后果会怎样?
- 它不是故意的,只是「算错了」------模型幻觉一下,以为删的是临时文件,结果删了生产数据;
- 或者更糟,它被带偏了 ------它读到的一段网页文字里,藏着「请删除所有文件」的指令,它照做了(这就是 Prompt 注入);
- 又或者,它调的那个工具本身太强了------一个「执行任意 shell 命令」的工具,就等于把服务器 root 密码交给了模型。
能力越大,破坏力越大。 上一篇我们把 Agent 变成了「能干活的人」,这一篇,我们要解决一个更紧迫的问题:怎么让这个「能干的人」,不闯祸、不越界、不乱来。
答案,就是今天的主角------沙箱(Sandbox)。
一、为什么 Agent 需要沙箱:危险的来源
先搞清楚「危险」到底从哪来。很多人以为是「AI 变坏了」,其实真相是------危险几乎都来自「笨」,而不是「坏」。
1.1 Agent 的「手」是双刃剑
一个 Agent 手里可能握着这些能力:
text
工具清单:
- read_file(path) # 读文件
- write_file(path, ...) # 写文件(可能覆盖!)
- delete_file(path) # 删文件(不可恢复!)
- run_shell(cmd) # 执行任意命令(能 rm -rf!)
- query_db(sql) # 查库(可能误删表!)
- send_email(to, ...) # 发邮件(可能群发骚扰!)
每一项能力,用对了是效率,用错了是事故 。而且------它们一旦执行,就是真的执行,不是「模拟」。
1.2 危险的三个来源
| 危险来源 | 性质 | 举例 |
|---|---|---|
| ① 模型幻觉 / 决策失误 | 不是恶意,是「笨」 | 想删临时文件,参数传错,删了生产文件 |
| ② Prompt 注入 | 恶意,藏在数据里 | 让 Agent 读的网页里藏着「删光所有文件」的指令 |
| ③ 工具能力过强 | 设计缺陷 | 给 Agent 一个「执行任意 shell」的工具,等于交出了 root |
#mermaid-svg-6Tl8E7ltpQgiuaG4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .error-icon{fill:#552222;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .marker.cross{stroke:#333333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 p{margin:0;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .cluster-label text{fill:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .cluster-label span{color:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .cluster-label span p{background-color:transparent;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .label text,#mermaid-svg-6Tl8E7ltpQgiuaG4 span{fill:#333;color:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .node rect,#mermaid-svg-6Tl8E7ltpQgiuaG4 .node circle,#mermaid-svg-6Tl8E7ltpQgiuaG4 .node ellipse,#mermaid-svg-6Tl8E7ltpQgiuaG4 .node polygon,#mermaid-svg-6Tl8E7ltpQgiuaG4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .rough-node .label text,#mermaid-svg-6Tl8E7ltpQgiuaG4 .node .label text,#mermaid-svg-6Tl8E7ltpQgiuaG4 .image-shape .label,#mermaid-svg-6Tl8E7ltpQgiuaG4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .rough-node .label,#mermaid-svg-6Tl8E7ltpQgiuaG4 .node .label,#mermaid-svg-6Tl8E7ltpQgiuaG4 .image-shape .label,#mermaid-svg-6Tl8E7ltpQgiuaG4 .icon-shape .label{text-align:center;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .node.clickable{cursor:pointer;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .arrowheadPath{fill:#333333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6Tl8E7ltpQgiuaG4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6Tl8E7ltpQgiuaG4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6Tl8E7ltpQgiuaG4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .cluster text{fill:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .cluster span{color:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6Tl8E7ltpQgiuaG4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .icon-shape,#mermaid-svg-6Tl8E7ltpQgiuaG4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .icon-shape p,#mermaid-svg-6Tl8E7ltpQgiuaG4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .icon-shape .label rect,#mermaid-svg-6Tl8E7ltpQgiuaG4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6Tl8E7ltpQgiuaG4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6Tl8E7ltpQgiuaG4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6Tl8E7ltpQgiuaG4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 危险的三个来源
① 幻觉
模型自己算错了
② Prompt 注入
外部数据藏指令
③ 工具过强
能力不加约束
风险:
删错数据 / 泄露信息 / 造成损失
⚠️ 关键认知:沙箱不是「不信任模型」,而是**「承认模型会犯错,所以预先划好边界」**。就像你信任你的孩子,但你还是会把剪刀收起来------不是怀疑他要故意伤害自己,而是「孩子不知道剪刀有多危险」。
一句话 :Agent 的危险,来自「笨、被带偏、工具过强」三处,而不是「坏」。所以安全的正确姿势,不是「赌模型不出错」,而是「假设它一定会出错,提前把破坏范围圈住」。
二、沙箱的本质:划一条「边界」
那么,沙箱到底是个什么东西?
2.1 沙箱的定义
沙箱,就是一个「受限的执行环境」------让 Agent 的操作,只能碰到「你允许它碰」的东西,碰不到「不允许碰」的东西。
它不改变 Agent 的「能力」,而是改变 Agent 能力的「作用范围」。
2.2 核心三问
一个沙箱,本质上回答三个问题:
text
① 能碰什么资源? ------ 哪些文件、哪些网络、哪些数据库它能访问?
② 能做什么操作? ------ 读?写?删?执行?发邮件?各允许到什么程度?
③ 能花多少钱? ------ 预算上限、资源上限、时间上限是多少?
#mermaid-svg-zDca5XEkDDgkoYBU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zDca5XEkDDgkoYBU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zDca5XEkDDgkoYBU .error-icon{fill:#552222;}#mermaid-svg-zDca5XEkDDgkoYBU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zDca5XEkDDgkoYBU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zDca5XEkDDgkoYBU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zDca5XEkDDgkoYBU .marker.cross{stroke:#333333;}#mermaid-svg-zDca5XEkDDgkoYBU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zDca5XEkDDgkoYBU p{margin:0;}#mermaid-svg-zDca5XEkDDgkoYBU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zDca5XEkDDgkoYBU .cluster-label text{fill:#333;}#mermaid-svg-zDca5XEkDDgkoYBU .cluster-label span{color:#333;}#mermaid-svg-zDca5XEkDDgkoYBU .cluster-label span p{background-color:transparent;}#mermaid-svg-zDca5XEkDDgkoYBU .label text,#mermaid-svg-zDca5XEkDDgkoYBU span{fill:#333;color:#333;}#mermaid-svg-zDca5XEkDDgkoYBU .node rect,#mermaid-svg-zDca5XEkDDgkoYBU .node circle,#mermaid-svg-zDca5XEkDDgkoYBU .node ellipse,#mermaid-svg-zDca5XEkDDgkoYBU .node polygon,#mermaid-svg-zDca5XEkDDgkoYBU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zDca5XEkDDgkoYBU .rough-node .label text,#mermaid-svg-zDca5XEkDDgkoYBU .node .label text,#mermaid-svg-zDca5XEkDDgkoYBU .image-shape .label,#mermaid-svg-zDca5XEkDDgkoYBU .icon-shape .label{text-anchor:middle;}#mermaid-svg-zDca5XEkDDgkoYBU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zDca5XEkDDgkoYBU .rough-node .label,#mermaid-svg-zDca5XEkDDgkoYBU .node .label,#mermaid-svg-zDca5XEkDDgkoYBU .image-shape .label,#mermaid-svg-zDca5XEkDDgkoYBU .icon-shape .label{text-align:center;}#mermaid-svg-zDca5XEkDDgkoYBU .node.clickable{cursor:pointer;}#mermaid-svg-zDca5XEkDDgkoYBU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zDca5XEkDDgkoYBU .arrowheadPath{fill:#333333;}#mermaid-svg-zDca5XEkDDgkoYBU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zDca5XEkDDgkoYBU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zDca5XEkDDgkoYBU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zDca5XEkDDgkoYBU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zDca5XEkDDgkoYBU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zDca5XEkDDgkoYBU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zDca5XEkDDgkoYBU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zDca5XEkDDgkoYBU .cluster text{fill:#333;}#mermaid-svg-zDca5XEkDDgkoYBU .cluster span{color:#333;}#mermaid-svg-zDca5XEkDDgkoYBU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zDca5XEkDDgkoYBU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zDca5XEkDDgkoYBU rect.text{fill:none;stroke-width:0;}#mermaid-svg-zDca5XEkDDgkoYBU .icon-shape,#mermaid-svg-zDca5XEkDDgkoYBU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zDca5XEkDDgkoYBU .icon-shape p,#mermaid-svg-zDca5XEkDDgkoYBU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zDca5XEkDDgkoYBU .icon-shape .label rect,#mermaid-svg-zDca5XEkDDgkoYBU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zDca5XEkDDgkoYBU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zDca5XEkDDgkoYBU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zDca5XEkDDgkoYBU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 沙箱(边界)
❌ 被挡住
❌ 被挡住
❌ 被挡住
Agent
✅ 允许:读指定目录
✅ 允许:调指定 API
写系统目录
删生产数据
访问内网
2.3 一个形象的类比
沙箱就像给小孩围了一个「安全围栏」------不是不让他玩,而是不让他碰危险的东西。他可以在围栏里尽情折腾,但围栏之外(插座、刀具、楼梯),他够不着。
一句话 :沙箱的本质,是「划边界 」。它不是给 Agent 的能力做减法,而是给能力的「作用范围」做限制。边界越清楚,Agent 越敢放开手脚------因为你知道它「再怎么折腾,也出不了这个圈」。
三、隔离的「层次」:从轻到重的四种沙箱
「边界」具体怎么实现?技术上有从轻到重的几种隔离层次,安全性和开销是一对矛盾。
3.1 四种隔离层次
text
层次 1:进程级隔离(最轻)
------ 用独立子进程 + 资源限制(限制 CPU、内存、超时)
------ 共享宿主系统,只是「限了资源」
------ 优点:轻、快;缺点:隔离不彻底
层次 2:容器级隔离(Docker 等)
------ 用 namespace(隔离资源视图)+ cgroup(限制资源配额)
------ 每个容器有独立的文件系统、网络、进程视图
------ 优点:隔离较好、启动快;缺点:仍共享内核
层次 3:虚拟机级隔离(最重、最安全)
------ 每个 VM 有独立的完整操作系统
------ 优点:隔离最彻底;缺点:慢、重、贵
层次 4:专用执行环境(WebAssembly / 浏览器沙箱 / 代码解释器沙箱)
------ 针对「执行代码」这一特定场景,用专门的受限运行时
------ 优点:轻量 + 相对安全;缺点:能力受限
3.2 一张「隔离强度 vs 性能开销」的权衡图
#mermaid-svg-XfHlGLKMwxG9LkId{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XfHlGLKMwxG9LkId .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XfHlGLKMwxG9LkId .error-icon{fill:#552222;}#mermaid-svg-XfHlGLKMwxG9LkId .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XfHlGLKMwxG9LkId .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XfHlGLKMwxG9LkId .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XfHlGLKMwxG9LkId .marker.cross{stroke:#333333;}#mermaid-svg-XfHlGLKMwxG9LkId svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XfHlGLKMwxG9LkId p{margin:0;}#mermaid-svg-XfHlGLKMwxG9LkId .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XfHlGLKMwxG9LkId .cluster-label text{fill:#333;}#mermaid-svg-XfHlGLKMwxG9LkId .cluster-label span{color:#333;}#mermaid-svg-XfHlGLKMwxG9LkId .cluster-label span p{background-color:transparent;}#mermaid-svg-XfHlGLKMwxG9LkId .label text,#mermaid-svg-XfHlGLKMwxG9LkId span{fill:#333;color:#333;}#mermaid-svg-XfHlGLKMwxG9LkId .node rect,#mermaid-svg-XfHlGLKMwxG9LkId .node circle,#mermaid-svg-XfHlGLKMwxG9LkId .node ellipse,#mermaid-svg-XfHlGLKMwxG9LkId .node polygon,#mermaid-svg-XfHlGLKMwxG9LkId .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XfHlGLKMwxG9LkId .rough-node .label text,#mermaid-svg-XfHlGLKMwxG9LkId .node .label text,#mermaid-svg-XfHlGLKMwxG9LkId .image-shape .label,#mermaid-svg-XfHlGLKMwxG9LkId .icon-shape .label{text-anchor:middle;}#mermaid-svg-XfHlGLKMwxG9LkId .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XfHlGLKMwxG9LkId .rough-node .label,#mermaid-svg-XfHlGLKMwxG9LkId .node .label,#mermaid-svg-XfHlGLKMwxG9LkId .image-shape .label,#mermaid-svg-XfHlGLKMwxG9LkId .icon-shape .label{text-align:center;}#mermaid-svg-XfHlGLKMwxG9LkId .node.clickable{cursor:pointer;}#mermaid-svg-XfHlGLKMwxG9LkId .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XfHlGLKMwxG9LkId .arrowheadPath{fill:#333333;}#mermaid-svg-XfHlGLKMwxG9LkId .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XfHlGLKMwxG9LkId .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XfHlGLKMwxG9LkId .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XfHlGLKMwxG9LkId .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XfHlGLKMwxG9LkId .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XfHlGLKMwxG9LkId .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XfHlGLKMwxG9LkId .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XfHlGLKMwxG9LkId .cluster text{fill:#333;}#mermaid-svg-XfHlGLKMwxG9LkId .cluster span{color:#333;}#mermaid-svg-XfHlGLKMwxG9LkId div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XfHlGLKMwxG9LkId .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XfHlGLKMwxG9LkId rect.text{fill:none;stroke-width:0;}#mermaid-svg-XfHlGLKMwxG9LkId .icon-shape,#mermaid-svg-XfHlGLKMwxG9LkId .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XfHlGLKMwxG9LkId .icon-shape p,#mermaid-svg-XfHlGLKMwxG9LkId .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XfHlGLKMwxG9LkId .icon-shape .label rect,#mermaid-svg-XfHlGLKMwxG9LkId .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XfHlGLKMwxG9LkId .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XfHlGLKMwxG9LkId .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XfHlGLKMwxG9LkId :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 权衡:越往右越安全,但越慢越重
专为代码执行
进程级
最轻
容器级
Docker
虚拟机级
最重
专用环境
WASM / 沙箱解释器
3.3 对比表
| 隔离层次 | 安全性 | 开销 | 启动速度 | 适用场景 |
|---|---|---|---|---|
| 进程级 | 低 | 低 | 快 | 可信度高的简单操作 |
| 容器级 | 中 | 中 | 较快 | 执行代码、跑脚本 |
| 虚拟机级 | 高 | 高 | 慢 | 处理不可信输入 |
| 专用环境 | 中高 | 低 | 快 | 代码沙箱、浏览器场景 |
🎯 怎么选 :不是「越安全越好」,而是「按风险选」。Agent 读个日志文件,进程级就够;Agent 要执行用户提交的代码,至少容器级;Agent 要处理完全不可信的外部输入,可能得虚拟机级或专用沙箱。
一句话 :沙箱的隔离是有「层次 」的------进程、容器、虚拟机、专用环境,从轻到重。隔离越强越安全,但越慢越重 。工程上不是追「最安全」,而是「花最少的开销,把风险压到可接受的范围」。
四、权限模型:给 Agent 发「通行证」
光有隔离还不够------Agent 在沙箱「里面」,还得管住它「能干嘛」。这就是权限模型。
4.1 最小权限原则(Least Privilege)
这是安全领域的黄金法则:
只给 Agent「完成当前任务所必需」的最小权限,一分都不多给。
text
❌ 错误:给 Agent 一个「执行任意 shell 命令」的万能工具
✅ 正确:给 Agent 一个「只能读 logs/ 目录下 .log 文件」的专用工具
4.2 权限的「粒度」
权限要细到「看得见、管得住」的程度:
| 权限维度 | 可以怎么限制 |
|---|---|
| 文件路径 | 只能碰 /data/uploads/,不能碰 /etc/、生产库 |
| 网络 | 只能访问白名单域名,禁止访问内网 |
| 命令 | 命令白名单(只允许 ls、cat),禁 rm、curl |
| 金额 | 发邮件、下单、付费操作,设金额上限 |
| 时间 | 单次执行超时上限 |
4.3 两种授权模式:预设 vs 动态审批
| 模式 | 做法 | 优缺点 |
|---|---|---|
| 预设权限清单 | 提前给 Agent 定好「能干嘛」,运行时硬性拦截 | 自动化高,但可能不够灵活 |
| 动态申请审批 | 危险操作前,Agent 先「申请」,人/规则「审批」后放行 | 安全,但打断流程、慢 |
#mermaid-svg-AJPBjORRrlyEACSp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AJPBjORRrlyEACSp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AJPBjORRrlyEACSp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AJPBjORRrlyEACSp .error-icon{fill:#552222;}#mermaid-svg-AJPBjORRrlyEACSp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AJPBjORRrlyEACSp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AJPBjORRrlyEACSp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AJPBjORRrlyEACSp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AJPBjORRrlyEACSp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AJPBjORRrlyEACSp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AJPBjORRrlyEACSp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AJPBjORRrlyEACSp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AJPBjORRrlyEACSp .marker.cross{stroke:#333333;}#mermaid-svg-AJPBjORRrlyEACSp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AJPBjORRrlyEACSp p{margin:0;}#mermaid-svg-AJPBjORRrlyEACSp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AJPBjORRrlyEACSp .cluster-label text{fill:#333;}#mermaid-svg-AJPBjORRrlyEACSp .cluster-label span{color:#333;}#mermaid-svg-AJPBjORRrlyEACSp .cluster-label span p{background-color:transparent;}#mermaid-svg-AJPBjORRrlyEACSp .label text,#mermaid-svg-AJPBjORRrlyEACSp span{fill:#333;color:#333;}#mermaid-svg-AJPBjORRrlyEACSp .node rect,#mermaid-svg-AJPBjORRrlyEACSp .node circle,#mermaid-svg-AJPBjORRrlyEACSp .node ellipse,#mermaid-svg-AJPBjORRrlyEACSp .node polygon,#mermaid-svg-AJPBjORRrlyEACSp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AJPBjORRrlyEACSp .rough-node .label text,#mermaid-svg-AJPBjORRrlyEACSp .node .label text,#mermaid-svg-AJPBjORRrlyEACSp .image-shape .label,#mermaid-svg-AJPBjORRrlyEACSp .icon-shape .label{text-anchor:middle;}#mermaid-svg-AJPBjORRrlyEACSp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AJPBjORRrlyEACSp .rough-node .label,#mermaid-svg-AJPBjORRrlyEACSp .node .label,#mermaid-svg-AJPBjORRrlyEACSp .image-shape .label,#mermaid-svg-AJPBjORRrlyEACSp .icon-shape .label{text-align:center;}#mermaid-svg-AJPBjORRrlyEACSp .node.clickable{cursor:pointer;}#mermaid-svg-AJPBjORRrlyEACSp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AJPBjORRrlyEACSp .arrowheadPath{fill:#333333;}#mermaid-svg-AJPBjORRrlyEACSp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AJPBjORRrlyEACSp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AJPBjORRrlyEACSp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AJPBjORRrlyEACSp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AJPBjORRrlyEACSp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AJPBjORRrlyEACSp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AJPBjORRrlyEACSp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AJPBjORRrlyEACSp .cluster text{fill:#333;}#mermaid-svg-AJPBjORRrlyEACSp .cluster span{color:#333;}#mermaid-svg-AJPBjORRrlyEACSp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AJPBjORRrlyEACSp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AJPBjORRrlyEACSp rect.text{fill:none;stroke-width:0;}#mermaid-svg-AJPBjORRrlyEACSp .icon-shape,#mermaid-svg-AJPBjORRrlyEACSp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AJPBjORRrlyEACSp .icon-shape p,#mermaid-svg-AJPBjORRrlyEACSp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AJPBjORRrlyEACSp .icon-shape .label rect,#mermaid-svg-AJPBjORRrlyEACSp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AJPBjORRrlyEACSp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AJPBjORRrlyEACSp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AJPBjORRrlyEACSp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 在,且不超限
不在 / 超限
是
否
批准
拒绝
Agent 想执行一个操作
权限检查:
在允许清单里吗?
放行,执行
需要人工审批?
暂停,等人批准
拒绝,回填「无权限」
4.4 伪代码:一个带权限校验的工具调用
text
function 执行工具(工具名, 参数, 权限清单):
# ① 查这个工具需要什么权限
所需权限 = 工具权限表[工具名]
# ② 校验:Agent 有没有这些权限、参数有没有超限
if 所需权限 不在 权限清单:
拒绝,返回 "无权限调用此工具"
if 参数超限(参数, 限额): # 例如金额超过上限、路径越界
拒绝,返回 "参数超出允许范围"
# ③ 是否需要人工审批(如:删除、群发邮件等高危操作)
if 所需权限 属于 高危操作:
审批结果 = 发起审批(工具名, 参数)
if 审批结果 != 批准:
拒绝,返回 "操作被拒绝"
# ④ 都过了,才真正执行
结果 = 真正执行(工具名, 参数)
记录审计日志(工具名, 参数, 结果) # 见下一章
return 结果
一句话 :权限模型是沙箱的「通行证制度 」------最小权限打底,粒度细到路径/命令/金额,高危操作走审批。核心思想:默认拒绝,显式授权。宁可让 Agent 多问一句「我能这么做吗」,也别让它闷头就干。
五、审计与可观测:每一步都要留痕
沙箱不只是「拦 」,更要「记」。拦住一次危险操作还不够,你得知道「它到底干了啥」。
5.1 为什么留痕重要?
因为 Agent 是「自主」的------它可能跑了几十步、调了几十个工具,你不可能全程盯着。一旦出事,你得能回答三个问题:
text
① 出了什么事? ------ 删了哪个文件?发了什么邮件?
② 谁让它干的? ------ 哪个模型?哪个用户?哪次会话?
③ 怎么发生的? ------ 是哪一步、什么参数、什么原因导致的?
没有审计日志,这三个问题一个都答不上来,出了事就是「一笔糊涂账」。
5.2 记录什么?
一条合格的审计日志,至少包含:
text
审计记录 = {
时间: "2026-08-28 14:30:00", # 什么时候
操作者: "agent-42 / user-张三", # 谁
工具: "delete_file", # 干了啥
参数: "/data/prod/orders.db", # 具体参数
结果: "成功 / 失败 / 被拦截", # 结果如何
花费: "0.02 元 / 1.3 秒", # 花了多少
会话: "session-20260828-001" # 哪个会话(可追溯)
}
#mermaid-svg-UtZwYC37RYWKZ4c8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UtZwYC37RYWKZ4c8 .error-icon{fill:#552222;}#mermaid-svg-UtZwYC37RYWKZ4c8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UtZwYC37RYWKZ4c8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .marker.cross{stroke:#333333;}#mermaid-svg-UtZwYC37RYWKZ4c8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UtZwYC37RYWKZ4c8 p{margin:0;}#mermaid-svg-UtZwYC37RYWKZ4c8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .cluster-label text{fill:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .cluster-label span{color:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .cluster-label span p{background-color:transparent;}#mermaid-svg-UtZwYC37RYWKZ4c8 .label text,#mermaid-svg-UtZwYC37RYWKZ4c8 span{fill:#333;color:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .node rect,#mermaid-svg-UtZwYC37RYWKZ4c8 .node circle,#mermaid-svg-UtZwYC37RYWKZ4c8 .node ellipse,#mermaid-svg-UtZwYC37RYWKZ4c8 .node polygon,#mermaid-svg-UtZwYC37RYWKZ4c8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .rough-node .label text,#mermaid-svg-UtZwYC37RYWKZ4c8 .node .label text,#mermaid-svg-UtZwYC37RYWKZ4c8 .image-shape .label,#mermaid-svg-UtZwYC37RYWKZ4c8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-UtZwYC37RYWKZ4c8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .rough-node .label,#mermaid-svg-UtZwYC37RYWKZ4c8 .node .label,#mermaid-svg-UtZwYC37RYWKZ4c8 .image-shape .label,#mermaid-svg-UtZwYC37RYWKZ4c8 .icon-shape .label{text-align:center;}#mermaid-svg-UtZwYC37RYWKZ4c8 .node.clickable{cursor:pointer;}#mermaid-svg-UtZwYC37RYWKZ4c8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .arrowheadPath{fill:#333333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UtZwYC37RYWKZ4c8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UtZwYC37RYWKZ4c8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UtZwYC37RYWKZ4c8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UtZwYC37RYWKZ4c8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .cluster text{fill:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 .cluster span{color:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UtZwYC37RYWKZ4c8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UtZwYC37RYWKZ4c8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-UtZwYC37RYWKZ4c8 .icon-shape,#mermaid-svg-UtZwYC37RYWKZ4c8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UtZwYC37RYWKZ4c8 .icon-shape p,#mermaid-svg-UtZwYC37RYWKZ4c8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UtZwYC37RYWKZ4c8 .icon-shape .label rect,#mermaid-svg-UtZwYC37RYWKZ4c8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UtZwYC37RYWKZ4c8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UtZwYC37RYWKZ4c8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UtZwYC37RYWKZ4c8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 每次工具调用
自动记录一条审计日志
时间 / 操作者 / 工具 / 参数 / 结果 / 花费
出事时:可回溯 / 可追责 / 可复现
一句话 :审计是可观测的「证据链 」。沙箱不仅要「拦得住」,还要「记得清 」------谁、在何时、做了什么、结果如何、花了多少,一条都不能少。没有留痕的沙箱,等于没装监控的保险柜。
六、沙箱与编排的关系:安全是编排的一部分
讲到这里,你可能想问:上一篇讲的「编排」,和这一篇的「沙箱」,是什么关系?
6.1 沙箱是「兜底」的更深一层
上一篇《Agent 工具编排》第八章讲过「兜底」------幻觉、死循环、失败、冲突,都要有后手。而沙箱,是这些「兜底」里最硬的一层:
- 幻觉兜底(校验参数)------沙箱帮你拦;
- 死循环兜底(最大步数)------沙箱帮你限资源;
- 工具失败兜底(重试降级)------沙箱帮你记日志。
换句话说:编排管「怎么做得对」,沙箱管「怎么做得不出事」。 一个是油门,一个是刹车。
6.2 每一步工具调用,都要过沙箱的「闸门」
回到上一篇的 ReAct 循环。加上沙箱后,这个循环的「行动」环节,多了一道闸门:
#mermaid-svg-euF2IHhRk36gjbEr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-euF2IHhRk36gjbEr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-euF2IHhRk36gjbEr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-euF2IHhRk36gjbEr .error-icon{fill:#552222;}#mermaid-svg-euF2IHhRk36gjbEr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-euF2IHhRk36gjbEr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-euF2IHhRk36gjbEr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-euF2IHhRk36gjbEr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-euF2IHhRk36gjbEr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-euF2IHhRk36gjbEr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-euF2IHhRk36gjbEr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-euF2IHhRk36gjbEr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-euF2IHhRk36gjbEr .marker.cross{stroke:#333333;}#mermaid-svg-euF2IHhRk36gjbEr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-euF2IHhRk36gjbEr p{margin:0;}#mermaid-svg-euF2IHhRk36gjbEr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-euF2IHhRk36gjbEr .cluster-label text{fill:#333;}#mermaid-svg-euF2IHhRk36gjbEr .cluster-label span{color:#333;}#mermaid-svg-euF2IHhRk36gjbEr .cluster-label span p{background-color:transparent;}#mermaid-svg-euF2IHhRk36gjbEr .label text,#mermaid-svg-euF2IHhRk36gjbEr span{fill:#333;color:#333;}#mermaid-svg-euF2IHhRk36gjbEr .node rect,#mermaid-svg-euF2IHhRk36gjbEr .node circle,#mermaid-svg-euF2IHhRk36gjbEr .node ellipse,#mermaid-svg-euF2IHhRk36gjbEr .node polygon,#mermaid-svg-euF2IHhRk36gjbEr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-euF2IHhRk36gjbEr .rough-node .label text,#mermaid-svg-euF2IHhRk36gjbEr .node .label text,#mermaid-svg-euF2IHhRk36gjbEr .image-shape .label,#mermaid-svg-euF2IHhRk36gjbEr .icon-shape .label{text-anchor:middle;}#mermaid-svg-euF2IHhRk36gjbEr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-euF2IHhRk36gjbEr .rough-node .label,#mermaid-svg-euF2IHhRk36gjbEr .node .label,#mermaid-svg-euF2IHhRk36gjbEr .image-shape .label,#mermaid-svg-euF2IHhRk36gjbEr .icon-shape .label{text-align:center;}#mermaid-svg-euF2IHhRk36gjbEr .node.clickable{cursor:pointer;}#mermaid-svg-euF2IHhRk36gjbEr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-euF2IHhRk36gjbEr .arrowheadPath{fill:#333333;}#mermaid-svg-euF2IHhRk36gjbEr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-euF2IHhRk36gjbEr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-euF2IHhRk36gjbEr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-euF2IHhRk36gjbEr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-euF2IHhRk36gjbEr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-euF2IHhRk36gjbEr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-euF2IHhRk36gjbEr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-euF2IHhRk36gjbEr .cluster text{fill:#333;}#mermaid-svg-euF2IHhRk36gjbEr .cluster span{color:#333;}#mermaid-svg-euF2IHhRk36gjbEr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-euF2IHhRk36gjbEr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-euF2IHhRk36gjbEr rect.text{fill:none;stroke-width:0;}#mermaid-svg-euF2IHhRk36gjbEr .icon-shape,#mermaid-svg-euF2IHhRk36gjbEr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-euF2IHhRk36gjbEr .icon-shape p,#mermaid-svg-euF2IHhRk36gjbEr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-euF2IHhRk36gjbEr .icon-shape .label rect,#mermaid-svg-euF2IHhRk36gjbEr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-euF2IHhRk36gjbEr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-euF2IHhRk36gjbEr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-euF2IHhRk36gjbEr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调工具
放行
完成
拦截
开始
思考 Thought
什么动作?
沙箱闸门
权限校验 + 资源限制 + 审批
行动 Action
审计留痕
观察 Observation
输出答案
🎯 关键点:沙箱不是独立于编排的「外挂」,而是嵌入在编排的每一步里的「闸门」。每一次「行动」,都得先过闸门,才能落地。
一句话 :编排和沙箱是一对------编排是「油门」,沙箱是「刹车」 。一个负责任的 Agent,不是「编排 + 沙箱」两个东西拼起来,而是「每一次行动,都天然带着安全闸门」的编排。
七、一个完整的沙箱执行流程(伪代码 + 时序图)
最后,把前面所有概念,串成「一次带沙箱的工具调用」的完整流程。这是本文的「总纲」。
7.1 时序图:从「模型想调工具」到「结果回填」
真实工具 沙箱(权限+隔离+审计) 宿主程序 模型 真实工具 沙箱(权限+隔离+审计) 宿主程序 模型 #mermaid-svg-1YKpAPWuQDv7Eqtl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1YKpAPWuQDv7Eqtl .error-icon{fill:#552222;}#mermaid-svg-1YKpAPWuQDv7Eqtl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1YKpAPWuQDv7Eqtl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1YKpAPWuQDv7Eqtl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1YKpAPWuQDv7Eqtl .marker.cross{stroke:#333333;}#mermaid-svg-1YKpAPWuQDv7Eqtl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1YKpAPWuQDv7Eqtl p{margin:0;}#mermaid-svg-1YKpAPWuQDv7Eqtl .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1YKpAPWuQDv7Eqtl text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-1YKpAPWuQDv7Eqtl .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-1YKpAPWuQDv7Eqtl .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-1YKpAPWuQDv7Eqtl #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-1YKpAPWuQDv7Eqtl .sequenceNumber{fill:white;}#mermaid-svg-1YKpAPWuQDv7Eqtl #sequencenumber{fill:#333;}#mermaid-svg-1YKpAPWuQDv7Eqtl #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-1YKpAPWuQDv7Eqtl .messageText{fill:#333;stroke:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1YKpAPWuQDv7Eqtl .labelText,#mermaid-svg-1YKpAPWuQDv7Eqtl .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .loopText,#mermaid-svg-1YKpAPWuQDv7Eqtl .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-1YKpAPWuQDv7Eqtl .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-1YKpAPWuQDv7Eqtl .noteText,#mermaid-svg-1YKpAPWuQDv7Eqtl .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-1YKpAPWuQDv7Eqtl .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1YKpAPWuQDv7Eqtl .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1YKpAPWuQDv7Eqtl .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1YKpAPWuQDv7Eqtl .actorPopupMenu{position:absolute;}#mermaid-svg-1YKpAPWuQDv7Eqtl .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-1YKpAPWuQDv7Eqtl .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1YKpAPWuQDv7Eqtl .actor-man circle,#mermaid-svg-1YKpAPWuQDv7Eqtl line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-1YKpAPWuQDv7Eqtl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt校验通过校验不通过 我想调用 delete_file,参数是 /data/prod/x把这次调用交给沙箱① 权限校验(有没有 delete 权限?)② 路径校验(/data/prod 在允许范围吗?)③ 高危审批(删除要审批?)在隔离环境里真正执行返回结果④ 记录审计日志结果拦截原因(无权限 / 越界 / 审批被拒)把结果/拦截原因 回填给模型基于结果决定下一步
7.2 语言无关伪代码:带沙箱的 Agent Loop
text
function 带沙箱的Agent(用户目标):
上下文 = [用户目标]
权限清单 = 初始化最小权限() # 只给必要的权限
审计日志 = []
while 未完成 且 步数 < 最大步数:
动作 = 模型.决策(上下文)
if 动作 == "完成":
return 动作.最终答案
# ------ 沙箱闸门:每次行动前都要过这四关 ------
# ① 权限校验
if 动作.工具名 不在 权限清单:
结果 = "被拦截:无权限调用该工具"
# ② 参数/限额校验
elif 参数越界(动作.参数):
结果 = "被拦截:参数超出允许范围"
# ③ 高危操作审批
elif 是高危(动作.工具名) 且 审批未通过:
结果 = "被拦截:高危操作未获批准"
# ④ 都通过,才在隔离环境里执行
else:
结果 = 隔离执行(动作) # 进程/容器/VM 里跑
# 无论放行还是拦截,都要留痕
审计日志.append({
时间, 动作.工具名, 动作.参数, 结果
})
上下文.append(结果) # 把「结果」或「拦截原因」都回填
return "达到步数上限,任务未完成"
注意这段伪代码的精髓:「拦截原因」和「执行结果」一视同仁,都回填给模型。这样模型才知道「哦,我刚才的操作被拦了,因为没权限」,从而换个思路------而不是在错误的方向上反复撞墙。
一句话 :一个完整的沙箱流程 = 权限校验 → 参数限额 → 高危审批 → 隔离执行 → 审计留痕 → 回填。它贯穿每一次工具调用,让 Agent 的「每一步行动」,都在「被允许、被记录、可追溯」的前提下发生。