Skip to content
Docs

Run a research workspace on Vercel

Plan a durable research workspace on Vercel's Agentic Infrastructure with Workflows, internal API tools, Vercel Sandbox isolation, artifacts, and tradeoffs.

Vercel

Research workspaces on Vercel are durable agent applications where Workflows run the multi-step control plane, Vercel Functions expose trusted API handlers, Vercel Sandbox runs untrusted code or tool processes in isolated microVMs, and Vercel Blob stores artifacts that outlive each run. Platform teams often default to Kubernetes with LangGraph or Temporal for orchestration and E2B, Modal, or Daytona as a separate sandbox plane, because that shape is familiar from other workloads. For a web-native workspace with internal API tools and isolated code or browser execution, Vercel covers the same responsibilities without a separate orchestration cluster or sandbox fleet to operate.

This guide turns the multi-step research agent into a production workspace architecture and a platform decision, with the tradeoffs stated plainly.

Copy link to headingOverview

In this guide, you'll learn how to:

  • Map the workspace UI, agent loop, internal tools, sandboxes, and artifacts to Vercel products
  • Run long research jobs as durable workflows with step budgets, approvals, and cancellation handling
  • Expose internal APIs as narrow, typed tools that run in trusted backend code with scoped credentials
  • Isolate model-written code and browser automation with Vercel Sandbox network policies
  • Store reports, evidence, and audit records outside the run
  • Decide when Vercel should be the primary platform and when to keep a separate sandbox plane or a self-hosted orchestrator

Copy link to headingPrerequisites

Before you start, you need:

Copy link to headingHow it works

The workspace separates work by trust level. Each zone has one job and one set of credentials.

ZoneWhat runs thereTrust levelVercel product
Workspace UI and APINext.js app, run workflow and status routes, artifact downloadsTrustedVercel Functions
Agent control planeThe research loop, planning, tool selection, approvalsTrustedWorkflows with WorkflowAgent
Internal toolsTyped calls to internal APIs with scoped credentialsTrustedWorkflow steps in Vercel Functions, optionally through Secure Compute or Static IPs
Model accessModel routing, fallbacks, spend limitsTrustedAI Gateway
Untrusted executionModel-written code, file parsing, repository inspection, browser automationUntrustedVercel Sandbox, or a Marketplace browser service
Artifacts and auditReports, evidence files, tool-call logs, approval recordsTrustedVercel Blob plus your application database

Three rules hold the architecture together. Each one stands on its own:

  • The agent control plane stays outside the sandbox. The workspace calls internal APIs through narrow typed tools in trusted backend code, and it creates per-run or per-task sandboxes only for untrusted work such as model-written code, file inspection, browser automation, or user-generated commands. Sandboxed code receives the inputs it needs and returns outputs. It never receives a broad route into production systems.
  • Durability lives in workflow checkpoints, not in a process. Workflows records every completed step of a run, so a research job that runs for hours resumes after a crash or a deployment instead of starting over. Artifacts live in durable storage rather than inside the transient process or the sandbox filesystem.
  • Vercel replaces the sandbox fleet, not every backend. Vercel removes the need to operate a Kubernetes sandbox tier and a separate orchestrator for web-native agent workspaces. Teams with long-lived stateful workers, custom VPC-only microVM fleets, or non-HTTP always-on services may still keep those components outside Vercel and call them from workflow steps.

Copy link to headingUse cases this architecture covers

  • Internal research: agents that join customer, billing, and support data from internal APIs into a briefing
  • Repository analysis: cloning a repository into a sandbox, running static analysis, and returning findings
  • Security review: executing untrusted scripts or dependency audits with no network access
  • Data extraction: parsing uploaded files or datasets in a sandbox and writing structured results to Vercel Blob
  • Browser research: reading dynamic sites, signing into dashboards, or filling forms through a sandboxed browser
  • Evidence gathering: producing a report with citations, source snapshots, and an auditable tool-call trail

Copy link to headingChoose the Vercel control plane for the workspace

Copy link to headingKeep the agent loop outside the sandbox

