Agent Runtime & Sandbox —— 运行时与沙箱 / Runtime & Sandbox
本章观点
前几章讲的 Agent 都是"逻辑层"——LLM 决策、工具调用、context 管理。但 Agent 真正跑起来,还有一个物理层问题:
Agent 在哪里跑?怎么跑?失败怎么恢复?能不能闯祸?
这四个问题对应两块工程:
- Agent Runtime(运行时):解决"在哪跑、怎么跑、失败怎么恢复"
- Agent Sandbox(沙箱):解决"能不能闯祸、闯了多大祸能兜住"
这两块是 Agent 从 Demo 变成生产系统的关键分水岭。一个 Demo Agent 在你本地跑通了,搬到生产环境第一个崩的就是 runtime,第二个出事的就是 sandbox 没设。
这一章讲 Runtime 和 Sandbox 的设计原则、主流方案、踩坑经验。
9.1 Agent Runtime 是什么
Agent Runtime = Agent 执行任务的物理环境 + 生命周期管理。
具体包括:
| 能力 | 解决什么 | 例子 |
|---|---|---|
| Execution Environment | Agent 在哪跑 | 本地进程 / 容器 / VM / 云函数 |
| Shell | Agent 能执行什么命令 | bash / 受限 shell |
| Filesystem | Agent 能读写哪 | 工作目录 / 挂载卷 |
| Browser | Agent 能上网吗 | Headless Chrome / Playwright |
| Queue | 任务怎么排队 | Redis / RabbitMQ |
| Cron | 定时任务怎么触发 | crontab / Cloudflare Cron |
| Retry | 失败怎么办 | 指数退避 / 有限重试 |
| Timeout | 卡住怎么办 | 单步超时 / 总超时 |
| Rollback | 改坏了怎么办 | git revert / 快照恢复 |
| Checkpoint | 崩了能续吗 | 序列化 state |
| Durable Execution | 长任务怎么不丢 | Temporal / Restate |
没有 Runtime 的 Agent,本质就是个本地脚本——只能在你电脑上跑,崩了就崩了,跑长任务会断。有 Runtime 的 Agent 才是生产系统。
9.2 Execution Environment:Agent 在哪跑
四种典型环境
| 环境 | 隔离性 | 启动速度 | 成本 | 适合 |
|---|---|---|---|---|
| 本地进程 | 无 | 即时 | 0 | 开发 / Demo |
| 容器 (Docker) | 中 | 秒级 | 低 | 单机部署 |
| MicroVM (Firecracker) | 高 | 毫秒级 | 中 | 多租户 |
| 云函数 (Lambda/Workers) | 高 | 秒级 | 按调用 | 事件驱动 |
Claude Code 的环境
Claude Code 在你本地终端跑,直接访问你的 shell 和文件系统。隔离性最低但灵活性最高——适合开发者自己用,不适合给多用户服务。
OpenHands 的环境
OpenHands 用 Docker 容器作为 runtime。每个任务起一个容器,容器里有:
- 完整的 shell
- Python / Node 环境
- 工作目录挂载
- 网络访问(可关)
任务结束容器销毁。这是"单机多租户"的标准方案。
E2B / Daytona 的环境
E2B 和 Daytona 提供"沙箱即服务":你调 API 就能得到一个隔离的代码执行环境。适合不想自己管 Docker 的团队。
选型建议
- 个人用 / 开发:本地进程(Claude Code 模式)
- 单机生产:Docker 容器(OpenHands 模式)
- 多租户 SaaS:MicroVM(Firecracker / gVisor)
- 事件驱动 / 无状态:云函数(Lambda / Cloudflare Workers)
- 不想管基建:E2B / Daytona
9.3 Shell 与 Filesystem:Agent 的手脚
Shell
Agent 调 Bash 工具时,本质是 runtime 起一个子进程执行命令。要决定:
| 决策 | 选项 | 建议 |
|---|---|---|
| 用什么 shell | bash / sh / 受限 shell | 受限 shell(rbash)更安全 |
| 能跑什么命令 | 白名单 / 黑名单 / 全放 | 白名单 + 黑名单组合 |
| 命令时长 | 单步超时 | 30s 默认,可配 |
| 输出捕获 | stdout / stderr / 退出码 | 三个都要 |
| 环境变量 | 继承 / 隔离 | 隔离,只显式注入 |
Filesystem
Agent 读写文件的范围要明确:
工作目录(Agent 可读写)
├── input/ ← 用户上传,只读
├── workspace/ ← Agent 工作区,可读写
├── output/ ← 结果输出,可写
└── system/ ← 系统文件,禁止访问关键原则:Agent 的工作目录要和系统目录隔离。Claude Code 用项目根目录作为边界,OpenHands 用容器文件系统作为边界。
命令白名单示例
Claude Code 的 Permission 系统就是这么设计的:
{
"permissions": {
"Bash": {
"allow": ["ls *", "cat *", "grep *", "git status", "git diff *"],
"deny": ["rm -rf *", "sudo *", "curl * | sh", "git push --force *"]
}
}
}白名单放行只读命令,黑名单拦截危险命令,灰色地带(如 git commit)询问用户。
9.4 Browser:Agent 上网
为什么 Agent 需要浏览器
很多任务离不开浏览器:
- 看网页内容(搜索结果、文档)
- 测试 Web 应用(E2E 测试)
- 抓取动态渲染内容(SPA)
- 自动化操作(填表、点击)
三种方案
| 方案 | 实现 | 适合 |
|---|---|---|
| HTTP 抓取 | requests.get(url) | 静态页面 |
| Headless Chrome | Playwright / Puppeteer | 动态页面、SPA |
| Browser MCP | microsoft/playwright-mcp | Agent 友好的浏览器控制 |
Playwright MCP 的设计
Playwright MCP 把浏览器能力包装成 MCP tools:
browser_navigate(url)— 导航browser_click(target)— 点击browser_type(target, text)— 输入browser_snapshot()— 获取页面快照browser_evaluate(js)— 执行 JS
Agent 调这些工具就像调函数,不用解析 HTML。这是浏览器 Agent 的主流方案。
Browser Sandbox 注意点
- 隔离用户会话:Agent 用的浏览器不能登录用户的账号(除非显式授权)
- 限制域名:Agent 只能访问白名单域名
- 下载隔离:下载文件放工作目录,不进系统下载文件夹
- 网络监控:记录所有 HTTP 请求,便于审计
9.5 Queue & Cron:长任务和定时任务
Queue:任务排队
Agent 任务经常是长耗时(几分钟到几小时)。直接同步处理会超时,必须用队列:
用户提交任务 → 入队 (Redis / RabbitMQ / SQS)
↓
Worker 进程取出任务
↓
起 Agent runtime 执行
↓
结果写回数据库 + 通知用户主流方案:
| 方案 | 适合 |
|---|---|
| Redis + BullMQ | 单机 / 小规模 |
| RabbitMQ | 复杂路由 |
| AWS SQS | 云原生 |
| Cloudflare Queues | 边缘计算 |
Cron:定时触发
很多 Agent 是定时的(每周论文追踪、每日报告)。两种实现:
传统 cron:
# crontab
0 9 * * 1 python paper_tracker.py # 每周一 9 点云函数 cron:
# wrangler.toml (Cloudflare Workers)
[triggers]
crons = ["0 9 * * 1"]云函数 cron 的好处是不用管服务器,坏处是执行时长受限(Lambda 15 分钟上限)。
长任务的工作流
Cron 触发
→ 入队
→ Worker 起容器
→ Agent 执行(可能跑几小时)
→ 写 Checkpoint(每 N 分钟)
→ 完成 → 通知用户
→ 失败 → 重试或人工介入这套工作流是 OpenHands、Devin 这类产品的标准架构。
9.6 Retry / Timeout / Rollback:失败处理
Retry:重试
工具调用失败时重试。但要分情况:
| 失败类型 | 是否重试 | 重试策略 |
|---|---|---|
| 网络超时 | 是 | 指数退避,最多 3 次 |
| API 限流 (429) | 是 | 看 Retry-After header |
| 临时错误 (5xx) | 是 | 指数退避 |
| 永久错误 (4xx) | 否 | 直接报错给 LLM |
| 工具内部 bug | 否 | 报错给 LLM 让它换方法 |
import time
import random
def retry_with_backoff(fn, max_retries=3, base_delay=1.0):
for attempt in range(max_retries):
try:
return fn()
except TransientError as e:
if attempt == max_retries - 1:
raise
delay = base_delay * (2 ** attempt) + random.random()
time.sleep(delay)不要无脑重试。重试 3 次还失败,就该把错误返回给 LLM 让它换方法,而不是继续磨。
Timeout:超时
两层超时:
# 单步超时:单个工具调用最多 30 秒
result = call_tool_with_timeout(tool, args, timeout=30)
# 总超时:整个 Agent 任务最多 10 分钟
agent_result = run_agent_with_timeout(task, total_timeout=600)超时不是失败,是"该停了"。Agent 收到超时应该总结当前进度,而不是机械继续。
Rollback:回滚
Agent 改坏文件怎么办?三种回滚策略:
| 策略 | 实现 | 适合 |
|---|---|---|
| Git revert | git checkout -- . | 代码项目 |
| 文件快照 | 任务开始时复制工作目录 | 临时文件操作 |
| 数据库事务 | BEGIN / ROLLBACK | DB 操作 |
Claude Code 默认依赖 git,用户随时可以 git stash 或 git checkout 回退。OpenHands 在容器内做事,整个容器可以销毁重建——这是"硬回滚"。
9.7 Checkpoint & Durable Execution
Checkpoint:状态序列化
Checkpoint = 把 Agent 的 State(第 5 章 Context Engineering 讲过)序列化存盘。崩了能从 checkpoint 续跑,不用从头。
LangGraph 的 checkpoint 设计是范本:
from langgraph.checkpoint.memory import MemorySaver
workflow = StateGraph(State)
# ... add nodes / edges
app = workflow.compile(checkpointer=MemorySaver())
# 每次调用都会自动存 checkpoint
config = {"configurable": {"thread_id": "task-123"}}
result = app.invoke(initial_state, config=config)
# 崩了后续可以从 thread_id 恢复
resumed = app.invoke(None, config=config) # 从最近 checkpoint 继续Durable Execution:持久化执行
Durable Execution 比 Checkpoint 更进一步:整个执行流(包括等待外部事件)都持久化。
典型场景:
- Agent 发邮件后等用户回复(可能等几天)
- Agent 提 PR 后等 CI 跑完(可能等几十分钟)
- Agent 调外部 API,API 异步回调
传统做法是写轮询代码,丑且易错。Durable Execution 框架(Temporal、Restate、DBOS)让你写"看起来同步"的代码,框架自动处理持久化:
# Temporal 风格(伪代码)
@workflow
def agent_workflow(task):
email_sent = send_email(task.user_email)
# 这里 workflow 会"休眠",等用户回复
# 即使 workflow 进程崩了,重启后能从这继续
reply = wait_for_reply(email_sent.id, timeout=86400)
if reply.approved:
execute_task(task)
else:
notify_user(task, "rejected")主流 Durable Execution 方案
| 方案 | 特点 | 适合 |
|---|---|---|
| Temporal | 最成熟,支持复杂工作流 | 企业级长流程 |
| Restate | 轻量,Rust 写的 | 中小项目 |
| DBOS | 数据库原生 | 数据密集型 |
| Inngest | Serverless 友好 | 边缘计算 |
| LangGraph Checkpoint | 简单 state 持久化 | Agent 状态机 |
Durable Execution 是长任务 Agent 的必选项。如果你的 Agent 任务可能跑超过 1 分钟,就要考虑 Durable Execution。
9.8 Agent Sandbox 是什么
Agent Sandbox = 限制 Agent 能力的隔离环境。
Sandbox 和 Runtime 的关系:
Runtime 解决"Agent 怎么跑",Sandbox 解决"Agent 不能干什么"。
Runtime 是"提供能力",Sandbox 是"限制能力"。两者通常在同一层实现(比如 Docker 容器既是 runtime 也是 sandbox)。
9.9 Sandbox 的十个维度
1. 文件权限
Agent 能读写哪些路径。
✅ 允许:/workspace/**
❌ 禁止:/etc/**, ~/.ssh/**, /root/**实现:
- Docker volume 挂载限制
- Linux capabilities(CAP_DAC_OVERRIDE 去掉)
- chroot / namespace
2. Shell 权限
Agent 能执行什么命令。第 9.3 节讲过:白名单 + 黑名单 + 询问。
3. 网络访问
Agent 能访问哪些域名 / 端口。
✅ 允许:api.anthropic.com, api.github.com
❌ 禁止:169.254.169.254 (云元数据), 内网 IP 段实现:
- DNS 黑洞
- iptables 规则
- Egress proxy
特别重要:云环境的元数据服务(如 AWS 169.254.169.254)能拿到 IAM 凭证。Agent 必须禁止访问。
4. 浏览器隔离
Agent 用的浏览器不能访问用户登录态。
# ✅ 用全新 profile
browser = playwright.chromium.launch_persistent_context(
user_data_dir="/tmp/agent-profile", # 独立 profile
# 不复用用户 Chrome 的 cookies / 密码
)5. 数据库权限
Agent 查数据库时,应该用只读账号。
-- 创建 Agent 专用只读账号
CREATE USER agent_ro WITH PASSWORD '...';
GRANT SELECT ON all_tables TO agent_ro;
-- 不给 INSERT / UPDATE / DELETE写操作要明确白名单:哪些表能写,哪些字段不能动。
6. API Key / Secret 管理
Agent 不应该直接拿到原始 secret。两种方案:
方案 A:Secret 注入到环境变量
# Agent runtime 启动时注入
os.environ["ANTHROPIC_API_KEY"] = get_secret("anthropic")
# Agent 代码用 os.environ["ANTHROPIC_API_KEY"]方案 B:通过 MCP server 代理
Agent → MCP server (持有 secret) → 外部 API
↑
Agent 拿不到原始 secret方案 B 更安全,因为 Agent 代码永远看不到 secret。Claude Code 的 MCP server 就是这个模式——MCP server 持有 GitHub token,Agent 只能调 github.* 工具。
7. 危险操作人工确认
副作用类操作必须人工确认:
# Claude Code 的 Permission 系统
def execute_tool(tool_name, args):
if tool_name in DANGEROUS_TOOLS:
# 弹窗让用户确认
approved = ask_user(f"执行 {tool_name}({args})?")
if not approved:
return {"error": "用户拒绝"}
return run_tool(tool_name, args)危险操作分级:
| 级别 | 操作 | 处理 |
|---|---|---|
| 安全 | read_file, ls, grep | 自动放行 |
| 中等 | write_file, git commit | 询问(默认允许) |
| 危险 | rm -rf, git push --force, send_email | 必须显式确认 |
| 灾难 | drop table, sudo, `curl | sh` |
8. 日志记录
Agent 所有工具调用都要记录,便于审计:
{
"timestamp": "2026-07-08T10:30:00Z",
"agent_id": "agent-123",
"tool": "Bash",
"args": {"cmd": "rm /tmp/cache/*"},
"approved_by": "user",
"result": "success",
"duration_ms": 120
}日志要存到独立位置(Agent 不能改),保留期至少 90 天。
9. 超时控制
第 9.6 节讲过。Sandbox 层面还要加:
- 单工具超时:30 秒
- 单轮循环超时:5 分钟
- 总任务超时:1 小时(可配)
- 空闲超时:30 秒没动作自动停
10. 成本限制
Agent 烧钱无上限是个真问题。三层限制:
# Token 预算
MAX_TOKENS_PER_TASK = 1_000_000
MAX_TOKENS_PER_DAY = 10_000_000
# 调用次数
MAX_TOOL_CALLS_PER_TASK = 100
MAX_LLM_CALLS_PER_DAY = 1000
# 金钱
MAX_COST_PER_TASK = 5.0 # USD超限要么停要么升级到人工确认。
9.10 Sandbox 实现方案对比
| 方案 | 隔离强度 | 启动速度 | 复杂度 | 适合 |
|---|---|---|---|---|
| 进程 + 权限检查 | 低 | 即时 | 低 | 个人开发 |
| Docker 容器 | 中 | 秒级 | 中 | 单机生产 |
| gVisor | 高 | 秒级 | 中 | 多租户 |
| Firecracker MicroVM | 极高 | 毫秒级 | 高 | 大规模 SaaS |
| WebAssembly (Wasm) | 中高 | 毫秒级 | 中 | 轻量沙箱 |
| E2B / Daytona | 高 | 秒级 | 低 | 不想自建 |
OpenHands 的沙箱设计
OpenHands 用 Docker 容器作为沙箱,关键设计:
- 每个任务一个容器:任务结束容器销毁
- 非 root 用户:容器内用
openhands用户,不是 root - 网络白名单:默认只放行几个 API 域名
- 资源限制:CPU / 内存 / 磁盘都有 cgroup 限制
- 挂载隔离:只挂载工作目录,不挂载宿主系统
这是单机生产级沙箱的范本。
Claude Code 的沙箱策略
Claude Code 不用容器(它在你的本地终端跑),但用权限系统作为软沙箱:
Read/Glob/Grep自动放行Edit/Write在项目目录内放行Bash按白名单 + 询问- 危险操作(
rm -rf、git push --force)必须确认
这种"软沙箱"适合开发者自己用(你信任自己),不适合给多用户服务。
9.11 一个完整的 Runtime + Sandbox 架构
把前面所有概念串起来,一个生产级 Agent 系统的架构:
┌──────────────────────────────────────────┐
│ User / API Client │
└──────────────┬───────────────────────────┘
↓
┌──────────────────────────────────────────┐
│ API Gateway │
│ - 鉴权 │
│ - 限流 │
└──────────────┬───────────────────────────┘
↓
┌──────────────────────────────────────────┐
│ Task Queue (Redis / SQS) │
│ - 任务排队 │
│ - 优先级 │
└──────────────┬───────────────────────────┘
↓
┌──────────────────────────────────────────┐
│ Worker Pool │
│ - 取任务 │
│ - 起 Sandbox │
│ - 监控执行 │
└──────────────┬───────────────────────────┘
↓
┌──────────────────────────────────────────┐
│ Sandbox (Docker / MicroVM) │
│ ┌─────────────────────────────────────┐ │
│ │ Agent Runtime │ │
│ │ - LLM 调用 (Anthropic API) │ │
│ │ - Tool 执行 (Bash / Read / Write) │ │
│ │ - MCP server 连接 │ │
│ │ - Context 管理 │ │
│ │ - Checkpoint 存储 │ │
│ └─────────────────────────────────────┘ │
│ 隔离层: │
│ - 文件权限 │
│ - Shell 白名单 │
│ - 网络白名单 │
│ - 资源限制 (CPU/MEM/DISK) │
└──────────────┬───────────────────────────┘
↓
┌──────────────────────────────────────────┐
│ Persistence Layer │
│ - PostgreSQL: 任务状态 / 历史 │
│ - S3 / B2: 文件 / Checkpoint │
│ - Langfuse: Trace / Logs │
└──────────────────────────────────────────┘这套架构是 Devin、OpenHands、Manus 这类产品的共同形态。具体实现各有差别,但骨架一样。
9.12 前人智慧 / Prior Art
OpenHands 的 Runtime 哲学
OpenHands 文档 里有一段关键说明:
"Each runtime is a sandboxed environment where the agent can execute code, browse the web, and manipulate files without affecting the host system."
翻译:每个 runtime 都是一个沙箱环境,Agent 可以执行代码、浏览网页、操作文件,不影响宿主系统。
OpenHands 的设计哲学:Runtime 即 Sandbox。两者不分层,直接用容器作为统一边界。好处是简单清晰,坏处是粒度粗(要么全开要么全关)。新一代系统(如 E2B)在探索更细粒度的沙箱——文件级、命令级、网络级的独立控制。
Temporal 的 Durable Execution 思想
Temporal 是 Durable Execution 的标杆。它的核心思想:
"Workflow code is deterministic. External interactions are through activities."
翻译:Workflow 代码是确定性的,外部交互通过 activity 进行。
这条原则解决了 Agent 长任务的几个根本问题:
- 确定性重放:workflow 崩了重启,能从最近 checkpoint 重放,结果一致
- 外部交互隔离:所有副作用(API 调用、DB 写)都在 activity 里,可追踪可回滚
- 定时器持久化:
workflow.sleep(86400)能跨进程重启
这套思想迁移到 Agent 工程:Agent 的核心 loop 应该是确定性的(给定 messages 一定走同一路径),所有副作用都在工具调用里。
Claude Code 的 Permission 分级
Claude Code 的 Permission 系统是软沙箱的范本。它的设计:
- 默认拒绝:未知操作默认询问
- 分级放行:读类自动,写类询问,删除类必须确认
- 可配置:
settings.json里能改规则 - 可绕过(用户自己责任):
--dangerously-skip-permissions标志
这套设计的核心是把控制权交给用户。开发者自己用 Claude Code,可以接受"软沙箱 + 询问",因为开发者能判断每次询问。给多用户服务时,必须升级到容器沙箱。
Browser-use 的浏览器沙箱
Browser-use 是 LLM 友好的浏览器库。它的沙箱设计:
- 独立 profile:每个 Agent session 用独立浏览器 profile
- 域名白名单:默认只能访问白名单域名
- 下载隔离:下载文件到工作目录
- 截图审计:每步操作都截图存档
这套设计是 Browser Agent 的范本。Playwright MCP 在这基础上加了 MCP 协议层,让 Agent 调用更自然。
E2B 的"沙箱即服务"
E2B 把沙箱做成 API:
from e2b import Sandbox
sandbox = Sandbox()
sandbox.filesystem.write("/hello.py", "print('hello')")
sandbox.process.start("python /hello.py")
sandbox.close()一行代码起一个隔离的代码执行环境。这种"沙箱即服务"让 Agent 开发者不用自己管 Docker / MicroVM,专注业务逻辑。是未来 Agent infra 的重要方向。
AWS Lambda 的隔离启示
AWS Lambda 用 Firecracker MicroVM 做隔离。每个 Lambda 函数跑在一个 MicroVM 里,启动时间 125ms,隔离强度接近硬件虚拟化。
这给 Agent sandbox 一个启示:MicroVM 是"容器速度 + VM 隔离"的折中。大规模 Agent SaaS(如 Devin)正在往 MicroVM 方向迁移。
Linux Capabilities 的细粒度权限
Linux capabilities 把 root 权限拆成几十个细粒度能力。Docker 默认丢掉大部分危险 capabilities(如 CAP_SYS_ADMIN)。
Agent runtime 用容器时,可以进一步收紧:
docker run --cap-drop ALL \
--cap-add CAP_NET_BIND_SERVICE \
...把所有 capabilities 都丢掉,只加需要的。这是"最小权限原则"在容器层面的实现。
9.13 常见误区
误区 1:本地跑通就能上线。 错。本地没考虑:任务排队、崩溃恢复、成本限制、多租户隔离、审计日志。生产环境第一个崩的就是这些。
误区 2:Docker 等于安全沙箱。 不完全。Docker 默认的隔离强度不够,root 用户能逃逸。要加 --cap-drop ALL、--user 非 root、--network 受限。
误区 3:Retry 总是好的。 错。重试只对临时错误有效。永久错误重试无用,工具 bug 重试会放大伤害。要分情况。
误区 4:Checkpoint 浪费性能。 错。Checkpoint 的开销远小于"长任务崩了从头跑"的开销。任何超过 1 分钟的任务都应该有 checkpoint。
误区 5:Sandbox 越严越好。 错。过度严格的 sandbox 会让 Agent 啥也干不了。Sandbox 要根据任务调整——查论文的 Agent 不需要写文件权限,但写代码的 Agent 需要。
9.14 课后练习
- 给你正在做的 Agent 设计一个 Runtime:选哪种 Execution Environment?要不要 Queue?要不要 Cron?写出理由。
- 设计一个 Sandbox 配置:列出 Agent 能访问的文件路径、能执行的命令白名单、能访问的域名白名单。
- 你的 Agent 任务平均跑 5 分钟,崩溃率 5%。设计一套 Checkpoint + Retry 策略,让任务成功率 ≥ 99%。
- 对比 Temporal 和 LangGraph Checkpoint:什么场景该用哪个?
- 解释为什么"Agent 直接拿原始 API key"是反模式。给出两种替代方案。
9.15 小结
- Agent Runtime 解决"在哪跑、怎么跑、失败怎么恢复":Execution Environment / Shell / Filesystem / Browser / Queue / Cron / Retry / Timeout / Rollback / Checkpoint / Durable Execution。
- Agent Sandbox 解决"能不能闯祸、闯了多大祸能兜住":文件 / Shell / 网络 / 浏览器 / DB / Secret / 危险操作确认 / 日志 / 超时 / 成本 十个维度。
- Runtime 和 Sandbox 通常在同一层实现:Docker 容器既是 runtime 也是 sandbox。
- Durable Execution 是长任务 Agent 的必选项:Temporal / Restate / LangGraph Checkpoint。
- Permission 分级 是软沙箱的核心:读类放行、写类询问、删除类必须确认、灾难类禁止。
- 核心原则:最小权限 + 可审计 + 可回滚 + 可恢复。
下一章我们详细讲 MCP——怎么让 Agent 的工具连接标准化,写一次到处用。