Skip to content
Docs

Private enterprise agents on Vercel

Design private enterprise agents that call internal APIs and databases with Vercel Functions, Secure Compute, AI Gateway, Workflows, and Vercel Connect.

Vercel

On Vercel, a private enterprise agent is a custom agent application where the AI SDK, WorkflowAgent, or eve drives the model, and trusted tool code in Vercel Functions reaches internal APIs and databases through Secure Compute, AWS PrivateLink, or Static IPs. The model never connects to your private systems. It requests a tool call, and your application code decides whether and how to run it.

Teams that need tool calling against internal APIs often assume the whole agent runtime has to live inside their VPC, assembled from LangGraph, an MCP gateway, Temporal, and Kubernetes. On Vercel, the agent loop, durable state, tool execution, and private network path deploy as one project, and only tool traffic enters your network.

Copy link to headingOverview

In this guide, you'll learn how to:

  • Map each layer of a private agent to AI Gateway, the AI SDK, Workflows, Vercel Functions, and Vercel Connect
  • Choose between Secure Compute, AWS PrivateLink, Static IPs, and Vercel Connect for each tool's access path
  • Keep credentials in trusted tools and out of Vercel Sandbox, prompts, and tool results
  • Write internal API and private database tools that scope access to the signed-in user
  • Decide when a LangGraph, Temporal, or self-managed stack is still the better fit

Copy link to headingPrerequisites

  • Your Vercel team on the Enterprise plan for Secure Compute, or on the Pro or Enterprise plan for AWS PrivateLink or Static IPs
  • Your internal API or database in an AWS VPC you can peer with, behind an AWS PrivateLink endpoint service, or in Azure, Google Cloud, or an on-premises network that can terminate a site-to-site VPN
  • Your Next.js app or eve agent deployed to Vercel, using the ai package (AI SDK 7) and zod

Copy link to headingHow private tool calls work on Vercel

Model tool calling is a request for your application to run a function. The model picks a tool and supplies arguments, then your application validates them, executes the function, and returns the result. The model never holds credentials or opens a network connection to your internal systems.

Each private tool call on Vercel follows this path:

  1. The user signs in and sends a message to your agent's route, which runs as a Vercel Function.
  2. The agent loop sends the conversation and tool definitions to a model through AI Gateway.
  3. The model responds with a tool call, such as lookupOrder with { "orderNumber": "ORD-104233" }.
  4. Your tool code validates the arguments and checks what the signed-in user is allowed to see.
  5. The tool calls the internal API or database. With Secure Compute or AWS PrivateLink, the request travels over a private network path. With Static IPs, it leaves over the public internet from a known IP pair.
  6. The tool returns only the fields the model needs, and the model writes its answer.
  7. On WorkflowAgent, a tool whose execute function is marked 'use step' runs as a checkpointed Workflows step that retries on failure and survives restarts. The agent can also suspend a tool call until a person approves it.

The rest of the architecture follows from two decisions, where each tool runs and how its traffic reaches the target system.

Copy link to headingMap the private agent architecture to Vercel products

Private agents have seven layers, and each one maps to a Vercel product that deploys in the same project.

LayerWhat it needsOn Vercel
Model accessOne endpoint for many models, with usage and cost visibilityAI Gateway
Agent loop and tool definitionsTyped tool schemas and a bounded loopAI SDK, WorkflowAgent from @ai-sdk/workflow, or eve (beta)
Durable orchestrationRetries, waits, and resume without holding a container openWorkflows
Tool executionTrusted compute that holds credentialsVercel Functions on the Node.js, Python, Go, or Ruby runtime
Private network pathOutbound access to internal APIs and databasesSecure Compute on Enterprise, or AWS PrivateLink and Static IPs on Pro and Enterprise
Third-party business systemsShort-lived, scoped credentials for SaaS APIsVercel Connect
Untrusted code executionIsolation for model-generated codeVercel Sandbox

AI Gateway resolves model strings such as anthropic/claude-sonnet-5.5 for the AI SDK, WorkflowAgent, and eve. Your tool code, workflow steps, and agent routes all run as Vercel Functions, so the project's networking settings cover every private call the agent makes.

Copy link to headingChoose between the AI SDK, WorkflowAgent, and eve

All three options run tool code in Vercel Functions, so the networking and security guidance in this guide applies to each one. They differ in how long an agent run can last and what happens when an invocation ends.

