---
title: Durable agent approval workflows on Vercel
description: How enterprise architects choose a stack and decide where to run durable, human-in-the-loop agent approval workflows on Vercel.
url: /kb/guide/agent-approval-workflow-stack-guide
canonical_url: "https://vercel.com/kb/guide/agent-approval-workflow-stack-guide"
last_updated: 2026-07-29
authors: Vercel
related:
  - /blog/agent-stack
  - /docs/workflows
  - /kb/guide/what-is-workflowagent
  - /docs/ai-gateway
  - /docs/functions
  - /docs/vercel-blob
  - /docs/networking/secure-compute
  - /docs/networking/static-ips
  - /docs/fluid-compute
  - /docs/workflows/pricing
  - /docs/saml
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

Agent approval workflows sit in an awkward middle ground. A single run can span seconds of model inference, hours of human review, and days of downstream side effects. Through all of it the agent has to remember where it was, retry safely, produce a report a reviewer can trust, and enforce access controls on internal data.

That shape breaks the assumptions the usual tools are built on. A request and response function expects to start, finish, and forget within one invocation. Agent frameworks expect in-memory state and a long-lived process. An approval run stops mid-thought for days and has to come back knowing everything it knew.

The standard workaround is assembly: keep the agent loop in a framework like LangGraph, add Temporal as the durability engine, and stand up Postgres or Redis to hold the checkpoints. It works, and every seam becomes something the team builds, secures, and pays for before the first approval flow ships.