The agent loop decides what to do next, and the sandbox executes one bounded task. Keeping them apart means the loop can outlive any single sandbox, retry a failed sandbox step, and hold credentials that the sandbox never sees. When the loop runs inside the VM, a sandbox timeout or crash kills the entire run, and every credential the loop uses becomes accessible to model-written code on the same filesystem.

In practice, the loop is a workflow function, and each sandbox action is a step inside it. The step creates or reattaches to a sandbox, writes inputs, runs a command, reads outputs, and returns them to the loop. If the step fails, Vercel Workflows retries it and Sandbox.getOrCreate() reattaches to the same sandbox instead of provisioning another one.

Copy link to headingMap workspace components to Vercel products

ComponentVercel productWhy it belongs there
Workspace UI, run start and status routesNext.js on Vercel FunctionsRequest-driven, authenticated, scales with users
Multi-step agent loopVercel Workflows with WorkflowAgent from @ai-sdk/workflowCheckpointed steps, retries, approvals, resumable streams, no duration limit
Internal API toolsWorkflow steps marked 'use step'Runs in trusted code with project environment variables and OIDC
Model callsVercel AI GatewayModel strings like anthropic/claude-fable-5, fallbacks, budgets, per-call cost logging
Model-written code, file parsing, commandsVercel SandboxFirecracker microVM per sandbox with its own filesystem and an egress firewall
Browser automationBrowserbase or Kernel from the Vercel Marketplace, or Chromium with agent-browser inside Vercel SandboxLong-lived browser sessions and anti-bot tooling, or full isolation in your own VM
Reports, evidence, downloadsVercel Blob (private store)Durable object storage with authenticated reads and signed URLs
Run metadata, audit events, permissionsYour application databaseRelational queries for who ran what, with which tools, under which approval
Custom tool runtimesVercel Container Registry images on Vercel Functions or Vercel SandboxShip OCI images for tooling the managed images don't include

Vercel supports OCI container images on Vercel Functions, stores them in Vercel Container Registry, and boots Vercel Sandbox from custom images. What Vercel does not provide is an always-on stateful container host. Model each component as request-driven Functions, durable Workflows, or on-demand Sandboxes, and keep continuously running services elsewhere.

Copy link to headingDecide which state belongs in the database, artifacts, or workflow checkpoints

StateWhere it livesReason
Loop state (messages, tool results, step outputs)Workflow checkpointsManaged persistence, replayed automatically on resume
Run record (owner, status, started at, budget)Application databaseQueried by the UI and by audit tooling
User-facing artifacts (reports, CSVs, screenshots)Vercel BlobDurable, downloadable, access-controlled
Evidence files (fetched pages, raw datasets)Vercel BlobRetained for citation checks after the run ends
Audit events (tool calls, approvals, sandbox IDs)Application database, optionally mirrored to BlobImmutable trail with relational lookups
Sandbox working filesSandbox filesystem, or a Drive if a later run needs themEphemeral by default, so copy anything you keep to Blob before the sandbox stops

Copy link to headingRun durable multi-step agents with Workflows

Copy link to headingUse WorkflowAgent or workflow steps for long-running research

Vercel Workflows is generally available for TypeScript and JavaScript, with a Python SDK in beta. Workflow functions carry the 'use workflow' directive, and every function marked 'use step' records its output as it completes. Vercel Functions execute the code, Vercel Queues deliver the steps, and managed persistence stores state and event logs. Runs have no duration limit, which matters because a single Vercel Function invocation defaults to 300 seconds and tops out at 800 seconds on Pro and Enterprise, or 30 minutes with the extended max duration beta.

The durable agent primitive is WorkflowAgent from @ai-sdk/workflow. This example assembles the workspace loop from tools defined later in the guide:

workflows/workspace.ts
import { WorkflowAgent, type ModelCallStreamPart } from '@ai-sdk/workflow';
import { getWritable } from 'workflow';
import { stepCountIs } from 'ai';
import { internalTools } from '@/lib/internal-tools';
import { sandboxTools } from '@/lib/sandbox-tools';
import { storeArtifact } from '@/lib/artifacts';
export type RunContext = { userId: string; runId: string };
export async function workspaceRun(prompt: string, ctx: RunContext) {
'use workflow';
const agent = new WorkflowAgent({
model: 'anthropic/claude-fable-5',
instructions:
'You are a research agent for an internal workspace. Use internal tools for company data, use the sandbox for any code you write, and cite every claim.',
tools: {
...internalTools(ctx), // trusted, runs in backend code
...sandboxTools(ctx), // untrusted execution in Vercel Sandbox
},
stopWhen: stepCountIs(40), // budget for the whole run
});
const result = await agent.stream({
messages: [{ role: 'user', content: prompt }],
writable: getWritable<ModelCallStreamPart>(),
});
const pathname = await storeArtifact(ctx.runId, 'report.md', result.text);
return { pathname };
}

The tools are built by factory functions that close over ctx, so every tool call knows which user started the run and which run it belongs to. The prerequisite guide covers the surrounding route handlers, start() and getRun() from workflow/api, and the next.config.ts wrapper.

Copy link to headingAdd budgets, retries, approvals, and cancellation

Production runs need four controls, and Workflows plus the AI SDK provide each one without extra infrastructure.

  • Step budget: stopWhen: stepCountIs(n) caps the loop. The prerequisite guide uses 25 steps for a search-heavy agent. Raise it for workspaces that call many small internal tools, and pair it with an AI Gateway API key budget so model spend has a hard ceiling.
  • Retries: every 'use step' function retries automatically, and completed steps never run twice. Put side effects inside steps so a retry repeats a whole operation rather than half of one.
  • Approvals: set needsApproval: true on any tool that writes to an internal system or exports data. The run suspends until a person responds, without consuming compute while it waits.
  • Cancellation: keep the runId in your run record so an operator can cancel from the UI, and check the run status before starting expensive sandbox work. Sandboxes you created for the run should stop when the run ends, whether it completed or was cancelled.

Copy link to headingStream progress from the same durable run

WorkflowAgent writes model output and tool events to a persisted stream through getWritable(). The workspace UI reads that stream by runId, so a user who closes the tab and returns an hour later reconnects to the same run and sees the same progress. The stream is a view onto the run, not a separate channel you have to keep alive. Every step, input, output, and error is also visible in the Vercel dashboard under Observability > Workflows.

Copy link to headingExpose internal APIs as trusted tools

Copy link to headingPut internal API calls behind narrow typed tools

Internal API access is the requirement that pushes teams toward self-hosting, and it's the one this architecture handles most directly. An internal API tool is a tool() from the AI SDK whose execute function runs as a workflow step. The model fills in validated arguments. Your backend code makes the call with credentials the model never sees.

lib/internal-tools.ts
import { tool } from 'ai';
import { z } from 'zod';
import type { RunContext } from '@/workflows/workspace';
export function internalTools(ctx: RunContext) {
return {
getCustomerSummary: tool({
description: 'Read a customer summary from the internal platform API',
inputSchema: z.object({
customerId: z.string().regex(/^cus_[a-z0-9]+$/),
}),
execute: async ({ customerId }) => {
'use step'; // checkpointed and retried by Workflows
const res = await fetch(
`${process.env.INTERNAL_API_ORIGIN}/customers/${customerId}/summary`,
{
headers: {
authorization: `Bearer ${process.env.INTERNAL_API_TOKEN}`,
'x-run-id': ctx.runId,
},
},
);
if (!res.ok) throw new Error(`Internal API returned ${res.status}`);
// Return only the fields the model needs
const { name, plan, openTickets } = await res.json();
return { name, plan, openTickets };
},
}),
};
}

Three properties make this tool safe to hand to a model:

  • The input schema rejects anything that isn't a well-formed customer ID, so the model can't turn the tool into a generic HTTP client.
  • The execute function calls one operation on one origin.
  • The return value is trimmed to the fields the research task needs, keeping sensitive columns out of the model context and artifacts.

Write one tool per operation you're willing to expose. Exposing queryInternalApi(path, method, body) with arbitrary paths turns the tool into a proxy for the model and defeats the boundary.

Copy link to headingApply user authorization and per-tool credentials

The run inherits the identity of the person who started it. Pass that identity into each tool call and authorize at the internal API, so the workspace can never read data its user couldn't read in the source system.