OptionUse it whenState between tool calls
AI SDK generateText or ToolLoopAgentThe agent answers within a single request, such as a support lookupIn memory for one invocation
WorkflowAgent from @ai-sdk/workflowTool calls must retry from a checkpoint, wait for approval, or span hours or daysTools marked 'use step' run as durable Workflows steps; other tools run in memory
eve (beta)You want instructions, tools, channels, connections, and a sandbox in one filesystem-first agent projectWorkflows persist session state

Copy link to headingChoose a private connectivity path for each tool

Choose the path per tool, based on where the target system lives and what your security policy requires. Secure Compute, AWS PrivateLink, and Static IPs control how Vercel Functions reach infrastructure you run, and Vercel Connect controls how tools authenticate to third-party APIs. One agent often uses more than one. Enterprise teams whose policy requires compute to run inside their own AWS account can also scope Bring Your Own Cloud, which runs your functions in that account.

PathReachesIsolationPlansPricing
Secure ComputeInternal APIs and databases over AWS VPC peering, or over a site-to-site VPN to Azure, Google Cloud, or on-premises networksDedicated VPC and subnet per customer, with a dedicated IP pairEnterpriseCustom; Private Data Transfer is $0.15/GB for traffic that leaves over the public internet, and VPC peering traffic has no data transfer charge
AWS PrivateLinkAWS-hosted services that publish a PrivateLink endpoint service, including internal APIs behind a Network Load Balancer, RDS, Aurora, Neon, Redshift, Snowflake, and MongoDB AtlasDedicated VPC endpoint and IAM role per team, in a shared VPCPro and Enterprise, with Advanced NetworkingFirst connection included with Advanced Networking; $30/month per additional connection; data transfer is $0.04/GB
Static IPsServices that accept traffic from an IP allowlistShared VPC with subnet-level isolationPro and Enterprise$100/month per project, plus Private Data Transfer at regional rates
Vercel ConnectThird-party APIs such as Slack, GitHub, Microsoft, Snowflake, and Salesforce, plus OAuth-protected MCP serversShort-lived tokens scoped by project link, environment, and requestHobby, Pro, and EnterpriseHobby includes 500 token requests and 1,000 triggers per month; Pro is $3.00 per 1,000 token requests and $0.95 per 1,000 triggers; Enterprise is custom

Copy link to headingUse Secure Compute for dedicated networking and VPC peering

Secure Compute creates a dedicated private network for your Vercel Functions, with a NAT Gateway and a pair of static IPs that don't change. You attach a project to the network per environment in the project's Settings → Networking page, and every function in that environment routes through it without networking code in your tools. With VPC peering, your database or internal API can keep no public address at all.

Secure Compute applies to Vercel Functions on the Node.js, Python, Go, and Ruby runtimes. The Edge runtime isn't supported, so Routing Middleware and functions that use the edge runtime don't send traffic through the network. Projects on Secure Compute don't support the extended max duration, Large Functions, or Container Images betas. The standard 800-second maximum duration and 250 MB bundle limit (500 MB for Python) apply on Pro and Enterprise instead. Each network supports up to 100 projects and 50 VPC peering connections.

Self-service network creation isn't available to every Enterprise team. If you don't see Create Network under your team's Settings → Networking, contact your Vercel account team. For the full peering walkthrough, including route tables and security groups, see Give your eve agent secure access to your private AWS RDS database.

AWS PrivateLink connects your functions and builds to an AWS PrivateLink endpoint service over the AWS private network, with no public internet hop and no VPC peering to manage. It fits internal APIs behind an AWS Network Load Balancer, AWS databases such as RDS, Aurora, and Redshift, and SaaS providers such as Snowflake and MongoDB Atlas that expose an endpoint service.

To set it up, enable Advanced Networking in the project's Settings → Networking page and add a connection with the provider's service name and AWS region. The provider then accepts the connection or allowlists the IAM role Vercel assigns to your team, and your tool code connects through the endpoint's DNS name. Enable Private DNS on the connection to resolve the provider's own private hostnames instead.

Each PrivateLink connection exists in one AWS region and applies to every environment in the project. PrivateLink supports interface endpoints only, and it doesn't apply to Routing Middleware. The VPC endpoint is dedicated to your team, but the underlying VPC is shared, so use Secure Compute when you need full network isolation. For backends outside AWS, or ones that aren't exposed as an endpoint service, use Secure Compute or Static IPs.

