Run agent-browser + Chrome inside Vercel Sandbox microVMs for browser automation from any Vercel-deployed app. Use when the user needs browser automation in a Vercel app (Next.js, SvelteKit, Nuxt, Remix, Astro, etc.), wants to run headless Chrome without binary size limits, needs persistent browser sessions across commands, or wants ephemeral isolated browser environments. Triggers include "Vercel Sandbox browser", "microVM Chrome", "agent-browser in sandbox", "browser automation on Vercel", or
在临时 Vercel Sandbox 微虚拟机中运行 agent-browser + 无头 Chrome。Linux 虚拟机按需启动,执行浏览器命令,然后关闭。适用于任何 Vercel 部署的框架(Next.js、SvelteKit、Nuxt、Remix、Astro 等)。
bash
pnpm add @vercel/sandbox
Sandbox 虚拟机需要 Chromium 的系统依赖项以及 agent-browser 本身。使用 sandbox 快照(如下)预安装所有内容,实现亚秒级启动。
ts
import { Sandbox } from @vercel/sandbox;
// Sandbox 虚拟机上 Chromium 所需的系统库(Amazon Linux / dnf)
const CHROMIUMSYSTEMDEPS = [
nss, nspr, libxkbcommon, atk, at-spi2-atk, at-spi2-core,
libXcomposite, libXdamage, libXrandr, libXfixes, libXcursor,
libXi, libXtst, libXScrnSaver, libXext, mesa-libgbm, libdrm,
mesa-libGL, mesa-libEGL, cups-libs, alsa-lib, pango, cairo,
gtk3, dbus-libs,
];
function getSandboxCredentials() {
if (
process.env.VERCEL_TOKEN &&
process.env.VERCELTEAMID &&
process.env.VERCELPROJECTID
) {
return {
token: process.env.VERCEL_TOKEN,
teamId: process.env.VERCELTEAMID,
projectId: process.env.VERCELPROJECTID,
};
}
return {};
}
async function withBrowser
fn: (sandbox: InstanceType
): Promise
const snapshotId = process.env.AGENTBROWSERSNAPSHOT_ID;
const credentials = getSandboxCredentials();
const sandbox = snapshotId
? await Sandbox.create({
...credentials,
source: { type: snapshot, snapshotId },
timeout: 120_000,
})
: await Sandbox.create({ ...credentials, runtime: node24, timeout: 120_000 });
if (!snapshotId) {
await sandbox.runCommand(sh, [
-c,
sudo dnf clean all 2>&1 && sudo dnf install -y --skip-broken ${CHROMIUMSYSTEMDEPS.join( )} 2>&1 && sudo ldconfig 2>&1,
]);
await sandbox.runCommand(npm, [install, -g, agent-browser]);
await sandbox.runCommand(npx, [agent-browser, install]);
}
try {
return await fn(sandbox);
} finally {
await sandbox.stop();
}
}
screenshot --json 命令将截图保存到文件并返回路径。将文件读取为 base64:
ts
export async function screenshotUrl(url: string) {
return withBrowser(async (sandbox) => {
await sandbox.runCommand(agent-browser, [open, url]);
const titleResult = await sandbox.runCommand(agent-browser, [
get, title, --json,
]);
const title = JSON.parse(await titleResult.stdout())?.data?.title || url;
const ssResult = await sandbox.runCommand(agent-browser, [
screenshot, --json,
]);
const ssPath = JSON.parse(await ssResult.stdout())?.data?.path;
const b64Result = await sandbox.runCommand(base64, [-w, 0, ssPath]);
const screenshot = (await b64Result.stdout()).trim();
await sandbox.runCommand(agent-browser, [close]);
return { title, screenshot };
});
}
ts
export async function snapshotUrl(url: string) {
return withBrowser(async (sandbox) => {
await sandbox.runCommand(agent-browser, [open, url]);
const titleResult = await sandbox.runCommand(agent-browser, [
get, title, --json,
]);
const title = JSON.parse(await titleResult.stdout())?.data?.title || url;
const snapResult = await sandbox.runCommand(agent-browser, [
snapshot, -i, -c,
]);
const snapshot = await snapResult.stdout();
await sandbox.runCommand(agent-browser, [close]);
return { title, snapshot };
});
}
Sandbox 在命令之间保持持久化,因此您可以运行完整的自动化序列:
ts
export async function fillAndSubmitForm(url: string, data: Record
return withBrowser(async (sandbox) => {
await sandbox.runCommand(agent-browser, [open, url]);
const snapResult = await sandbox.runCommand(agent-browser, [
snapshot, -i,
]);
const snapshot = await snapResult.stdout();
// 解析快照以查找元素引用...
for (const [ref, value] of Object.entries(data)) {
await sandbox.runCommand(agent-browser, [fill, ref, value]);
}
await sandbox.runCommand(agent-browser, [click, @e5]);
await sandbox.runCommand(agent-browser, [wait, --load, networkidle]);
const ssResult = await sandbox.runCommand(agent-browser, [
screenshot, --json,
]);
const ssPath = JSON.parse(await ssResult.stdout())?.data?.path;
const b64Result = await sandbox.runCommand(base64, [-w, 0, ssPath]);
const screenshot = (await b64Result.stdout()).trim();
await sandbox.runCommand(agent-browser, [close]);
return { screenshot };
});
}
Sandbox 快照是已安装系统依赖项 + agent-browser + Chromium 的 Vercel Sandbox 的保存虚拟机镜像。可以将其视为 Docker 镜像——无需每次都从头安装依赖项,sandbox 从预构建的镜像启动。
这与 agent-browser 的无障碍快照功能(agent-browser snapshot)无关,后者会转储页面的无障碍树。Sandbox 快照是 Vercel 基础设施概念,用于快速虚拟机启动。
没有 sandbox 快照时,每次运行都需要安装系统依赖项 + agent-browser + Chromium(约 30 秒)。使用快照后,启动时间可缩短至亚秒级。
快照必须包含系统依赖项(通过 dnf)、agent-browser 和 Chromium:
ts
import { Sandbox } from @vercel/sandbox;
const CHROMIUMSYSTEMDEPS = [
nss, nspr, libxkbcommon, atk, at-spi2-atk, at-spi2-core,
libXcomposite, libXdamage, libXrandr, libXfixes, libXcursor,
libXi, libXtst, libXScrnSaver, libXext, mesa-libgbm, libdrm,
mesa-libGL, mesa-libEGL, cups-libs, alsa-lib, pango, cairo,
gtk3, dbus-libs,
];
async function createSnapshot(): Promise
const sandbox = await Sandbox.create({
runtime: node24,
timeout: 300_000,
});
await sandbox.runCommand(sh, [
-c,
sudo dnf clean all 2>&1 && sudo dnf install -y --skip-broken ${CHROMIUMSYSTEMDEPS.join( )} 2>&1 && sudo ldconfig 2>&1,
]);
await sandbox.runCommand(npm, [install, -g, agent-browser]);
await sandbox.runCommand(npx, [agent-browser, install]);
const snapshot = await sandbox.snapshot();
return snapshot.snapshotId;
}
运行一次,然后设置环境变量:
bash
AGENTBROWSERSNAPSHOTID=snapxxxxxxxxxxxx
演示应用中提供了辅助脚本:
bash
npx tsx examples/environments/scripts/create-snapshot.ts
建议用于任何使用 Sandbox 模式的生产部署。
在 Vercel 部署中,Sandbox SDK 通过 OIDC 自动进行身份验证。对于本地开发或显
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 vercel-sandbox-1775901308 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 vercel-sandbox-1775901308 技能
skillhub install vercel-sandbox-1775901308
文件大小: 3.67 KB | 发布时间: 2026-4-12 11:49