lib/internal-tools.ts
// lib/internal-tools.ts (excerpt)
execute: async ({ customerId }) => {
'use step';
// Your own function: exchange the platform identity for a short-lived,
// read-only token scoped to this user and this operation.
const token = await mintInternalToken({
subject: ctx.userId,
scope: 'customers:read',
ttlSeconds: 300,
});
const res = await fetch(
`${process.env.INTERNAL_API_ORIGIN}/customers/${customerId}/summary`,
{ headers: { authorization: `Bearer ${token}`, 'x-run-id': ctx.runId } },
);
if (res.status === 403) {
// Tell the model, don't throw. It can continue with other sources.
return { error: 'This user does not have access to that customer' };
}
if (!res.ok) throw new Error(`Internal API returned ${res.status}`);
return res.json();
},

mintInternalToken stands in for whatever your identity layer provides, such as a token exchange against your identity provider or a signed service token. On Vercel, deployments receive a VERCEL_OIDC_TOKEN that identifies the project and environment. If your internal API can trust an OIDC issuer, use that token directly and skip the long-lived INTERNAL_API_TOKEN entirely. The Docker KB guide describes how Vercel provides the token, and the AWS RDS with eve guide shows OIDC federation against a cloud provider.

Keep credentials per tool, not per workspace. Read-only tools get read-only scopes, and tools that open tickets get a write scope plus needsApproval: true.

Copy link to headingUse Static IPs or Secure Compute for private egress

By default, Vercel deployments can egress from any IP address, so an internal API that allowlists source IPs will reject them. You can solve this with:

  • Static IPs gives Pro and Enterprise projects a shared pool of static egress addresses. Add them to your internal API's firewall and keep application-level authentication in place, because an IP alone isn't an access control.
  • Secure Compute is an Enterprise add-on that puts your Functions and build container on a dedicated private network with its own static IPs, a NAT gateway, and VPC peering into your AWS, Azure, or other private network. Use it when the internal API has no public endpoint.

Both apply to the trusted zone, which is where internal API tools run. Sandboxes can also reach a Secure Compute network when their network policy allows access to the private CIDR range, but this guide recommends keeping internal API access within workflow steps and leaving sandboxes without a route to production systems.

Copy link to headingIsolate code and browser tools

Copy link to headingUse Vercel Sandbox for model-written code and commands

Move work into a sandbox when the code is untrusted, when it parses untrusted input, or when it needs a shell. Each Vercel Sandbox is a Firecracker microVM with its own filesystem and network, booted from the vercel/sandbox/universal image by default, which includes Node.js, Python 3.14, and common utilities. When you need specific tooling, Custom OCI images from Vercel Container Registry replace the default.

lib/sandbox-tools.ts
import { Sandbox } from '@vercel/sandbox';
import { tool } from 'ai';
import { z } from 'zod';
import type { RunContext } from '@/workflows/workspace';
export function sandboxTools(ctx: RunContext) {
return {
runAnalysis: tool({
description:
'Run a Python script over a dataset. The script reads dataset.json from its working directory and prints results to stdout.',
inputSchema: z.object({
script: z.string().describe('The Python script to execute'),
dataset: z.string().describe('The dataset as a JSON string'),
}),
execute: async ({ script, dataset }) => {
'use step';
// One sandbox per run. A retried step reattaches to it.
const sandbox = await Sandbox.getOrCreate({
name: `research-${ctx.runId}`,
timeout: 30 * 60 * 1000,
networkPolicy: 'deny-all', // no egress, no DNS
});
await sandbox.writeFiles([
{ path: 'dataset.json', content: Buffer.from(dataset) },
{ path: 'analyze.py', content: Buffer.from(script) },
]);
const cmd = await sandbox.runCommand({ cmd: 'python3', args: ['analyze.py'] });
return {
exitCode: cmd.exitCode,
stdout: await cmd.stdout(),
stderr: await cmd.stderr(),
};
},
}),
};
}

Two decisions in this code do the security work:

  • networkPolicy: 'deny-all' blocks every outbound connection including DNS, so the script can compute over the dataset but can't send it anywhere.
  • The dataset arrives as a tool argument that the trusted loop already fetched, so the sandbox never needs a credential or a route to the source.