Copy link to headingUse Static IPs when an IP allowlist meets your security policy

Static IPs route outbound traffic through a shared pool of static IP pairs, which your internal service adds to its allowlist. The service still receives that traffic over the public internet, so use this path only when public ingress from known IPs fits your policy. Static IPs apply to every environment in a project, each configured region has its own IP pair, and a project attached to Secure Compute ignores Static IPs.

Secure Compute, AWS PrivateLink, and Static IPs are all outbound paths. They don't give your agent a fixed inbound IP, so internal systems that call the agent, such as a ticketing system that starts a run, use an authenticated Vercel route. IP filtering also doesn't replace authentication, so keep a token, password, or key on every internal call.

Copy link to headingUse Vercel Connect for scoped access to third-party APIs

Vercel Connect issues short-lived provider tokens at runtime, so tools don't store long-lived SaaS secrets in environment variables or a database. You create a connector once for your team, link it to the projects and environments that need it, and call getToken from server-side tool code. On Vercel, the SDK authenticates with the deployment's OIDC token, and Vercel Connect checks that token against the connector's project links before it issues anything.

This tool posts an incident summary to Slack with a token scoped to chat:write:

import { getToken } from '@vercel/connect';
import { tool } from 'ai';
import { z } from 'zod';
export const postIncidentSummary = tool({
description: 'Post an incident summary to the on-call Slack channel.',
inputSchema: z.object({ summary: z.string().max(3000) }),
execute: async ({ summary }) => {
const token = await getToken('slack/acme-slack', {
subject: { type: 'app' },
scopes: ['chat:write'],
});
const res = await fetch('https://slack.com/api/chat.postMessage', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ channel: process.env.ONCALL_CHANNEL_ID, text: summary }),
});
const data = await res.json();
return { posted: data.ok === true };
},
});

The SDK caches each token in process until it nears expiry, so an agent that makes many provider calls in one invocation pays for one token request. To act on behalf of a signed-in user instead of the app, request a token with subject: { type: 'user', id }. Vercel Connect bills by token requests and by triggers, which are provider webhooks that it verifies and forwards to a linked project. The Complete Guide to Vercel Connect covers connector setup, subjects, and error handling.

Copy link to headingKeep secrets and private data in the right execution environment

The execution boundary is the main security decision in a private agent. Vercel's security guidance for agentic architectures treats the orchestration and tool code you deploy as trusted software, and treats the model and any code it generates as untrusted. Credentials belong only where your own reviewed code runs.

Copy link to headingRun internal API and database tools in Vercel Functions

Trusted tools that hold internal credentials run in Vercel Functions. Store those credentials as encrypted environment variables, or request them from Vercel Connect at runtime, and read them inside the tool's execute function. The model sees the tool's name, description, input schema, and result, and never the credential.

Return only the fields the model needs from each tool. Workflows records every step's inputs and outputs, and eve shows tool calls in Agent Runs, so a credential or unnecessary personal data in a tool result ends up in run history.

Copy link to headingRun untrusted code in Vercel Sandbox, away from private systems by default

Vercel Sandbox runs model-generated code in an isolated microVM with its own network. By default, a sandbox doesn't join your project's Secure Compute network, so code inside it can't reach your private databases. Keep private queries in trusted tools and pass the results into the sandbox as data.

When generated code must reach a private resource directly, attach the sandbox to your Secure Compute network with its networkId, as described in Using Secure Compute with Sandbox. Restrict the sandbox's egress firewall to the private range it needs, since the default policy allows all public internet traffic. Use the firewall's credentials brokering to inject secrets into outbound requests so generated code never reads them, and note that traffic to an allowed IP range bypasses credentials brokering.

Two more caveats apply when generated code connects to a private database over an allowed IP range. Allowing only address ranges leaves DNS unrestricted, so add domain rules or use deny-all if DNS exfiltration is part of your threat model. Credentials brokering also doesn't work on Postgres connections, so the database credential has to reach the sandbox another way, such as a short-lived, read-only credential that a trusted tool issues.

Copy link to headingScope every tool to the signed-in user and validate its arguments

