EdgeOne Makers 从入门到精通
附录

§25 沙箱原子 API:自己动手封装工具

25.1 平台给的工具不够用时

3周前我接了个活:要让 Agent 批量把 200 个 CSV 跑成图表,还要登录某后台截图存证。平台内置工具够日常用,但这活儿要自己控制进程、读写文件、操作浏览器、跨调用保留变量——光靠高级封装不够。这时候就得直接用 context.sandbox.* 这套原子 API。

sandbox 是开发者直接调用的视角,你基于它自己封装工具,想怎么玩怎么玩。

25.2 commands:每次都是干净的新进程

我第一次用 commands.run 时踩了个坑:我以为连续两次调用能共享环境变量,结果第二次拿不到。后来才看懂文档——每次调用都是独立新进程,不保留 cwd、不保留环境变量改动。要跨调用保留状态,得用后面的 runCode

const { stdout, exitCode } = await context.sandbox.commands.run(
  'pip install requests && python -c "import requests; print(requests.__version__)"',
  { timeout: 60 },
);

opts 支持 cwd / env / user / timeout(秒),返回 { stdout, stderr, exitCode }。一句话跑完即焚,干净。

25.3 files:读写沙箱文件系统

我在做数据预处理时,全靠 files 在沙箱里落盘。文本直接读写,二进制资产(比如 .png)建议先用 commands 在沙箱内下载或解码,再走别的通道读出。

await context.sandbox.files.makeDir('/work/output');
await context.sandbox.files.write('/work/output/result.json', JSON.stringify(data));
const entries = await context.sandbox.files.list('/work/output');

可用方法:read / write / list / makeDir(或 make_dir) / exists / remove,覆盖日常文件系统操作。

25.4 browser:CDP 连内置 Chromium

我做过一个需要"登录后截图"的需求,内置的 browser_screenshot 工具做不到——它没法保持登录态。原子 API 里的 browser 走 CDP 连沙箱内置 Chromium(底层 Playwright),能跑多步有状态流程。

await context.sandbox.browser.goto('https://example.com/login');
await context.sandbox.browser.type('input[name=user]', 'alice');
await context.sandbox.browser.type('input[name=pass]', 'secret');
await context.sandbox.browser.click('button[type=submit]');
await context.sandbox.browser.goto('https://example.com/dashboard');
const { base64Image } = await context.sandbox.browser.screenshot({ fullPage: true });

browser 还暴露 cdpUrl(外部 Playwright 直连)和 liveUrl(NoVNC 人工实时看页面),方法含 goto / click / type / evaluate / getContent / close。这是比"截个图"高级得多的浏览器控制力。

25.5 runCode:变量跨调用保留的 Jupyter kernel

我做数据批处理时最依赖 runCode——它在沙箱内置 Jupyter kernel 里执行代码,变量跨调用保留。这是它和 commands 最大的区别。

exec = await context.sandbox.run_code(
    """
import pandas as pd
df = pd.read_csv('/work/data.csv')
df.plot().get_figure().savefig('/work/out.png')
print('done')
""",
    language='python',
)

opts 支持 language(默认 python,也支持 javascript / r / bash)和 timeout(秒),返回 Execution { results, logs, error }

25.6 标叔的结论

我的经验:commands 干一次性的脏活,files 管落盘,browser 做有状态的网页操作,runCode 跑要保状态的数据任务。四件套一上手,你基本能给 Agent 封出任何工具,不再受平台内置清单的限制。

接下来,翻到 §26,我看怎么给 Agent 接上"联网搜索"这种即插即用的工具。