• 产品简介
  • 快速开始
    • Agent 开发
    • 导入 Git 仓库
    • 从模板开始
    • 直接上传
    • 从 AI 开始
  • 框架指南
    • Agent
    • 前端
      • Vite
      • React
      • Vue
      • Hugo
      • 其他框架
    • 后端
    • 全栈
      • Next.js
      • Nuxt
      • Astro
      • React Router
      • SvelteKit
      • TanStack Start
      • Vike
    • 自定义 404 页面
  • 项目指南
    • 项目管理
    • edgeone.json
    • 缓存配置
    • 构建输出配置
    • 错误码
  • 构建指南
  • 部署指南
    • 概览
    • 触发部署
    • 管理部署
    • 部署按钮
    • 使用 Github Action
    • 使用 Gitlab CI/CD
    • 使用 CNB 插件
    • 使用 IDE 插件
    • 使用 CodeBuddy IDE
  • 域名管理
    • 概览
    • 自定义域名
    • 配置 HTTPS 证书
      • 概览
      • 申请免费证书
      • 使用 SSL 托管证书
    • 配置 DNS 的 CNAME 记录
  • 企业解决方案
    • Vibe Coding
    • 平台与多租户
    • 内部应用
  • 可观测性
    • 概览
    • 指标分析
    • 日志分析
  • Functions
    • 概览
    • Edge Functions
    • Cloud Functions
      • 概览
      • Node.js
      • Python
      • Go
  • Agents
    • 概览
    • 快速开始
    • 会话管理
    • 可观测
    • 沙箱工具
      • 概览
      • Agent 框架使用
      • 沙箱原子 API
      • 网络搜索工具
    • Agent 鉴权
  • Models
    • 概览
    • 模型与厂商
      • 概览
      • 使用厂商密钥
        • OpenAI
        • Anthropic
        • Google AI Studio
        • DeepSeek
        • MiniMax
        • 混元
        • 智谱
        • 月之暗面
    • 常见问题
  • 存储
    • 概览
    • KV
    • Blob
  • 中间件
  • AI 原生开发
    • Skills
    • MCP
  • Copilot
    • 概览
    • 快速开始
  • API Token
  • EdgeOne CLI
  • 消息通知
  • 集成指南
    • AI
      • 对话型大模型集成
      • 图片大模型集成
    • 数据库
      • Supabase 集成
      • Pages KV 集成
    • 电商
      • Shopify 集成
      • WooCommerce 集成
    • 支付
      • Stripe 集成
      • Paddle 集成
    • CMS
      • WordPress 集成
      • Contentful 集成
      • Sanity 集成
      • Payload 集成
    • 身份验证
      • Supabase 集成
      • Clerk 集成
  • 最佳实践
    • 为网站添加 AI 对话助手
    • AI 对话式部署:使用 Skill 一句话部署项目
    • 使用通用大模型快速搭建 AI 应用
    • 使用 Shopify 搭建电商平台
    • 使用 Supabase 和 Stripe 搭建 SaaS 站点
    • 如何快速搭建公司品牌站点
    • 如何快速搭建博客站点
  • 迁移指南
    • 从 Vercel 迁移至 EdgeOne Makers
    • 从 Cloudflare Pages 迁移至 EdgeOne Makers
    • 从 Netlify 迁移至 EdgeOne Makers
  • 排障指南
  • 常见问题
  • 限制与配额
  • 价格与套餐
  • 联系我们
  • 产品动态

概览

Makers Agents 内置的沙箱工具底层是腾讯云的隔离实例,专门承载 Agent 执行过程中的"副作用"——跑命令、读写文件、操控浏览器、运行代码,让 LLM 真正具备"动手"能力,而不是只能输出文本。

两层 API

平台把同一个沙箱实例分别包装成两层 API 暴露在 context 上:一层给 LLM 当工具调用,一层给开发者直接使用。
视角
字段
给谁用
粒度
LLM 视角
context.tools.*
传给 LLM 的工具清单(按 framework 包装为原生对象)
扁平化为原子工具,便于按需放开调用范围
开发者视角
context.sandbox.*
开发者代码中直接调用的沙箱原子 API
按模块组织:commands / files / browser /runCode 顶层方法
两层 API 底层共用同一个沙箱实例——context.tools 中需要沙箱能力的内置工具,其内部实现就是直接调用 context.sandbox.*,不存在两套独立逻辑。

实例生命周期

维度
说明
实例归属
一对话一实例,按 conversation_id 维度托管
创建时机
懒加载——首次访问沙箱工具时由适配层调用
跨请求复用
如果沙箱实例未被销毁,同 conversation_id 的沙箱工具请求落到同一实例
生命周期上限
edgeone.json sandbox.timeout 控制,到时间点自动回收
隔离
不同对话的沙箱实例物理隔离