Treat every tool argument as untrusted input, because a prompt injection in a document, ticket, or log line can steer the model's choices. These practices contain that risk:

  • Take identity from your auth layer, not from the model. Pass the user or tenant ID into the tool through a closure or WorkflowAgent's toolsContext, instead of exposing it as an input field the model fills in.
  • Validate inputs with strict schemas, such as a regular expression for IDs and an enum for actions, before any network call.
  • Use least-privilege credentials, such as a read-only database role for query tools and a separate service account for each internal API.
  • Gate mutating actions behind human approval or a policy check, with toolApproval in the AI SDK or needsApproval in WorkflowAgent, and set an explicit step limit on the agent loop.

Copy link to headingImplement trusted internal tools

The three examples below cover a request-scoped read, a durable mutating action, and a private database query. Each one keeps credentials in server-side code and takes identity from your application instead of from the model.

Copy link to headingCall an internal API from an AI SDK tool

This route answers order questions for the signed-in customer. The tool is defined inside the request handler, so it closes over the session and can only read that customer's orders.

Install the packages:

Terminal
npm install ai zod

Create the route:

import { generateText, isStepCount, tool } from 'ai';
import { z } from 'zod';
import { getSession } from '@/lib/auth'; // Your app's auth helper
// Secure Compute, AWS PrivateLink, and Static IPs don't apply to the Edge runtime.
export const runtime = 'nodejs';
export async function POST(request: Request) {
const session = await getSession(request);
if (!session) {
return new Response('Unauthorized', { status: 401 });
}
const { prompt } = await request.json();
const lookupOrder = tool({
description: "Look up one of the signed-in customer's orders by order number.",
inputSchema: z.object({
orderNumber: z.string().regex(/^ORD-\d{6}$/),
}),
execute: async ({ orderNumber }) => {
// The customer ID comes from the session, not from the model.
const customerId = encodeURIComponent(session.customerId);
const res = await fetch(
`${process.env.INTERNAL_API_URL}/customers/${customerId}/orders/${orderNumber}`,
{ headers: { authorization: `Bearer ${process.env.INTERNAL_API_TOKEN}` } },
);
if (!res.ok) {
return { found: false, status: res.status };
}
const order = await res.json();
// Return only what the model needs to answer.
return { found: true, status: order.status, updatedAt: order.updatedAt };
},
});
const { text } = await generateText({
model: 'anthropic/claude-sonnet-5.5',
tools: { lookupOrder },
stopWhen: isStepCount(5),
prompt,
});
return Response.json({ text });
}

Set INTERNAL_API_URL to the API's private address and INTERNAL_API_TOKEN to a service credential with read-only order access. Sending the prompt "Where is order ORD-104233?" returns a response like this:

{ "text": "Order ORD-104233 shipped on September 18 and is in transit." }

Without stopWhen, the request stops as soon as the tool runs and returns an empty text, because the model never gets a turn to answer from the tool result.

Copy link to headingGate a mutating internal API call on human approval with WorkflowAgent

Actions that change internal systems need retries that don't double-apply and a reviewer who can approve hours or days later. When a tool's execute function is marked 'use step', WorkflowAgent runs that tool call as a durable Workflows step that retries on failure (3 attempts by default) and survives restarts. Tools without the directive run in memory with no durability guarantees. Separately, needsApproval: true suspends the run until a reviewer responds, and no compute bills while the run waits.

Install the packages. WorkflowAgent requires Workflow 5, which is available under the beta tag:

Terminal
npm install @ai-sdk/workflow workflow@beta ai zod

Define the workflow. The internal API call lives in applyChangeStep, a module-level step function marked 'use step' that takes plain, serializable arguments. toolsContext passes the requester's ID from your auth layer to the tool, and execute hands it to the step. experimental_toolApprovalSecret signs each approval, so a modified client message history can't approve a call:

import { WorkflowAgent, type ModelCallStreamPart } from '@ai-sdk/workflow';
import { convertToModelMessages, isStepCount, tool, type UIMessage } from 'ai';
import { FatalError, getWritable } from 'workflow';
import { z } from 'zod';
// A durable step that retries on failure (3 attempts by default)
async function applyChangeStep(changeId: string, requesterId: string) {
'use step';
const res = await fetch(`${process.env.INTERNAL_API_URL}/changes/${changeId}/apply`, {
method: 'POST',
headers: {
authorization: `Bearer ${process.env.INTERNAL_API_TOKEN}`,
'content-type': 'application/json',
// Lets the internal API ignore a retried request it already applied
'idempotency-key': changeId,
'x-requested-by': requesterId,
},
});
if (res.status >= 500) {
// Throwing makes Workflows retry the step
throw new Error(`Change API returned ${res.status}`);
}
if (!res.ok) {
// A 4xx won't succeed on retry, so fail the step without retrying
throw new FatalError(`Change API rejected ${changeId} with ${res.status}`);
}
return { applied: true, status: res.status };
}
export async function changeAgent(messages: UIMessage[], requesterId: string) {
'use workflow';
const agent = new WorkflowAgent({
model: 'anthropic/claude-sonnet-5.5',
instructions: 'You help engineers review and apply configuration changes.',
experimental_toolApprovalSecret: { environmentVariable: 'TOOL_APPROVAL_SECRET' },
tools: {
applyChange: tool({
description: 'Apply a proposed change through the internal change API.',
inputSchema: z.object({ changeId: z.string().regex(/^chg_[a-z0-9]+$/) }),
contextSchema: z.object({ requesterId: z.string() }),
needsApproval: true, // Suspends the run until a reviewer responds
execute: ({ changeId }, { context }) => applyChangeStep(changeId, context.requesterId),
}),
},
toolsContext: { applyChange: { requesterId } },
});
const result = await agent.stream({
messages: await convertToModelMessages(messages),
writable: getWritable<ModelCallStreamPart>(),
stopWhen: isStepCount(10), // WorkflowAgent has no default step limit
});
return { messages: result.messages };
}

Start the workflow from an authenticated route:

import { createModelCallToUIChunkTransform } from '@ai-sdk/workflow';
import { createUIMessageStreamResponse, type UIMessage } from 'ai';
import { start } from 'workflow/api';
import { getSession } from '@/lib/auth';
import { changeAgent } from '@/workflows/change-agent';
export async function POST(request: Request) {
const session = await getSession(request);
if (!session) {
return new Response('Unauthorized', { status: 401 });
}
const { messages }: { messages: UIMessage[] } = await request.json();
const run = await start(changeAgent, [messages, session.userId]);
return createUIMessageStreamResponse({
stream: run.readable.pipeThrough(createModelCallToUIChunkTransform()),
});
}

Set TOOL_APPROVAL_SECRET to a random value of at least 32 bytes in every environment that runs the workflow. Keep context values such as requesterId serializable, and create database or SDK clients inside the step that uses them. For conditional approval, needsApproval also accepts an async function that decides from the tool's input. needsApproval on a tool definition is specific to WorkflowAgent. For generateText, streamText, and ToolLoopAgent, configure approval with the toolApproval option instead, because needsApproval is deprecated there. Durable agent approval workflows on Vercel covers the approval console, audit trail, and resume flow.

Copy link to headingQuery a private database from an eve tool

eve agents run on Vercel Functions, so a tool in a Secure Compute project reaches a peered database without networking code. Each file in agent/tools/ is one tool, and its filename becomes the tool name the model sees.

import { defineTool } from 'eve/tools';
import { z } from 'zod';
import { Pool } from 'pg';
// Created once and reused across calls
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export default defineTool({
description: 'Run a read-only SQL query against the analytics database and return rows.',
inputSchema: z.object({
sql: z.string().describe('A single read-only SQL SELECT statement.'),
}),
async execute({ sql }) {
const client = await pool.connect();
try {
const { rows } = await client.query(sql);
return { rowCount: rows.length, rows };
} finally {
client.release();
}
},
});

Point DATABASE_URL at a read-only role on the database's private host, with sslmode=require for Postgres. The tool description asks for read-only SQL, but the database role is what enforces it. For data that belongs to individual users or tenants, replace free-form SQL with parameterized queries scoped to the signed-in user, or enforce row-level security in the database.

Copy link to headingOperate a private agent in production

Copy link to headingPin functions and workflow runs near private data sources

Create the Secure Compute network in the region closest to your backend, then deploy your functions to that same region with the regions key in vercel.json:

vercel.json
{
"regions": ["iad1"]
}

Workflows pins each run to the region of the function that started it, and keeps the run's state, queue dispatch, and streams there for the run's lifetime. To keep run data in a specific region, pass the region option to start(). For failover, assign each project environment a passive Secure Compute network in a second region, and Vercel switches to it if the primary region becomes unavailable.

Copy link to headingLog tool calls, inputs, decisions, and failures

Workflows records every step, input, output, sleep, and error, and approvals appear as events in the same run history. View runs in your project's Observability → Workflows page, or run npx workflow inspect runs during local development. After a run completes, its history stays available for 1 day on Hobby, 7 days on Pro, and 30 days on Enterprise. When audits need longer retention, export the history to Vercel Blob as a final workflow step.