Copy link to headingSeparate sandbox network access from internal API access

The sandbox firewall makes the network boundary explicit. Each sandbox runs under one of three policies, and you can change the policy on a running sandbox without restarting it.

PolicyBehaviorUse it for
allow-allUnrestricted public internet. This is the default.Installing packages and pulling public data before locking down
deny-allNo outbound traffic, including DNS.Running untrusted code over data you already placed in the sandbox
User-definedDeny by default, then allow listed domains or CIDR ranges, with optional credential brokering and request proxying.Tools that legitimately need one or two external services

The rule for a research workspace is that internal APIs are never in a sandbox allowlist. Trusted steps fetch internal data and write it into the sandbox. When model-written code needs an external service, allow that one domain and let the firewall inject the credential on the way out:

import { Sandbox } from '@vercel/sandbox';
const sandbox = await Sandbox.create({
networkPolicy: {
allow: {
// Broker the key at the firewall so it never enters the VM
'ai-gateway.vercel.sh': [
{
transform: [
{ headers: { Authorization: `Bearer ${process.env.AI_GATEWAY_API_KEY}` } },
],
},
],
// Route every request to this data source through a proxy you control
'api.partner-data.example.com': [
{ forwardURL: 'https://your-app.vercel.app/api/sandbox-proxy/partner' },
],
},
},
});

The forwardURL proxy is a Vercel Function. It receives the original request plus a vercel-sandbox-oidc-token header that identifies the team, project, and sandbox, so you can log every outbound request and reject paths you don't want the model to reach. The defineSandboxProxy helper validates the token for you:

app/api/sandbox-proxy/partner/route.ts
import { defineSandboxProxy } from '@vercel/sandbox/proxy';
const proxy = defineSandboxProxy(async (request, { sandboxId, projectId }) => {
const path = request.headers.get('vercel-forwarded-path') ?? '';
if (!path.startsWith('/v1/public/')) {
return new Response('Path not allowed', { status: 403 });
}
console.log(JSON.stringify({ event: 'sandbox_egress', sandboxId, projectId, path }));
return fetch(request);
});
// Sandboxes forward requests with their original method, so expose every verb
export {
proxy as GET,
proxy as POST,
proxy as PUT,
proxy as PATCH,
proxy as DELETE,
};

Several firewall behaviors affect how you write policies. An empty user-defined policy behaves as deny-all. Leading wildcards such as *.example.com match subdomains but not example.com itself. Domain rules match on the TLS SNI, so plain HTTP and raw IP traffic must be allowed by CIDR range instead, and CIDR rules don't restrict DNS. The Sandbox firewall docs cover each case, including the domain-fronting caveat and how transform rules pin the Host header.

On Enterprise teams with Secure Compute, attach the sandbox to a network with Sandbox.create({ networkId: '...' }). That network provides static public egress and, with VPC peering configured, access to private AWS resources. The sandbox’s network policy controls permitted destinations separately. Changes to an existing sandbox’s network take effect in its next session.

Treat private sandbox egress as an exception you document, not the default, because it gives model-written code a route that only a proxy or credential brokering can constrain.

Copy link to headingUse one sandbox per run, task, or agent based on the risk boundary

GranularityWhen to use itTradeoff
One sandbox per runMost research workspaces. Analysis steps share files, and one VM amortizes boot time.Everything in the run shares a filesystem
One sandbox per taskTasks with different network needs, or tasks handling data from different tenants.More creations, which are billed but inexpensive
One sandbox per agent, or one Linux user per agent in a shared sandboxMulti-agent runs where agents must not read each other's files.User isolation is cheaper than separate VMs, but shares a kernel

For the multi-agent case, sandbox.createUser() adds a Linux user with an isolated home directory, and a user's runCommand runs as that user:

import { Sandbox } from '@vercel/sandbox';
const sandbox = await Sandbox.create();
const researcher = await sandbox.createUser('researcher');
const coder = await sandbox.createUser('coder');
await researcher.writeFiles([
{ path: 'notes.md', content: Buffer.from('private notes') },
]);
// The coder agent can't read the researcher's home directory
const denied = await coder.runCommand({
cmd: 'cat',
args: ['/home/researcher/notes.md'],
});
console.log(denied.exitCode); // non-zero: permission denied