项目持久化与恢复

沙箱实例是临时运行资源。当实例到期、被回收或调用 kill() 后,未持久化的沙箱文件和运行时状态不保证可以恢复。
如果应用需要在后续请求、页面刷新或沙箱实例重新创建后继续使用项目,请在开发者代码中显式调用以下 API:
context.sandbox.persist({ path }):将指定路径下的项目内容保存为当前项目的持久化检查点。
context.sandbox.restore({ path }):尝试将已持久化的项目内容恢复到指定路径。
持久化数据写入当前项目保留的 __sandbox Blob 存储,归档字节不会经过对话消息或对话元数据。持久化源码会计入当前项目的 Blob 存储空间和配额,应用不需要直接访问或管理 __sandbox 存储。

persist(options)

将指定项目目录下的内容保存为当前项目的持久化检查点。归档大小上限为 25 MiB;默认排除依赖、构建输出、版本控制和缓存目录,也可以通过 exclude 增加需要排除的目录名。

参数

参数
类型
必填
说明
path
string
需要持久化的非根项目目录。
exclude
string[]
额外排除的目录名。默认已排除 node_modules.next.gitdistbuildoutcoverage.cache.turbo.vite.parcel-cache__pycache__.venvvenv.edgeone
timeout
number
整个持久化操作的超时时间,单位为秒,默认 180 秒。必须是正整数。
返回结果:
{
size: number;
sha256: string;
etag: string;
persistedAt: string;
}

restore(options)

尝试将已持久化的项目内容恢复到指定的非根项目目录。恢复前会下载并校验归档;恢复成功后,目标目录会被替换为检查点中的项目内容。

参数

参数
类型
必填
说明
path
string
用于恢复项目内容的非根目标目录。
timeout
number
整个恢复操作的超时时间,单位为秒,默认 180 秒。必须是正整数。
没有可用检查点时返回:
{
restored: false;
reason: 'not_found';
}
恢复成功时返回:
{
restored: true;
size: number;
sha256: string;
etag: string;
persistedAt: string;
}

TypeScript 示例

const projectPath = 'projects/<conversation_id>/app';

// 初始化工作区时先尝试恢复已有检查点
const restored = await context.sandbox.restore({
path: projectPath,
timeout: 180,
});

if (!restored.restored) {
// 没有可用检查点时,初始化新的项目工作区
await context.sandbox.files.makeDir(projectPath);
// 初始化项目文件
}

// 项目文件完成修改后保存最新检查点
const persisted = await context.sandbox.persist({
path: projectPath,
timeout: 180,
});
console.log(persisted.size, persisted.persistedAt);
Node SDK 使用对象参数;Python SDK 使用关键字参数,例如:
await sandbox.persist(
path='/home/user/project',
exclude=['tmp'],
timeout=180,
)
restored = await sandbox.restore(
path='/home/user/project',
timeout=180,
)
建议在项目工作区初始化时调用 restore(),并在完成重要文件修改、任务停止或即将释放沙箱实例前等待 persist() 完成。
persist()restore() 只处理指定目录下的项目内容。运行中的进程、浏览器状态、临时环境状态以及预览地址不保证会被持久化。恢复项目后,如需提供预览,应重新启动服务并获取新的预览地址。归档内容不经过 Agent Runtime 内存,存储和请求流量计入当前项目的 Blob 配额。

实例控制

方法挂载在 context.sandbox 顶层,用于管理沙箱实例本身的生命周期与对外暴露。
方法
用途
getHost(port)
获取沙箱实例的外部访问地址
envdAccessToken
获取数据面访问 token
getInfo()
获取当前沙箱信息(instanceIdexpiresAt 等)
extendTimeout(seconds)
延长当前沙箱实例寿命;返回 { instanceId, expiresAt, message? }
kill()
销毁沙箱实例

getHost(port) / get_host(port)

获取沙箱实例某个端口的外部可访问地址,用于把沙箱内启动的 server 暴露给浏览器或外部调用方。
参数
Parameter
Type
Required
Description
port
number / int
Yes
沙箱内监听的端口号
返回值
形如 https://<port>-<instance>.sandbox.example.com 的外部地址。
TS 示例:
// 沙箱里跑个 vite dev server,再把它的访问地址返给前端
await context.sandbox.commands.run('nohup npx vite --port 5173 &', { timeout: 10 })
const previewUrl = context.sandbox.getHost(5173)
return Response.json({ previewUrl })
Python 示例:
await ctx.sandbox.commands.run('nohup python -m http.server 8000 &', timeout=10)
preview_url = ctx.sandbox.get_host(8000)
return {'preview_url': preview_url}