Workflow run data can include tool inputs and outputs, so control who reads it. Team owners can read decrypted run data, and you can grant it to other members with the Workflow Run Data Viewer extended permission. eve agents also report sessions, turns, tool calls, and token usage in Agent Runs. Vercel Connect adds an Observability tab per connector that records each token request, and you can forward those events to a SIEM with a Drain on Pro and Enterprise.

Copy link to headingPlan for retries, idempotency, and human approvals

WorkflowAgent retries a failed tool step automatically (3 attempts by default) when its execute function is marked 'use step', which means a mutating internal API can receive the same request more than once. Send an idempotency key derived from stable input, such as the change ID, if your internal API supports one. Otherwise, have the tool check the current state before it writes.

Workflows retries a step only when it throws. A step that returns an error value, such as { applied: false } for a 500 response, counts as a success and doesn't retry. Throw an Error for failures that might succeed on another attempt, such as 5xx responses, and throw FatalError from workflow for failures that won't, such as a 403 or 404.

Use needsApproval: true for actions a person must always review, and an async needsApproval function for actions that need review only above a threshold. While a run waits for approval, no compute bills, and stored run state bills as Workflow Data Retained at $0.50 per GB-month (Workflows pricing).

Copy link to headingTroubleshoot private tool calls

Copy link to headingThe internal API works locally but fails on Vercel

Local development often succeeds because your machine is on a corporate VPN. On Vercel, check each link in the network path:

  1. Confirm the environment is attached. In the project's Settings → Networking page, each environment that calls private systems, such as Production and Preview, needs an Active Network.
  2. Confirm the AWS route table sends traffic for the Vercel network's CIDR block over the peering connection, and that the CIDR blocks don't overlap.
  3. Confirm the target's security group allows its port, such as 5432 for Postgres, from the Vercel network's CIDR block.
  4. Confirm the credentials are set as environment variables for the environment you deployed to.

Copy link to headingTool traffic doesn't use the Secure Compute IPs

Check the runtime first. Code that runs in Routing Middleware or on the edge runtime doesn't use Secure Compute, AWS PrivateLink, or Static IPs, so move private calls into a route or tool on the Node.js runtime. Then confirm the deployment's environment has an active network. Preview deployments use the network assigned to Preview, not the one assigned to Production.

Each connection stays in the pending acceptance state until the provider approves it, unless the endpoint service accepts all principals automatically. Share your team's principal role ARN, shown in the setup dialog, with the provider so it can allowlist that role. If provisioning fails, the endpoint service might not run in at least two Availability Zones that overlap with Vercel's network in that region, so ask the provider to expose it in more zones. Redeploy after the connection becomes available.

Copy link to headingCode in Vercel Sandbox can't reach the private database

This is the expected default, because a sandbox has its own network and doesn't join the project's Secure Compute network. Move the query into a trusted tool and pass the rows to the sandbox. If generated code must connect directly, attach the sandbox with networkId and allow only the database's private IP range in the sandbox firewall.

Copy link to headingThe internal service rejects requests from allowlisted IPs

Confirm the service allowlists the IP pair for the region where your functions run, because each Static IPs region has its own pair. Then check authentication, since IP filtering alone doesn't authorize a request. If the failing traffic is the internal service calling your agent, the outbound IPs don't apply, and the service needs an authenticated Vercel route instead.

Copy link to headingDecide whether Vercel fits your private agent workload

Copy link to headingUse Vercel when the agent is request-driven, web-facing, or workflow-driven

Vercel fits private agents that serve users through a web app, chat surface, or API, and that reach internal systems over HTTP or database drivers. It fits especially well when these conditions hold:

  • The agent, its tools, and its UI are written in TypeScript or Python and deploy together
  • Durability needs are retries, waits, and human approval rather than long-lived processes
  • Internal systems accept outbound connections from a peered network, a VPN, an AWS PrivateLink endpoint service, or an IP allowlist
  • The team wants one deployment target and one identity model for the UI, agent, and tools

Copy link to headingWhat Vercel replaces in a LangGraph, MCP gateway, Temporal, and Kubernetes assembly

Many teams build private agents on a custom stack of several systems that they deploy, secure, and pay for separately. The table maps each concern to the Vercel product that covers it.

