ViteHub is still experimental. Expect bugs and breaking changes.

Workflows

Start provider-tracked long-running work with run ids, durable state, and optional steps.

Workflows own durable long-running execution. Use them when work needs a Workflow Run, provider-tracked state, retries, resumability, or optional Workflow Steps.

Workflow is not Queue. Queue delivers jobs; Workflow starts and tracks a run.

Quick start

Install

Terminal
pnpm add @vite-hub/workflow

Configure

vite.config.ts
import { hubWorkflow } from '@vite-hub/workflow/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [hubWorkflow()],
})

Start using it

server/workflows/onboard-user.ts
import { defineWorkflow } from '@vite-hub/workflow'

export default defineWorkflow<{ email: string }>(async ({ payload }) => {
  return createUser(payload.email)
})
server/api/onboard.post.ts
import { runWorkflow } from '@vite-hub/workflow'

export default defineEventHandler(async () => {
  return runWorkflow('onboard-user', { email: 'ada@example.com' })
})

Public imports

ImportUse
defineWorkflow from @vite-hub/workflowDeclare a Workflow Definition.
runWorkflow, deferWorkflow, getWorkflowRun from @vite-hub/workflowStart, defer, or inspect Workflow Runs.
createWorkflow from @vite-hub/workflowCreate an inline Workflow Handle for app-owned code.
normalizeWorkflowOptions from @vite-hub/workflowResolve Integration Options to a concrete Workflow Provider.
WorkflowError from @vite-hub/workflowHandle provider and runtime failures.
readRequestPayload, readValidatedPayload, validatePayload from @vite-hub/workflowRead provider request payloads in custom runtime entrypoints.
hubWorkflow from @vite-hub/workflow/viteRegister Workflow discovery and provider output generation.

Workflow Provider, Definition, Run, Step, Start Options, and Integration Options types are exported from @vite-hub/workflow.

Configure the Vite Integration

vite.config.ts
import { hubWorkflow } from '@vite-hub/workflow/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [hubWorkflow()],
})

The Vite config key is workflow.

OptionTypeDefaultDescription
workflow: falsefalseenabledDisables Workflow provider output.
providerWorkflowProviderinferredSelects cloudflare, vercel, or openworkflow.
bindingstringprovider defaultProvider binding name for generated output.
namestringdiscovered workflow nameProvider resource name override.
databasestringnoneOpenWorkflow storage through a ViteHub Named Database.
postgres.urlWorkflowRuntimeConfigValuenoneOpenWorkflow Postgres URL.
postgres.schemastringprovider defaultOpenWorkflow Postgres schema.
postgres.namespaceIdstringprovider defaultOpenWorkflow namespace id.
postgres.runMigrationsbooleanprovider defaultRuns OpenWorkflow storage migrations.
sqlite.pathWorkflowRuntimeConfigValuenoneOpenWorkflow SQLite path.
sqlite.namespaceIdstringprovider defaultOpenWorkflow SQLite namespace id.
sqlite.runMigrationsbooleanprovider defaultRuns OpenWorkflow SQLite migrations.
worker.concurrencynumberprovider defaultOpenWorkflow worker concurrency.

When no provider is configured, ViteHub selects Cloudflare on Cloudflare hosting and Vercel otherwise. On Node or Docker hosting, OpenWorkflow is inferred when OpenWorkflow storage is configured through database, postgres.url, or sqlite.path.

Providers

ProviderConfigure withProvider outputNuance
Cloudflareworkflow: { provider: 'cloudflare' }Cloudflare Workflow class, binding, and runtime entry output.Runs through Cloudflare Workflow bindings. Use binding and name when the generated names must match existing infrastructure.
Vercelworkflow: { provider: 'vercel' }Vercel workflow runtime output under the build output.Persists run state through provider runtime support and Vercel-specific workflow names.
OpenWorkflowworkflow: { provider: 'openworkflow', database/postgres/sqlite }OpenWorkflow worker/runtime output.Requires explicit storage. database, postgres.url, and sqlite.path are mutually exclusive storage choices.

Define a workflow

Create a Workflow Definition for named long-running work.

server/workflows/onboard-user.ts
import { defineWorkflow } from '@vite-hub/workflow'

export default defineWorkflow<{ email: string }>(async ({ payload }) => {
  const user = await createUser(payload.email)
  await sendWelcomeEmail(user.email)

  return { userId: user.id }
})

Use Workflow Steps only when the selected provider and definition need independently retryable or inspectable units.

Workflow Definition options

defineWorkflow(handler, options?) accepts these options. The discovered file name provides the Definition name.

OptionTypeDescription
idstringStatic provider id override for the Workflow Definition.
rootStepbooleanWraps the handler in a root Workflow Step when the provider supports steps.

The handler receives a WorkflowExecutionContext with name, payload, provider, optional run id, and provider-backed step or typed steps helpers when available.

Start a run

Use runWorkflow() from server code.

server/api/onboard.post.ts
import { runWorkflow } from '@vite-hub/workflow'

export default defineEventHandler(async (event) => {
  const body = await readBody<{ email: string }>(event)

  return runWorkflow('onboard-user', body, {
    id: `onboard:${body.email}`,
  })
})

The run id belongs to Invocation Options. Use a stable id when the provider should dedupe or resume the same logical run.

Runtime Helpers

HelperDescription
runWorkflow(name, payload?, options?)Starts a Workflow Run immediately.
deferWorkflow(name, payload?, options?)Starts a run through the deferred provider path when available.
getWorkflowRun(name, id)Reads the current run state.
createWorkflow(name, options?)Returns a handle with run, defer, and getRun.

WorkflowStartOptions currently accepts id.

Workflow Run shape

FieldTypeDescription
idstringProvider or ViteHub Workflow Run id.
providerWorkflowProviderSelected provider for the run.
statusWorkflowRunStatusqueued, running, completed, failed, or unknown.
resultTResultCompleted result when available.
payloadTPayloadOriginal payload when the provider returns it.
metadataunknownProvider metadata.

Inspect a run

Use getWorkflowRun() when server code needs current run state.

server/api/workflows/[id].get.ts
import { getWorkflowRun } from '@vite-hub/workflow'

export default defineEventHandler((event) => {
  return getWorkflowRun('onboard-user', getRouterParam(event, 'id')!)
})

Connect it to Agents

An Agent can start a workflow only when you explicitly expose that behavior through a Capability or server route. Workflow owns durable orchestration; Agent owns model-backed behavior and Agent Invocations.

Use a product-specific Capability when a model should start or inspect a particular Workflow Run.

Production boundaries

Use Queue when background delivery is enough. Use Workflow when the app must inspect run state, resume work, or coordinate multiple steps over time.

Keep credentials and database URLs in Server Env. Hosted workflow providers may require explicit state storage or deployment setup.

Next steps

Copyright © 2026