envdAccessToken / envd_access_token

获取沙箱实例数据面的访问 token
返回值
envd token
TS 示例:
const token = context.sandbox.envdAccessToken
Python 示例:
token = ctx.sandbox.envd_access_token

getInfo() / get_info()

获取当前会话缓存的沙箱元信息,沙箱实例 ID、过期时间等。
返回值
SandboxInfo
interface SandboxInfo {
instanceId: string
sandboxToken: string
sandboxDomain?: string
envdVersion?: string
expiresAt: string // ISO 时间字符串,由后端 acquire/update 返回
}
@dataclass
class SandboxInfo:
instance_id: str
sandbox_token: str
expires_at: str
sandbox_domain: Optional[str] = None
envd_version: Optional[str] = None
TS 示例:
const info = context.sandbox.getInfo()
console.log(info.instanceId, info.expiresAt)
const remainingMs = new Date(info.expiresAt).getTime() - Date.now()
if (remainingMs < 60_000) {
await context.sandbox.extendTimeout(600)
}
Python 示例:
info = ctx.sandbox.get_info()
print(info.instance_id, info.expires_at)

extendTimeout(seconds) / extend_timeout(seconds)

为当前沙箱实例发起续期请求,真实生效的时长以后端返回为准。如果你要求的秒数超出后端允许的剩余可续期窗口,后端会截断并告诉你实际只续到什么时候,SDK 会用返回的 expiresAt / expires_at 同步更新本地缓存。
参数
Parameter
Type
Required
Description
seconds
number / int
Yes
续期秒数,必须是正整数
返回值
UpdateResponse
interface UpdateResponse {
instanceId: string
expiresAt: string // 后端确认后的真实新过期时间
message?: string // 仅当被后端截断续期时返回,例如 "extended to max lifetime"
}
Python:dict,字段为 instance_id / expires_at / message?(snake_case)。
TS 示例
await context.sandbox.commands.run('echo init', { timeout: 300 })
const renewed = await context.sandbox.extendTimeout(600)
console.log('new expiresAt:', renewed.expiresAt)
Python 示例
await ctx.sandbox.commands.run('echo init', timeout=300)
renewed = await ctx.sandbox.extend_timeout(600)
print('new expires_at:', renewed['expires_at'])

kill()

主动销毁当前沙箱实例。
context.sandbox.kill()
何时应该调 kill 一次性脚本结束、或确认整个对话结束希望立刻把沙箱实例配额释放出来。

错误码说明

错误码
说明
SANDBOX_LIMIT_EXCEEDED
并发实例数 / 总内存时长配额 / 单实例最大运行时长超限
SANDBOX_INVALID_PARAMETER
参数校验失败,如缺少 conversation_id、授权 Token 等
SANDBOX_AUTHORIZATION_EXPIRED
授权 Token 无效/过期
SANDBOX_FAILED_OPERATION
沙箱服务操作失败(限频/超时等)
SANDBOX_NETWORK_ERROR
沙箱服务网络异常
SANDBOX_INSTANCE_UNAVAILABLE
沙箱实例不存在或已过期
SANDBOX_NETWORK_ERROR
数据面运行时客户端依赖缺失或创建失败
SANDBOX_UNKNOWN_ERROR
兜底错误码,错误详情可查看 message 字段
遇到以上问题,无法解决时,可以加入我们在 Discord 上的服务器 EdgeOne 寻求技术支持.

FAQ

Q:browser_screenshot 返回什么?base64 还是 URL?
A:返回 { base64Image }(PNG base64),不返回 URL,也不在沙箱内保存文件。如需展示给前端 / 持久化,自己落对象存储换 URL 即可。
Q:browser_fetch 和直接 HTTP 请求有什么区别?
A:browser_fetch 用真实 Chromium 导航(CDP + Playwright),能拿到 JS 渲染后的页面元信息和 HTML;普通 HTTP fetch 只能拿到原始响应。需要轻量抓接口的场景可在 commands 里用 curl
Q:能不能把沙箱实例的 timeout 调到 10 小时?
A:目前免费版沙箱实例的最长运行时长为 1 小时,如需延长实例运行时间,您可以提交 工单 进行申请。
Q:可以只放开部分工具给 LLM 吗?
A:可以,context.tools.all() 是全集;按需可用 context.tools.files() / context.tools.browser() 拿分组,或用 context.tools.get(name) 自行组装子集。