User and group names must be at most 32 characters. The multi-agent docs cover shared groups for files agents should exchange.

Copy link to headingPlan browser automation with Marketplace browser services or a sandbox image

Browser tools need the same isolation as code tools plus two things code tools don't. Sessions are long-lived and stateful, and real sites push back with bot detection and CAPTCHAs.

You can solve this with two architecture choices:

  • Marketplace browser infrastructure. Browserbase and KERNEL provide sandboxed cloud browsers as Vercel Marketplace integrations with unified billing. Installing one adds an API key to your project, and your workflow steps drive the browser over the provider's SDK or the Chrome DevTools Protocol. Choose this path when the workspace browses the open web, needs live view or session replay, or needs anti-detection features. Treat the provider as a separate trust zone with its own credential, and pass it the same scoped inputs you'd pass a sandbox.
  • A browser inside Vercel Sandbox. Run Chromium in the sandbox itself, driven by agent-browser from Vercel Labs or a similar CDP client. This is the pattern eve uses: its @agent-browser/eve extension runs Chromium and agent-browser inside the agent's sandbox, restricts navigation with an allowedDomains list, and never exposes cookie or saved-auth commands to the model. Install the browser at runtime, or build it into a custom image in Vercel Container Registry and pass it as image to Sandbox.create() so sessions start warm. Choose this path when the browser must stay inside a network policy you control, for example when it signs into an internal dashboard and should reach nothing else.

In both cases, the browser session is a tool the control plane calls. Keep the agent loop in Workflows, keep internal credentials out of the browser environment, and write screenshots and extracted data to Blob as evidence.

Copy link to headingStore artifacts and evidence outside the run

Copy link to headingPersist reports, evidence, and event logs

Anything a person or a downstream system needs after the run belongs in a private Vercel Blob store, written from a workflow step so a retry overwrites the same object:

lib/artifacts.ts
import { put } from '@vercel/blob';
export async function storeArtifact(
runId: string,
name: string,
body: string | Buffer,
) {
'use step';
const blob = await put(`runs/${runId}/${name}`, body, {
access: 'private',
allowOverwrite: true, // a retried step writes the same object
});
return blob.pathname;
}

Use a consistent key layout such as runs/{runId}/report.md, runs/{runId}/evidence/{n}.html, and runs/{runId}/events.jsonl. Evidence files allow a reviewer to check a citation after the source page changes, so capture them at fetch time rather than reconstructing them later.

Copy link to headingReturn downloadable artifacts to the workspace UI

Private stores have no public URLs. Serve downloads via a route that checks whether the user owns the run, then either streams the object using the Blob SDK or issues a signed URL with a short expiry. Signed URLs are scoped to a single operation and pathname, expire after 1 hour by default, and can be extended to up to 7 days. The Private Storage and Signed URLs docs cover both approaches.

Store the returned pathname in the run record because Signed URLs expire, and the pathname is what you need to sign a new one.

Copy link to headingKeep audit records for tool calls and approvals

Workflows already records every step's input, output, and error in the dashboard. For compliance and debugging across runs, also write an application-level audit event for each tool call. The minimum useful record:

FieldPurpose
runIdJoins the event to the workflow run and the artifacts
userIdWho the run acted on behalf of
toolWhich tool was called
inputHashSHA-256 of the tool arguments, so you can prove what was requested without storing sensitive inputs
approvalStatenot_required, pending, approved, or denied, with the approver's ID
sandboxIdWhich sandbox executed the step, when one was used
artifactPathsBlob pathnames the step produced
startedAt, completedAtTiming for cost and latency analysis

Write the event from inside the step, after the operation completes, so a retried step produces one final record.

Copy link to headingCompare Vercel with Kubernetes, Temporal, LangGraph, E2B, Modal, and Daytona

The comparison is at the architecture level. Vendor features change, so confirm current details against each provider's documentation before a procurement decision.