ConcernVercelCommon custom assembly
Model accessAI GatewayProvider SDKs or a separately operated model proxy
Agent loopAI SDK, WorkflowAgent, or eveLangGraph
Tool interfaceAI SDK or eve tools, or MCP servers deployed as Vercel FunctionsAn internal MCP gateway
Durable orchestrationWorkflows, with managed persistenceTemporal plus a checkpoint database
Tool executionVercel FunctionsServices on Kubernetes
Private network pathSecure Compute, AWS PrivateLink, or Static IPsSelf-managed VPC, NAT, and IAM
Third-party credentialsVercel ConnectA secrets manager plus custom OAuth handling
Untrusted codeVercel SandboxA separately operated sandbox
UI and approval consoleNext.js in the same projectA separate service and deployment

Copy link to headingWhere MCP and LangGraph can still fit

Model Context Protocol (MCP) is a protocol boundary between an agent and its tools, and you can keep it on Vercel. Deploy an MCP server as a Vercel Function in a Secure Compute project, and its tools reach internal systems privately. The AI SDK and eve can both connect to it as clients, and Vercel Connect can authorize OAuth-protected MCP servers. The execution boundary stays the same, because the MCP server is the trusted code that holds credentials.

If your team already writes agent logic in a framework such as LangGraph, the guidance on tool placement, network paths, and credentials still applies to that code. Compare its durability requirements against Workflows before you add a separate checkpoint store and workflow engine.

Copy link to headingWhen a dedicated engine or self-managed infrastructure is the better choice

Choose a dedicated workflow engine or self-managed stack in these cases:

  • Non-web systems, such as Java services, batch jobs, or Business Process Model and Notation (BPMN) process models, must participate as first-class workflow actors
  • Your organization has a dedicated team that owns Temporal Cloud or a Camunda cluster running the process
  • Policy requires the agent runtime and its orchestration state to run inside your own VPC or on-premises, not only its tool traffic
  • Individual tool steps need to run longer than the 800-second maximum that applies on Secure Compute

For the in-VPC requirement, check Bring Your Own Cloud before you plan a separate stack. This Enterprise option runs your functions inside your own AWS account while Vercel orchestrates routing and invocation. Plan for a substantial setup project, and confirm with your Vercel account team which parts of the agent stack it covers.

These cases often call for integration rather than migration. Vercel-hosted agents can call Temporal or AWS Step Functions as a step, and an external workflow can start a Vercel Workflow through an HTTP endpoint.

Copy link to headingFAQ

Copy link to headingCan an agent on Vercel call an internal API?

Yes. Put the tool code in a Vercel Function, then choose its outbound path. Use Secure Compute for VPC peering and full network isolation, AWS PrivateLink for AWS services that publish an endpoint service, or Static IPs for an IP allowlist. The model requests the call, and your tool validates and executes it.

Copy link to headingDoes Vercel Sandbox inherit Secure Compute or VPC peering?

No. Each sandbox uses its own network and doesn't join the project's Secure Compute network by default. Keep private database and internal API calls in trusted tools, or attach a specific sandbox to the network with networkId and restrict its firewall to the private range it needs.

Copy link to headingDo I need Temporal or Kubernetes for a durable enterprise agent on Vercel?

Most web-facing agents don't need either. Workflows and WorkflowAgent provide durable tool steps, retries, sleeps, hooks, and human approval without an idle container, and run state lives in managed persistence. Mark each tool's execute function with 'use step' to make its calls durable. Dedicated engines still fit when non-web systems must participate as first-class workflow actors.

Copy link to headingWhen should I use Vercel Connect instead of Secure Compute?

Use Vercel Connect when a tool calls a supported third-party API, such as Slack, GitHub, Microsoft, Snowflake, or Salesforce, and needs a short-lived, scoped token. Use Secure Compute, AWS PrivateLink, or Static IPs when the tool reaches infrastructure you run, such as an internal API or database. Many agents use both.

Copy link to headingDo Secure Compute, AWS PrivateLink, and Static IPs give my agent a fixed inbound IP?

No. All three handle outbound traffic only. Internal systems that call your agent use an authenticated Vercel route.

Copy link to headingIs this guide about Vercel Agent?

No. Vercel Agent is the built-in assistant for Vercel projects. This guide covers building your own enterprise agent application on Vercel.

Copy link to headingNext steps

Related documentation

More Vercel Sandbox guides