¿Qué hace Automatización de Navegador con Vercel Sandbox?
Ejecuta agent-browser + Chrome headless dentro de microVMs efímeras de Vercel Sandbox. Una VM Linux se inicia bajo demanda, ejecuta comandos del navegador y se apaga. Funciona con cualquier framework desplegado en Vercel (Next.js, SvelteKit, Nuxt, Remix, Astro, etc.).
Dependencias
pnpm add @agent-browser/sandbox @vercel/sandbox
La VM del sandbox necesita dependencias del sistema para Chromium además del propio agent-browser. Los helpers de @agent-browser/sandbox las instalan por defecto para sandboxes nuevos y usan snapshots de sandbox (abajo) para un inicio en menos de un segundo. Pasa installSystemDependencies: false solo cuando la imagen del sandbox ya proporcione las bibliotecas necesarias de Chromium.
Patrón Principal
import {
createAgentBrowserSnapshot,
runAgentBrowserCommand,
withAgentBrowserSandbox,
type VercelSandboxSession,
} from "@agent-browser/sandbox/vercel";
async function withBrowser<T>(
fn: (sandbox: VercelSandboxSession) => Promise<T>,
): Promise<T> {
return withAgentBrowserSandbox(fn);
}
Captura de Pantalla
El comando screenshot --json guarda en un archivo y devuelve la ruta. Lee el archivo de vuelta como base64:
export async function screenshotUrl(url: string) {
return withBrowser(async (sandbox) => {
await runAgentBrowserCommand(sandbox, ["open", url]);
const titleResult = await runAgentBrowserCommand<{ data?: { title?: string } }>(sandbox, [
"get", "title",
]);
const title = titleResult.json?.data?.title || url;
const ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [
"screenshot",
]);
const ssPath = ssResult.json?.data?.path;
if (!ssPath) throw new Error("La captura de pantalla no devolvió una ruta de archivo.");
const b64Result = await sandbox.runCommand("base64", ["-w", "0", ssPath]);
const screenshot = (await b64Result.stdout()).trim();
await runAgentBrowserCommand(sandbox, ["close"], { json: false });
return { title, screenshot };
});
}
Instantánea de Accesibilidad
export async function snapshotUrl(url: string) {
return withBrowser(async (sandbox) => {
await runAgentBrowserCommand(sandbox, ["open", url]);
const titleResult = await runAgentBrowserCommand<{ data?: { title?: string } }>(sandbox, [
"get", "title",
]);
const title = titleResult.json?.data?.title || url;
const snapResult = await runAgentBrowserCommand(sandbox, ["snapshot", "-i", "-c"], {
json: false,
});
await runAgentBrowserCommand(sandbox, ["close"], { json: false });
return { title, snapshot: snapResult.stdout };
});
}
Flujos de Trabajo Multipaso
El sandbox persiste entre comandos, por lo que puedes ejecutar secuencias completas de automatización:
export async function fillAndSubmitForm(
url: string,
data: Record<string, string>,
postSubmitWaitArgs: string[],
) {
return withBrowser(async (sandbox) => {
await runAgentBrowserCommand(sandbox, ["open", url]);
const snapResult = await runAgentBrowserCommand(sandbox, ["snapshot", "-i"], {
json: false,
});
const snapshot = snapResult.stdout;
// Analizar snapshot para encontrar referencias a elementos...
for (const [ref, value] of Object.entries(data)) {
await runAgentBrowserCommand(sandbox, ["fill", ref, value]);
}
await runAgentBrowserCommand(sandbox, ["click", "@e5"]);
// Pasa una espera específica de la aplicación, como ["--url", "**/checkout/complete"],
// ["--text", "Gracias"], o ["#confirmation"].
await runAgentBrowserCommand(sandbox, ["wait", ...postSubmitWaitArgs]);
const ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [
"screenshot",
]);
const ssPath = ssResult.json?.data?.path;
if (!ssPath) throw new Error("La captura de pantalla no devolvió una ruta de archivo.");
const b64Result = await sandbox.runCommand("base64", ["-w", "0", ssPath]);
const screenshot = (await b64Result.stdout()).trim();
await runAgentBrowserCommand(sandbox, ["close"], { json: false });
return { screenshot };
});
}
Snapshots de Sandbox (Inicio Rápido)
Un snapshot de sandbox es una imagen de VM guardada de un Vercel Sandbox con las dependencias del sistema + agent-browser + Chromium ya instalados. Piénsalo como una imagen de Docker: en lugar de instalar dependencias desde cero cada vez, el sandbox arranca desde la imagen preconstruida.
Esto no está relacionado con la funcionalidad de instantánea de accesibilidad de agent-browser (agent-browser snapshot), que vuelca el árbol de accesibilidad de una página. Un snapshot de sandbox es un concepto de infraestructura de Vercel para un inicio rápido de la VM.
Sin un snapshot de sandbox, cada ejecución instala dependencias del sistema + agent-browser + Chromium (~30 s). Con uno, el inicio es de menos de un segundo.
Creación de un snapshot de sandbox
El snapshot debe incluir las dependencias del sistema (a través de dnf), agent-browser y Chromium:
const snapshotId = await createAgentBrowserSnapshot();
Ejecútalo una vez, luego configura la variable de entorno:
AGENT_BROWSER_SNAPSHOT_ID=snap_xxxxxxxxxxxx
Hay un script auxiliar disponible en la aplicación de ejemplo:
npx tsx examples/environments/scripts/create-snapshot.ts
Recomendado para cualquier despliegue en producción que utilice el patrón Sandbox.
Autenticación
En despliegues de Vercel, el SDK de Sandbox se autentica automáticamente mediante OIDC. Para desarrollo local o control explícito, configura:
VERCEL_TOKEN=<token-de-acceso-personal>
VERCEL_TEAM_ID=<id-del-equipo>
VERCEL_PROJECT_ID=<id-del-proyecto>
Estos se distribuyen en las llamadas a Sandbox.create(). Cuando están ausentes, el SDK recurre a VERCEL_OIDC_TOKEN (automático en Vercel).
Flujos de Trabajo Programados (Cron)
Combínalo con Cron Jobs de Vercel para tareas recurrentes del navegador:
// app/api/cron/route.ts (o su equivalente en tu framework)
export async function GET() {
const result = await withBrowser(async (sandbox) => {
await sandbox.runCommand("agent-browser", ["open", "https://example.com/pricing"]);
const snap = await sandbox.runCommand("agent-browser", ["snapshot", "-i", "-c"]);
await sandbox.runCommand("agent-browser", ["close"]);
return await snap.stdout();
});
// Procesar resultados, enviar alertas, almacenar datos...
return Response.json({ ok: true, snapshot: result });
}
// vercel.json
{ "crons": [{ "path": "/api/cron", "schedule": "0 9 * * *" }] }
Variables de Entorno
| Variable | Requerida | Descripción |
|---|---|---|
AGENT_BROWSER_SNAPSHOT_ID | No (pero recomendada) | ID del snapshot de sandbox preconstruido para inicio ultrarrápido (ver arriba) |
VERCEL_TOKEN | No | Token de acceso personal de Vercel (para desarrollo local; OIDC es automático en Vercel) |
VERCEL_TEAM_ID | No | ID del equipo de Vercel (para desarrollo local) |
VERCEL_PROJECT_ID | No | ID del proyecto de Vercel (para desarrollo local) |
Ejemplos por Framework
El patrón funciona de manera idéntica en todos los frameworks. La única diferencia es dónde colocas el código del lado del servidor:
| Framework | Ubicación del código del servidor |
|---|---|
| Next.js | Server actions, rutas API, route handlers |
| SvelteKit | +page.server.ts, +server.ts |
| Nuxt | server/api/, server/routes/ |
| Remix | Funciones loader, action |
| Astro | Frontmatter de .astro, rutas API |
Ejemplo
Consulta examples/environments/ en el repositorio de agent-browser para ver una aplicación funcional con el patrón de Vercel Sandbox, que incluye un script de creación de snapshots de sandbox, interfaz de progreso en streaming y límite de tasa.