概览

最近更新时间:2026-06-12 21:01:31

我的收藏
Makers Agent 内置的沙箱工具底层是腾讯云的隔离实例,专门承载 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 控制,到时间点自动回收
隔离
不同对话的沙箱实例物理隔离

实例控制

方法挂载在 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 字段 。

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 调到 24 小时?
A:目前免费版沙箱实例的最长运行时长为 1 小时,如需延长实例运行时间,您可以提交 工单 进行申请。
Q:可以只放开部分工具给 LLM 吗?
A:可以,context.tools.all() 是全集;按需可用 context.tools.files() / context.tools.browser() 拿分组,或用 context.tools.get(name) 自行组装子集。