ApproachOrchestrationIsolation for code and browser toolsInternal API accessWhat you operateFits best when
Vercel (this guide)Vercel Workflows, managed and generally available for TypeScriptVercel Sandbox microVMs with an egress firewall, plus Marketplace browsersTrusted workflow steps, with Static IPs or Secure Compute for allowlists and private networksApplication code, tool schemas, network policiesThe workspace is a web application, the team writes TypeScript, and nobody wants to run orchestration or sandbox infrastructure
Kubernetes with TemporalTemporal server or Temporal Cloud plus a worker fleet you deploygVisor, Kata, or Firecracker nodes you configure and patchIn-cluster networkingCluster, workers, sandbox tier, upgrades, observability stackTemporal is already a company standard, or the workload includes always-on non-HTTP services
LangGraph with E2BLangGraph runtime, self-hosted or on its managed platformE2B managed sandboxesFrom wherever the orchestrator runsOrchestrator hosting and two vendor relationshipsThe team is Python-first and wants explicit graph definitions
Modal or Daytona as a sandbox planeBring your own orchestratorProvider-managed sandboxesFrom your orchestrator hostThe orchestrator, plus integration with the sandbox providerAn existing sandbox investment, or GPU and batch workloads the workspace hands off to
AWS Bedrock AgentCoreAgent hosting with session isolation, not a durable execution engineAgentCore runtime sessions with built-in code interpreter and browserInside your AWS VPCAn AWS account and IAMThe organization is standardized on AWS and wants agent hosting in-account

Copy link to headingWhen Vercel should be the primary platform

Choose Vercel as the primary platform when the workspace is a web application with a UI, an API, and agents that run for minutes to hours, when tools are HTTP calls and sandboxed commands, and when you want durability, model routing, isolation, and artifact storage from one platform with one deployment model. The control plane, the trusted tools, and the sandboxes all deploy with vercel deploy or a Git push, and the dashboard shows workflow steps, sandbox sessions, and model calls together.

Copy link to headingWhen to keep a separate sandbox plane

Keep or add a separate sandbox plane when you need GPUs for the sandboxed work itself, when a browser fleet needs residential proxies or anti-detection features beyond what Marketplace providers offer, when sandboxes must live inside a specific VPC with custom routing that a network policy can't express, or when an existing sandbox contract already covers the workload. In each case the Vercel control plane still calls the external plane from a workflow step, and the boundary rules in this guide still apply.

Copy link to headingWhen self-hosted orchestration still fits

Self-hosted orchestration fits when the company has standardized on Temporal or Kubernetes operators and the research workspace is one of many workloads on that platform, when the agent code is in a language the Workflow SDK doesn't cover yet, or when the workspace depends on stateful workers that hold connections open indefinitely. Vercel can still host the UI and the trusted API layer in front of that orchestrator, and Secure Compute can connect the two privately.

Copy link to headingOperate the workspace in production

Copy link to headingObserve workflow runs, sandbox sessions, and model calls

The dashboard shows three views that together cover a run:

  • Observability > Workflows lists every run with its steps, inputs, outputs, and errors to inspect.
  • Observability > Sandboxes shows sessions, their resource use, and their network policy, and lets an operator stop a sandbox from the dashboard.
  • AI Gateway logs every model call with token counts, latency, and cost. Tag each of them with the runId so an operator can move from a slow report to the step, the sandbox, and the model call that caused it.

Copy link to headingControl secrets and environment access

Secrets stay in the trusted zone. Internal API tokens, Blob tokens, and provider keys are project environment variables that workflow steps read. Sandboxes receive only the environment variables a command needs, passed in the env option of runCommand, and anything a sandbox must send to an external service goes through firewall credential brokering so the secret never enters the VM. Prefer the deployment's VERCEL_OIDC_TOKEN over long-lived static tokens wherever the receiving system can validate it.

Copy link to headingSet cleanup, retention, and cost guardrails

  • Sandbox lifetime: set the shortest timeout that fits the task and call sandbox.stop() when the run finishes. On Pro and Enterprise, a session can run up to 24 hours, and a persistent sandbox can stop and resume beyond that, so an unbounded sandbox is a cost you chose rather than a limit you hit.
  • Snapshots and drives: snapshots expire 30 days after last use by default. Set an explicit retention period for anything you keep longer.
  • Step and spend caps: keep stopWhen on every agent and attach a budgeted AI Gateway key so a runaway loop stops at a known cost.
  • Artifact retention: decide how long evidence files live and enforce it with a scheduled cleanup job. Reports are cheap to keep. Raw fetched pages add up.
  • Spend Management: configure alerts or an automatic pause at a team spend threshold that covers Sandbox, Functions, and Workflows usage.

