第八章:沙盒与安全防御(Guardrails)
欢迎来到第八章!在前面的章节中,我们已经构建了一个功能完善的 AI Agent,具备了工具调用、上下文管理、记忆系统和 RAG 能力。
然而,当 Agent 能够执行命令、读写文件时,安全性就变得至关重要。本章介绍如何为 Agent 设计安全防护机制,包括 Docker 沙盒隔离和人工确认机制。
🎯 你将学到什么
- Docker 沙盒隔离:在容器中运行 bash 命令,保障本地环境安全
- 智能工具选择:自动检测 Docker 可用性,优雅降级到普通 bash
- 人工确认(Human-in-the-loop):在执行危险命令前请求用户确认
- 确认状态管理:Allow/Reject/Always Allow 三种确认选项
- Context 取消机制:用户按 ESC 提前终止 Agent Loop
🛠 核心功能
1. Docker 沙盒隔离
问题:Agent 执行的 bash 命令可能对本地系统造成破坏性影响。
解决方案:使用 Docker 容器隔离执行环境,限制命令的影响范围。
沙盒架构:
┌─────────────────────────────────────────────────┐
│ Host Machine │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ Docker Container: babyagent-sandbox │ │
│ │ Image: alpine:3.19 │ │
│ │ │ │
│ │ /workspace (mounted) ←→ Project Dir │ │
│ │ │ │
│ │ $ bash commands execute here │ │
│ └────────────────────────────────────────────┘ │
│ │
│ docker exec container sh -c "command" │
└─────────────────────────────────────────────────┘核心特性:
- 工作区隔离:每个工作区使用独立的容器(容器名包含项目名称)
- Lazy Initialization:首次使用时自动启动容器
- 自动创建:容器不存在时自动创建并配置
- 卷挂载:将项目目录挂载到容器的
/workspace - 优雅降级:Docker 不可用时自动切换到普通 bash
- 保持运行:容器使用
sleep infinity保持运行状态
容器命名规则:
- 项目目录
/home/user/project-a→ 容器名babyagent-sandbox-project-a - 项目目录
/home/user/project-b→ 容器名babyagent-sandbox-project-b
这样每个工作区都有独立的沙盒环境,互不干扰。
工具工厂模式:
系统会自动检测 Docker 是否可用:
- Docker 可用 + 工作目录非空 → 使用
DockerBashTool - Docker 不可用或工作目录为空 → 使用普通
BashTool
2. 工具调用确认
问题:Agent 可能执行危险操作(如 rm -rf),需要人工干预。
解决方案:为工具配置确认选项,执行前展示确认框。
┌─────────────────────────────────────────┐
│ 工具确认 │
│ bash(cowsay "Hello") │
│ │
│ ┌─────────────────────────┐ │
│ │ ▶ 允许 │ │
│ │ 拒绝 │ │
│ │ 始终允许 │ │
│ └─────────────────────────┘ │
│ │
│ ↑↓ 选择 Enter 确认 Esc 拒绝 │
└─────────────────────────────────────────┘三种确认选项:
- 允许:执行本次工具调用
- 拒绝:拒绝本次调用,终止 Agent Loop
- 始终允许:执行并记录,当前会话同类工具不再确认
3. 提前终止 Loop(ESC)
需求:用户可以随时按 ESC 终止 Agent Loop。
实现机制:
- TUI 创建可取消的 context
- 用户按 ESC → 发送取消信号
- Agent 检测到取消 → 跳过 policies/memory,保存当前状态
📖 代码结构速览
Agent (ch08/agent.go)
ToolConfirmConfig:工具确认配置alwaysAllowTools:当前会话的"始终允许"记录findTool():统一的工具查找方法(支持本地和 MCP 工具)RunStreaming():支持确认和取消的流式请求
Docker Tool (ch08/tool/docker_bash.go)
DockerBashTool:Docker 容器化 bash 工具ensureSandboxContainer():确保容器运行(启动或创建)- Lazy 初始化:首次使用时启动容器
Tool Factory (ch08/tool/factory.go)
CreateBashTool():智能 bash 工具创建函数checkDockerAvailable():检测 Docker 是否可用- 自动选择合适的 bash 工具实现
VO (ch08/vo.go)
ConfirmationAction:确认动作枚举(Allow/Reject/AlwaysAllow)ToolConfirmationVO:确认请求数据结构MessageTypeToolConfirm:确认消息类型
TUI (ch08/tui/tui.go)
stateAwaitingConfirmation:等待用户确认状态confirmOptions:确认选项列表selectedConfirmIdx:当前选中的选项索引renderConfirmBox():渲染确认框 UI
💡 使用示例
运行 TUI
bash
go run ./ch08/mainDocker 沙盒示例
首次运行:
你: 列出当前目录的文件
Agent: [检测到 Docker,启动沙盒容器...]
[创建容器 babyagent-sandbox,镜像 alpine:3.19]
Agent: [在容器中执行命令]
docker exec babyagent-sandbox sh -c "ls -la"
输出: drwxr-xr-x workspace/
-rw-r--r-- main.go
-rw-r--r-- README.md
...工具确认示例
你: 用 bash 说 hello
Agent: 准备调用 bash 工具
[确认框弹出]
┌─────────────────────────────────┐
│ 工具确认 │
│ bash(cowsay "Hello") │
│ │
│ ▶ 允许 │
│ 拒绝 │
│ 始终允许 │
└─────────────────────────────────┘
│ ↑↓ 选择 Enter 确认 Esc 拒绝 │
[用户按 ↓ 选择"始终允许",Enter 确认]
Agent: [在容器中执行命令]
docker exec babyagent-sandbox sh -c "cowsay Hello"
输出: ____
/ Hello \
--------
\ /
\/
[后续 bash 调用不再需要确认]ESC 取消示例
你: 帮我删除所有日志文件
Agent: 准备调用 bash
[用户按 ESC]
提示: 用户取消了 agent loop,消息已保留。
你: 继续执行删除操作
[Agent 从上次消息继续,不需要重新上下文]🔧 配置说明
工具确认配置
在 ch08/tui/main.go 中配置需要确认的工具:
tool.AgentToolBash:bash 命令需要确认tool.AgentToolWrite:写文件需要确认tool.AgentToolEdit:编辑文件需要确认tool.AgentToolRead:读取文件通常不需要确认
MCP 工具确认
MCP 工具使用完整工具名(如 babyagent_mcp__filesystem__write_file)作为 key 进行配置。
Docker 沙盒配置
默认配置(可在 ch08/tool/docker_bash.go 中修改):
- 容器名称:
babyagent-sandbox-{项目名}(每个工作区独立) - 镜像:
alpine:3.19 - 工作目录:自动挂载当前项目目录到
/workspace
⚠️ 注意事项
- Docker 要求:使用 Docker 沙盒需要本地安装并启动 Docker
- 容器持久化:容器使用
unless-stopped重启策略,重启后自动运行 - 确认状态与会话绑定:
alwaysAllowTools在ResetSession()后清空 - ConfirmReject 终止 Loop:拒绝工具调用会返回错误,退出循环
📚 延伸阅读
功能扩展方向
更细粒度的确认策略
- 按命令前缀:
rm*开头的命令需要确认 - 按文件路径:修改
/etc/*文件需要确认 - 按参数大小:大文件操作需要确认
- 按时间窗口:第一次调用确认,N 分钟内免确认
审计日志
- 记录所有工具调用和用户确认决策
- 便于安全审计和问题排查
权限级别
- Safe:无需确认(如读取文件)
- Warning:需要确认(如写入文件)
- Danger:需要二次确认(如删除操作)
更强大的沙盒
- 网络隔离:禁止容器访问外网
- 资源限制:CPU、内存使用限制
- 只读挂载:某些目录只读挂载,防止篡改
Docker 与容器安全
Docker 安全最佳实践
- 使用非 root 用户运行容器
- 限制容器资源(CPU、内存)
- 只读文件系统
- 网络隔离与防火墙规则
容器逃逸防护
- 避免特权模式(--privileged)
- 谨慎使用卷挂载
- AppArmor/Seccomp 配置
AI Agent 安全
Prompt Injection:提示词注入攻击与防御
- 研究案例:indirect prompt injection
- 防御策略:输入验证、输出清洗、分隔符设计
工具调用安全:限制 Agent 能力范围
- 白名单/黑名单策略
- 沙箱执行环境
- 审计与监控
Human-in-the-Loop:人机协同的安全设计
- 关键操作人工确认
- 可解释性与透明度
- 紧急停止机制
相关工具与框架
- E2B:专为 AI Agent 设计的沙箱环境
- Docker Sandboxing:使用 Docker 构建隔离执行环境
- gVisor:用户空间内核,更强的容器隔离
- Firecracker:轻量级虚拟机,微秒级启动
推荐资源
- OWASP LLM Top 10:大语言模型应用的安全风险清单
- Anthropic Constitutional AI:通过原则约束 AI 行为
- OpenAI Safety Guidelines:OpenAI 的安全实践指南
- Claude's Guardrails:Claude 的安全防护机制设计