EdgeOne Makers 从入门到精通
附录

§21 沙箱与工具框架:给 Agent 装上手脚

21.1 只会说话的 Agent 不值钱

6月前我做一个能"改代码并预览"的 Agent。光输出文本没用,它得真能跑命令、读文件、开浏览器。我一度想自己搭执行环境,看到 Makers 内置沙箱才松口气——这活它接了。

沙箱底层是腾讯云隔离实例,专门承载 Agent 的"副作用"。LLM 不再只能聊天,能真动手。

21.2 两层 API,同一个实例

平台把沙箱包成两层,都挂在 context 上:

视角 字段 给谁 粒度
LLM 视角 context.tools.* 传给 LLM 当工具 原子化,便于放开范围
开发者视角 context.sandbox.* 你直接调 按模块:commands/files/browser/runCode
标叔的结论 两层共用一实例 不用自己维护 一致才省心

context.tools 里的内置工具,底层就是调 context.sandbox.*,没有两套逻辑。

21.3 内置工具清单(节选)

工具按能力原子化,LLM 按名字语义匹配:

工具 干什么
commands 执行一次性 shell 命令
files_read / files_write 读 / 写文件
browser_fetch 真实 Chromium 取渲染后页面
browser_screenshot 截图,返回 base64
code_interpreter 跑代码
web_search 轻量网页搜索

给 LLM 全部工具很简单:

import { Agent } from "@openai/agents";
const agent = new Agent({
  name: "Assistant",
  instructions: "Use sandbox tools.",
  tools: context.tools.all(),   // 全部内置工具
  model,
});

预期结果:Agent 能自己决定调哪个工具,跑命令、读文件、开浏览器。

注意
别一股脑全放开。

只给文件 + 浏览器,不开放 shell 和代码解释器,更安全:

typescript const safeTools = [...context.tools.files(), ...context.tools.browser()];

21.4 不同框架,同一套工具

context.tools 的输出格式由 edgeone.json 里的 framework 决定。Claude / OpenAI / LangGraph / CrewAI / DeepAgents 各自适配。

{ "agents": { "framework": "claude-agent-sdk" } }

预期结果:你不用自己写工具转换,平台按框架把沙箱工具包成原生形态。我第一次对接 LangGraph 时,光工具适配就耗了两天,换成 Makers 的 toLangChainTools,一行就完事。

framework 输出形态 标叔的结论
claude-agent-sdk MCP server bundle 直接 createSdkMcpServer
openai-agents-sdk function-tool 无需 helper
langgraph LangChain 工具 toLangChainTools
crewai CrewAI 工具 toCrewAITools

21.5 开发者也能直接用沙箱

不只 LLM,你的代码也能直接操作沙箱。比如沙箱里起个 vite,把预览地址返前端:

await context.sandbox.commands.run("nohup npx vite --port 5173 &", { timeout: 10 });
const previewUrl = context.sandbox.getHost(5173);   // 暴露到外网
return Response.json({ previewUrl });

预期结果:Agent 改完代码,立刻把预览地址给用户,闭环体验。

标叔的经验
沙箱实例按 conversation_id 一对话一实例。

我第一次跑长任务没续命,沙箱到点被回收,进度全丢。后来才学会在快到期前 extendTimeout。长任务用它续命,结束用 kill() 释放。别让它空跑烧额度。

Agent 会想、会记、会动手了。但它万一乱来怎么办?下一章,把它的每一步看穿。