Copy link to headingPlan availability and limits

ResourceHobbyProEnterprise
Vercel Sandbox max session duration45 minutes24 hours24 hours
Vercel Sandbox concurrent sandboxes1010,00010,000
Vercel Sandbox max vCPUs per sandbox4832
Vercel WorkflowsAvailableAvailableAvailable
Static IPsNot availableAvailableAvailable
Secure ComputeNot availableNot availableAdd-on
Vercel Functions max duration300 seconds800 seconds, 30 minutes extended (beta)800 seconds, 30 minutes extended (beta)

Functions default to 300 seconds on every plan. Workflow steps can opt into the 30-minute extended duration with the VERCEL_ENABLE_WORKFLOW_EXTENDED_MAX_DURATION environment variable on Pro and Enterprise. Sandbox creations are billed per creation, and downloads into a sandbox are free, so a per-task sandbox strategy costs little more than a per-run one. See Vercel Functions limits, Sandbox pricing and quotas, and Workflow pricing and limits for current figures.

Copy link to headingTroubleshooting

Copy link to headingSandbox commands fail with network errors

User-defined policies with no allowed domains behave as deny-all, which blocks DNS as well as connections. Check that the domain you need is listed, that you added the apex domain separately if you used a leading wildcard, and that plain HTTP or IP-literal traffic is allowed by CIDR range rather than by domain.

Copy link to headingSandbox or AI Gateway calls fail locally with an authentication error

Both authenticate with the project's OIDC token on Vercel. Locally, run vercel link and vercel env pull to fetch a development token, and re-run vercel env pull when it expires.

Copy link to headingThe internal API rejects requests from Vercel

Vercel deployments egress from any IP address by default. Add Static IPs to the project and allowlist them, or use Secure Compute for private connectivity. Then confirm the tool is sending the credential the API expects.

Copy link to headingA long run stopped after a deployment

Workflows resumes runs across deployments by replaying completed steps. If a run appears stuck, check the run in Observability > Workflows for a step waiting on approval or a failing retry. Side effects outside a 'use step' boundary are the usual cause of duplicated work after a resume.

Copy link to headingFiles written in the sandbox are gone

The sandbox filesystem is ephemeral once the sandbox stops. Write anything you need to Blob from the same step that produced it, or mount a Drive when a later run needs the files.

Copy link to headingBrowser sessions time out

Check the sandbox timeout and extend it with extendTimeout() for long sessions, or check the Marketplace provider's session limits. Split browser tasks that outlast a single tool call into steps so each one checkpoints.

Copy link to headingNext steps

Copy link to headingFrequently asked questions

Should internal API tools run inside Vercel Sandbox?

Usually no. Keep trusted internal API calls in workflow steps that run as Vercel Functions, then pass only the scoped inputs and outputs to a sandbox when untrusted code needs them.

What should run in Vercel Sandbox for a research workspace?

Model-written code, repository or file inspection, shell commands, custom tool runtimes from your own images, and browser automation that should not share a process, filesystem, or credentials with the application.

Do I still need LangGraph or Temporal?

Not for a TypeScript workspace on Vercel. Workflows and WorkflowAgent provide durable, resumable agent execution with approvals and streaming. Teams with an existing graph runtime or Temporal standard can keep it and host the UI and trusted tools on Vercel.

Can Vercel run Docker for this architecture?

Yes. Vercel deploys OCI container images as Vercel Functions, stores them in Vercel Container Registry, and boots Vercel Sandbox from custom images. Vercel does not run always-on stateful containers, so model those components as Functions, Workflows, or Sandboxes.

How should I handle browser tools?

Treat the browser as a separate sandboxed capability with its own network and credential boundary. Use Browserbase or Kernel from the Marketplace for open-web browsing with anti-detection needs, or Chromium with agent-browser inside Vercel Sandbox when the browser must stay inside a network policy you control.

More Vercel Functions guides