The [Agent Stack](https://vercel.com/blog/agent-stack) collapses that assembly into one platform. An approval workflow runs on [Vercel Workflows](https://vercel.com/docs/workflows) for orchestration, [WorkflowAgent](https://vercel.com/kb/guide/what-is-workflowagent) for the agent loop, [AI Gateway](https://vercel.com/docs/ai-gateway) for model calls, [Vercel Functions](https://vercel.com/docs/functions) for tool execution, and [Vercel Blob](https://vercel.com/docs/vercel-blob) for generated reports, with [Secure Compute](https://vercel.com/docs/networking/secure-compute) or [Static IPs](https://vercel.com/docs/networking/static-ips) reaching internal APIs inside a private network.

## Contents

- [What an approval workflow needs, and what runs each part](#the-six-parts-of-an-approval-workflow)
  
- [How to gate a tool call on human approval](#gate-a-tool-call-on-human-approval)
  
- [How a run holds state through days of waiting](#durable-state-without-persistent-containers)
  
- [What you operate in production, and what a waiting run costs](#where-the-workflow-runs-in-production)
  
- [How steps reach APIs inside a private VPC](#reaching-private-apis-from-a-public-workflow)
  
- [How to answer who approved what, and when](#who-approved-what-and-when)
  
- [Where generated reports live](#generated-reports-as-first-class-artifacts)
  
- [When Temporal, Step Functions, or Camunda is still the right call](#when-vercel-workflows-replaces-temporal-step-functions-or-camunda)
  

## The six parts of an approval workflow

A production approval workflow has six moving parts, whatever it runs on.

| **Moving part**               | **What it needs**                                                                       | **On Vercel**                                                                                                                                                                                                                                                                                                |
| ----------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Approval console              | A queue, the proposed change, approve and reject actions, live status of in-flight runs | A Next.js app in the same project                                                                                                                                                                                                                                                                            |
| Workflow runtime              | Suspend on approval or sleep, resume on demand, no container idling between             | [Vercel Workflows](https://vercel.com/docs/workflows)                                                                                                                                                                                                                                                        |
| Agent loop                    | Tool calls that checkpoint, retry, and resume                                           | [WorkflowAgent](https://vercel.com/kb/guide/what-is-workflowagent) from `@ai-sdk/workflow`                                                                                                                                                                                                                   |
| Tool execution                | Compute that bills nothing between steps, with a path to internal APIs                  | [Vercel Functions](https://vercel.com/docs/functions) on [Fluid compute](https://vercel.com/docs/fluid-compute); [Secure Compute](https://vercel.com/docs/networking/secure-compute) on Enterprise or [Static IPs](https://vercel.com/docs/networking/static-ips) on Pro and Enterprise for private networks |
| Artifacts and reports         | Durable object storage under the same auth as the app                                   | [Vercel Blob](https://vercel.com/docs/vercel-blob), or an external store                                                                                                                                                                                                                                     |
| Model calls and notifications | One endpoint for many models, and a route to where reviewers already work               | [AI Gateway](https://vercel.com/docs/ai-gateway); [Chat SDK](https://chat-sdk.dev/) for Slack or Teams, `createWebhook` and `createHook` for custom surfaces                                                                                                                                                 |

_The middle column is the requirement; the right column is where it lands in one Vercel project._

## Gate a tool call on human approval

The distinctive requirement of an approval workflow is a tool that reaches an internal API and then waits for a person before it acts. WorkflowAgent expresses both in one tool definition. A tool built with `tool()` from `ai` runs as a durable `'use step'`, retries on failure from the last checkpoint, and, when marked `needsApproval: true`, suspends the agent until a user responds hours or days later.

Install the packages with `npm install @ai-sdk/workflow workflow`. The `@ai-sdk/workflow` package requires `ai` and `zod` as peer dependencies, and the `workflow` package provides the runtime.

``import { WorkflowAgent } from '@ai-sdk/workflow' import { tool } from 'ai' import { z } from 'zod' const applyChange = tool({ description: 'Apply an agent-proposed change through the internal change API', inputSchema: z.object({ changeId: z.string() }), needsApproval: true, // suspends the run until a reviewer responds execute: async ({ changeId }) => { 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', }, }) return { applied: res.ok, status: res.status } }, }) export const agent = new WorkflowAgent({ model: 'anthropic/claude-sonnet-4-6', tools: { applyChange }, })``

_A WorkflowAgent tool that calls an internal API and suspends until a reviewer approves_

Each call to `applyChange` runs as a discrete durable step and [retries up to three times by default](https://workflow-sdk.dev/docs/foundations/errors-and-retries). For conditional gating, `needsApproval` also accepts an async function that decides per call from the tool's input. [What is WorkflowAgent?](https://vercel.com/kb/guide/what-is-workflowagent) covers the suspend and resume mechanics, and the [AI SDK WorkflowAgent reference](https://ai-sdk.dev/docs/agents/workflow-agent) covers tool definitions and model resolution.

## Durable state without persistent containers

A run may wait 48 hours for a reviewer, then resume, then wait again. Holding that state in memory means holding a container open, which is what pushes teams onto Temporal or Kubernetes.

Vercel Workflows removes the container. A workflow suspends on any of three primitives and resumes when the signal arrives:

- [`**sleep**`](https://workflow-sdk.dev/docs/api-reference/workflow/sleep)**:** pause for minutes to months, with no upper limit on duration
  
- [`**createWebhook**`](https://workflow-sdk.dev/docs/foundations/hooks)**:** wait for an HTTP call from an external system
  
- [`**createHook**`](https://workflow-sdk.dev/docs/foundations/hooks)**:** wait for a typed in-app event, such as an approval decision
  

The runtime reconstructs the run's state when the resume signal arrives. WorkflowAgent extends the same guarantee to the agent loop itself, so a suspended tool call resumes with the exact message history, tool outputs, and pending decisions it had before. Context values cross workflow and step boundaries, so keep them [serializable](https://workflow-sdk.dev/docs/foundations/serialization) and recreate non-serializable resources like database clients inside the step function that uses them.

## Where the workflow runs in production

In production the question shifts from what to build to what you operate. On Vercel the answer is a single project, and the platform holds the state.

- **Orchestration state:** the durable state of every run, its message history, pending approvals, and step checkpoints, is held by the Workflows runtime in managed persistence. There is no checkpoint database to provision or operate, and no container is held open for a run while it waits for a reviewer.
  
- **Tool execution:** each `'use step'` runs as a function invocation on [Fluid compute](https://vercel.com/docs/fluid-compute). Steps that call an internal API send their outbound traffic through Secure Compute or Static IPs into the private network.
  
- **The approval console:** the Next.js UI, the workflow, and the tools deploy together, share one identity model, and read the same environment variables. Resuming a run is an authenticated route in the same app.
  

Three tradeoffs come with that choice:

- **Generality for one surface:** Vercel Workflows targets web tooling, model tool calls, and human review. Coordinating Java services or Business Process Model and Notation (BPMN) models as first-class actors belongs in a dedicated engine, covered in the [comparison below](https://file+.vscode-resource.vscode-cdn.net/Users/kev/development/draft0/projects/shared/article/agent-approval-workflow-stack-guide/04-drafts/draft-v3.md#when-vercel-workflows-replaces-temporal-step-functions-or-camunda).
  
- **Cost while waiting:** while a step runs, Fluid compute bills [Active CPU](https://vercel.com/docs/fluid-compute); while a run is suspended, nothing executes and no compute bills. Stored run state bills separately as Workflow Data Retained, alongside Events and Data Written ([Workflows pricing](https://vercel.com/docs/workflows/pricing)). A multi-day approval costs storage cents, and an always-on container costs the container.
  
- **Egress only:** Secure Compute and Static IPs provide fixed outbound IPs into private networks and no fixed inbound IPs. An approval callback that must originate from a known source uses those egress IPs; an inbound trigger from an internal caller lands on an authenticated Vercel route.
  

## Reaching private APIs from a public workflow

The most common enterprise objection is that the internal tools live in a private VPC, so the workflow must run there too. Two separate concerns hide in that objection. Tool calls need a network path into the VPC, and orchestration state needs a home. Outbound connectivity from Vercel Functions covers the first while the state stays in the Workflows runtime. The workflow does not need to run inside your VPC for its steps to reach services inside it.

Two features provide that outbound path, and they differ in isolation and plan.

- [**Vercel Secure Compute**](https://vercel.com/docs/networking/secure-compute)**:** creates a dedicated private network inside a VPC with static IPs that do not change, a NAT Gateway, and VPC peering to your backend. Each customer gets a dedicated VPC and subnet, and each network reports its dedicated IP pair, AWS account ID, region, VPC ID, and CIDR block. You can include or exclude the build container from the network. Network creation is self-service from team Settings → Networking, though it is not available to all Enterprise teams, and teams without it contact their Vercel account team. Secure Compute is an Enterprise plan feature, and projects using it do not support the extended max duration beta, which caps the longest individual tool steps.
  
- [**Static IPs**](https://vercel.com/docs/networking/static-ips)**:** provides static egress IPs from a shared VPC with subnet-level isolation, available on Pro and Enterprise at $100.00 per month per project plus Private Data Transfer at regional rates. It is egress only and does not provide fixed inbound IPs. If a project uses Secure Compute, Static IPs are ignored.
  

Choose Secure Compute when you need dedicated infrastructure, VPC peering, or complete network isolation, which is the common enterprise case for reaching internal systems. Choose Static IPs when a shared egress pool behind an IP allowlist is enough. In both cases the direction is outbound, so an approval callback that must originate from a known source uses these IPs, while an inbound trigger from an internal caller uses an authenticated Vercel route.

## Who approved what, and when

Any approval system has to answer who approved what, when, and with which inputs. The Vercel stack answers it from the workflow itself, without a separate logging pipeline.

Every tool call appears as a discrete step in the [workflow dashboard](https://vercel.com/docs/workflows#observability) with its inputs, outputs, retries, and timing. Approvals are recorded as workflow events, so the decision that resumed a suspended run is part of the same durable history as the tool call it gated. During local development, `npx workflow inspect runs` reads the same history from the terminal. Access to the history sits behind team controls, including [SAML SSO](https://vercel.com/docs/saml), role-based access, audit logs, and encrypted environment variables.

Run history is retained after completion for 1 day on Hobby, 7 days on Pro, and 30 days on Enterprise, with custom periods available through support ([storage retention](https://vercel.com/docs/workflows/pricing)). For audits that outlive retention, export the run's history to [Vercel Blob](https://vercel.com/docs/vercel-blob) as a final workflow step. The exported history joins the generated report in storage, and together they form an audit bundle that lasts as long as the auditor needs.

## Generated reports as first-class artifacts

Reports are part of the workflow's contract with the reviewer. The path from generation to the reviewer's screen:

1. **Generate inside a** `**'use step'**`**:** the work is checkpointed and retried like any other step.
   
2. **Store through the** [`**@vercel/blob**`](https://vercel.com/docs/vercel-blob) [**SDK**](https://vercel.com/docs/vercel-blob)**:** the store lives under the same auth and environment model as the rest of the project, with storage backed by Amazon S3 for durability. Derive the object key from stable identifiers of the run and step rather than a timestamp, and set `allowOverwrite: true` so a retried step writes the same key instead of failing. When data residency, existing lifecycle policies, or cross-cloud requirements dictate an external store, the step writes to S3, GCS, or Azure Blob Storage instead.
   
3. **Link from the approval console:** the reviewer reads the report and records the decision against the same run.
   

Stored next to the exported run history, the report completes the audit bundle.

## When Vercel Workflows replaces Temporal, Step Functions, or Camunda

Vercel Workflows covers the same approval-flow ground as Temporal, AWS Step Functions, and Camunda when the flow is built from web tooling, LLM tool calls, and human review. Feature-by-feature comparisons live in the Workflow SDK docs for [Temporal](https://workflow-sdk.dev/docs/comparisons/workflow-sdk-vs-temporal) and [Step Functions](https://workflow-sdk.dev/docs/comparisons/workflow-sdk-vs-aws-step-functions). Choose Vercel Workflows when:

- The workflow is expressed in TypeScript alongside the UI that triggers it
  
- Durability, retries, sleep, and human approval primitives are the core requirements
  
- The team wants one deployment target for UI, workflow, and tools
  
- Approvals resume through webhooks, chat surfaces, or authenticated app routes
  

Choose Temporal, Step Functions, or Camunda when:

- Non-web systems like Java services, batch jobs, or BPMN process models need to participate as first-class workflow actors
  
- A dedicated workflow engineering team already owns Temporal Cloud or a Camunda cluster
  
- Regulatory or contractual requirements pin orchestration to a specific vendor or on-premise deployment
  

Vercel does not replace every workload. When one of the conditions above holds, integrate rather than migrate. A Vercel-hosted agent can call into Temporal or Step Functions as a step, and a Temporal workflow can trigger a Vercel Workflow through an HTTP endpoint. The boundary belongs at the systems that already own the process.

## How the stack compares to LangGraph plus Temporal plus S3

A common assembly for the same problem uses LangGraph for agent orchestration, Temporal for durability, Postgres or Redis for LangGraph checkpoints, S3 for artifacts, and a separate Next.js or FastAPI service for the UI. That stack works, but each seam becomes something the team owns.

| **Concern**                 | **Vercel stack**                                                                                                                   | **LangGraph plus Temporal plus S3**          |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| Orchestration               | [Vercel Workflows](https://vercel.com/docs/workflows)                                                                              | Temporal                                     |
| Agent loop                  | [WorkflowAgent](https://vercel.com/kb/guide/what-is-workflowagent) (`@ai-sdk/workflow`)                                            | LangGraph                                    |
| Durability                  | Built into Workflows                                                                                                               | Temporal plus Postgres or Redis checkpoints  |
| Approval primitives         | `needsApproval`, `createWebhook`, `createHook`, `sleep`                                                                            | Custom, built on Temporal signals            |
| Artifact and report storage | [Vercel Blob](https://vercel.com/docs/vercel-blob) or external object store                                                        | S3 or equivalent, wired separately           |
| Internal API access         | [Secure Compute](https://vercel.com/docs/networking/secure-compute) or [Static IPs](https://vercel.com/docs/networking/static-ips) | Self-managed VPC, NAT, and IAM               |
| Audit trail                 | Workflow run history in the dashboard, exportable to Blob                                                                          | Assembled from Temporal history and app logs |
| UI layer                    | Next.js on Vercel, same project                                                                                                    | Separate service and deployment              |
| Enterprise controls         | SAML SSO, audit logs, encrypted env vars                                                                                           | Assembled per component                      |

_One column is a project; the other is a portfolio of systems the team assembles, secures, and pays for separately._

The Vercel stack trades some orchestration generality for one deployment surface and built-in approval primitives. The LangGraph assembly trades operational weight for flexibility across non-web runtimes.

## FAQ

**Does a run cost anything while it waits for approval?** No compute. Functions bill [Active CPU](https://vercel.com/docs/fluid-compute) only while a step executes, and a suspended run executes nothing. Stored run state bills as Workflow Data Retained at $0.50 per GB-month ([Workflows pricing](https://vercel.com/docs/workflows/pricing)).

**Can workflow steps reach APIs inside a private VPC?** Yes. Steps on Vercel Functions route outbound traffic through [Secure Compute](https://vercel.com/docs/networking/secure-compute) on Enterprise or [Static IPs](https://vercel.com/docs/networking/static-ips) on Pro and Enterprise, while orchestration state stays in the Workflows runtime. Both paths are egress only.

**How long is workflow run history retained?** After a run completes: 1 day on Hobby, 7 days on Pro, 30 days on Enterprise, with custom periods available through support. For longer audit windows, export the history to [Vercel Blob](https://vercel.com/docs/vercel-blob) as a final step.

**Can the workflow coordinate with an existing Temporal or Step Functions deployment?** Yes. A Vercel-hosted agent can call either system as a step, and an external workflow can trigger a Vercel Workflow through an HTTP endpoint. Integrate at the boundary of the system that already owns the process.

## Next steps

- [Vercel Workflows documentation](https://vercel.com/docs/workflows): runtime behavior, observability, pricing, and limits
  
- [Workflow SDK reference](https://workflow-sdk.dev/docs): `'use workflow'`, `'use step'`, `createWebhook`, and `createHook`
  
- [What is WorkflowAgent?](https://vercel.com/kb/guide/what-is-workflowagent): the durable agent loop, retries, and `needsApproval` suspension
  
- [WorkflowAgent in the AI SDK](https://ai-sdk.dev/docs/agents/workflow-agent): tool definitions, conditional approval, and model resolution
  
- [Secure Compute](https://vercel.com/docs/networking/secure-compute) and [Static IPs](https://vercel.com/docs/networking/static-ips): outbound paths into a private network
  
- [Vercel Blob](https://vercel.com/docs/vercel-blob): report and artifact storage, conditional writes, and access modes