概览
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、.git、dist、build、out、coverage、.cache、.turbo、.vite、.parcel-cache、__pycache__、.venv、venv 和 .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() | 获取当前沙箱信息( instanceId、expiresAt 等) |
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、过期时间等。
返回值
SandboxInfointerface SandboxInfo {instanceId: stringsandboxToken: stringsandboxDomain?: stringenvdVersion?: stringexpiresAt: string // ISO 时间字符串,由后端 acquire/update 返回}
@dataclassclass SandboxInfo:instance_id: strsandbox_token: strexpires_at: strsandbox_domain: Optional[str] = Noneenvd_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: stringexpiresAt: 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 字段 |
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 小时?
Q:可以只放开部分工具给 LLM 吗?
A:可以,
context.tools.all() 是全集;按需可用 context.tools.files() / context.tools.browser() 拿分组,或用 context.tools.get(name) 自行组装子集。