This reverts commit 3b839446a9.
11 KiB
Agent Instructions
CRITICAL RULES:
- NEVER push directly to the
mainbranch - Do not remove or break agent-discoverable docs sitemap behavior: keep docs/app/sitemap.md/route.ts and docs/app/[lang]/sitemap.md/route.ts, and keep the sitemap link in docs/app/[lang]/llms.mdx/...slug/route.ts.
Overview
Workflow SDK is a durable functions framework for JavaScript/TypeScript that enables writing long-running, stateful application logic on top of stateless compute. The runtime persists progress as an event log and deterministically replays code to reconstruct state after cold starts, failures, or scale events.
This repository contains the client-side SDK code for workflows, along with example apps that showcase Workflow SDK in action.
Architecture
Core Components
- packages/core: Core workflow runtime and primitives (
@workflow/core) - packages/next: Next.js integration (
@workflow/next) - packages/cli: Command-line interface (
@workflow/cli) - packages/world: Core interfaces and types for workflow storage backends (
@workflow/world) - packages/world-local: Filesystem-based workflow backend for local development and testing (
@workflow/world-local) - packages/world-vercel: Production workflow backend for Vercel platform deployments (
@workflow/world-vercel) - packages/swc-plugin-workflow: SWC compiler plugin for workflow transformations
- workbench/example: Basic workflow examples using the CLI (aka "standalone mode")
- workbench/nextjs-turbopack: Workflow examples using the Next.js integration
Workflow Execution Model
Workflows consist of two types of functions:
- Workflow functions (
"use workflow"): Orchestrators that run in a sandboxed VM without full Node.js access - Step functions (
"use step"): Individual pieces of logic with full Node.js runtime access
The framework uses compiler transformations to split workflow files into separate bundles for client, workflow, and step execution contexts.
Development Commands
Workspace-level Commands
# Build all packages
pnpm build
# Run tests across all packages
pnpm test
# Run end-to-end tests
pnpm test:e2e
# Format code with Biome
pnpm format
# Lint with Biome
pnpm lint
# Typecheck TypeScript
pnpm typecheck
# Clean build artifacts
pnpm clean
Core Package Testing
# Test core functionality
cd packages/core && pnpm test
# Test specific file
cd packages/core && pnpm vitest run src/[filename].test.ts
# Run E2E tests (requires environment variables and running dev server)
# Note: Use nextjs-turbopack for local e2e testing (not example app - it has no dev server)
# Step 1: Start the dev server in background
cd workbench/nextjs-turbopack && pnpm dev > /tmp/nextjs-dev.log 2>&1 &
# Step 2: Wait for server to be ready (usually 15-20 seconds)
sleep 15
# Step 3: Run the e2e tests from the project root
DEPLOYMENT_URL="http://localhost:3000" APP_NAME="nextjs-turbopack" pnpm vitest run packages/core/e2e/e2e.test.ts
# Step 4: Stop the dev server when done
pkill -f "pnpm dev"
# To run specific tests, use the -t flag:
DEPLOYMENT_URL="http://localhost:3000" APP_NAME="nextjs-turbopack" pnpm vitest run packages/core/e2e/e2e.test.ts -t "sleeping"
# For running E2E locally against a deployed Vercel preview/production app:
# The test matrix in .github/workflows/tests.yml is the source of truth —
# each app entry defines the project-id / project-slug needed below.
#
# Required environment variables (matches the CI `e2e-vercel-prod` job):
# - DEPLOYMENT_URL: Full URL of the deployed app (e.g. a preview deployment URL)
# - VERCEL_DEPLOYMENT_ID: The dpl_... ID of the deployment (get via `vercel inspect <url>`)
# - APP_NAME: App name (example, nextjs-turbopack, nextjs-webpack, nitro, vite,
# nuxt, sveltekit, hono, express, fastify, astro)
# - WORKFLOW_VERCEL_ENV: "preview" or "production"
# - WORKFLOW_VERCEL_AUTH_TOKEN: Vercel auth token with access to the team
# - WORKFLOW_VERCEL_TEAM: Vercel team ID (CI uses team_nO2mCG4W8IxPIeKoSsqwAxxB for labs)
# - WORKFLOW_VERCEL_PROJECT: Vercel project ID (prj_...) — see test matrix
# - WORKFLOW_VERCEL_PROJECT_SLUG: Vercel project slug — see test matrix
# - VERCEL_OIDC_TOKEN: Short-lived OIDC token used to bypass
# deployment protection via Trusted Sources.
# In CI this is auto-minted from the GitHub
# Actions runner. Locally, run
# `vercel env pull` from any workbench app's
# directory and the resulting `.env.local`
# will contain a `VERCEL_OIDC_TOKEN` value
# that all workbench projects accept (they
# are configured to trust each other under
# `trustedSources.projects`).
#
# Example (nextjs-turbopack preview deployment):
NODE_OPTIONS="--enable-source-maps" \
DEPLOYMENT_URL="https://example-nextjs-workflow-turbopack-<hash>.labs.vercel.dev" \
VERCEL_DEPLOYMENT_ID="dpl_..." \
APP_NAME="nextjs-turbopack" \
WORKFLOW_VERCEL_ENV="preview" \
WORKFLOW_VERCEL_AUTH_TOKEN="<vercel_labs_token>" \
WORKFLOW_VERCEL_TEAM="team_nO2mCG4W8IxPIeKoSsqwAxxB" \
WORKFLOW_VERCEL_PROJECT="prj_yjkM7UdHliv8bfxZ1sMJQf1pMpdi" \
WORKFLOW_VERCEL_PROJECT_SLUG="example-nextjs-workflow-turbopack" \
VERCEL_OIDC_TOKEN="$(grep VERCEL_OIDC_TOKEN workbench/nextjs-turbopack/.env.local | cut -d= -f2-)" \
pnpm run test:e2e
Example App Development
# Build workflow bundles for example app
cd workbench/example && pnpm build
# Use workflow CLI directly
cd workbench/example && pnpm workflow [command]
cd workbench/example && pnpm wf [command] # shorthand
Next.js App Development
# Start Next.js dev server with workflow support
cd workbench/nextjs-turbopack && pnpm dev
# Build Next.js app with workflows
cd workbench/nextjs-turbopack && pnpm build
# Production server
cd workbench/nextjs-turbopack && pnpm start
Key Workflow Concepts
These are only relevant when writing code using the Workflow SDK
- Workflow functions orchestrate step execution but have limited runtime access
- Step functions handle side effects, API calls, and complex logic with full Node.js access
- All function inputs/outputs are serialized to the event log for replay
- Built-in retry semantics for step functions with
FatalError/RetryableErrorcontrols - Standard JavaScript async patterns work:
Promise.all(),Promise.race(), etc.
File Structure Conventions
These are only relevant when writing code using the Workflow SDK
- Workflow files go in
workflows/directory (orsrc/workflows/if using src) - Generated API routes appear in
app/.well-known/workflow/v1/(Next.js integration) - Workflow files must contain
"use workflow"or"use step"directives to be processed - Add
.swcdirectory to.gitignorefor SWC plugin cache artifacts
Package Manager
This project uses pnpm with workspace configuration. The required version is specified in package.json#packageManager.
Code Style
- Uses Biome for formatting and linting
- 2-space indentation, single quotes, trailing commas (ES5)
- Import type enforcement enabled
- Explicit
anyis discouraged (Biome'snoExplicitAnyrule is currently disabled); exhaustive dependencies warnings enabled
Documentation Standards
- README.md files in each package must accurately reflect the current functionality and purpose of that package
- READMEs should not contain outdated or incorrect information about package capabilities
- When modifying package functionality, ensure corresponding README updates are included
- When modifying skill files in
skills/, always bump theversionfield in the frontmatter metadata
Docs Preview Links in PR Descriptions
When a PR adds or updates docs pages (anything under docs/content/), add a "Docs Preview" section to the PR description with direct links to each changed page on the workflow-docs preview deployment:
- Get the preview base URL from the
vercel[bot]comment on the PR — use the Preview link from theworkflow-docsproject row (e.g.https://workflow-docs-git-<branch-slug>.vercel.sh). Don't construct the URL by hand; Vercel's branch-slug normalization is not a simple substitution. - Map content paths to routes:
docs/content/docs/v4/<path>.mdxis served at/docs/<path>(v4 is the default/latest version) anddocs/content/docs/v5/<path>.mdxat/v5/docs/<path>. - When a change is scoped to a specific section of a page, link to its heading anchor (e.g.
/docs/foundations/hooks#checking-for-token-conflicts) and verify the anchor matches a real heading in the MDX. - A simple table with one row per page (and one column per docs version, when both v4 and v5 were updated) works well.
- The preview deployment sits behind deployment protection, so the links require Vercel team access — that's expected; include them anyway for reviewers.
SWC Plugin
When modifying the SWC compiler plugin (packages/swc-plugin-workflow), you must also update the specification document at packages/swc-plugin-workflow/spec.md to reflect any changes to the transformation behavior.
Changesets
workflowand@workflow/coreuse changesets' "fixed" versioning strategy - they always have the same version number- Every PR requires a changeset to be included before it will be merged
- To check if one is needed, run
pnpm changeset status --since=main >/dev/null 2>&1 && echo "no changeset needed" || echo "changeset needed" - Create a changeset using
pnpm changeset add- All changed packages should be included in the changeset. Never include unchanged packages.
- Use the appropriate semver bump: "patch" for bug fixes, "minor" for new features, "major" for breaking changes.
- Remember to always build any packages that get changed before running downstream tests like e2e tests in the workbench
- Remember that changes made to one workbench should propagate to all other workbenches. The workflows should typically only be written once inside the example workbench and symlinked into all the other workbenches
- When writing changesets, use the
pnpm changesetcommand from the root of the repo. Keep the changesets terse (see existing changesets for examples). Try to make changesets that are specific to each modified package so they are targeted. Ensure that any breaking changes are marked as "BREAKING CHANGE"
Common Patterns
Build-time Version Injection
Use genversion to access package version at runtime. See @workflow/core and @workflow/world-vercel for examples:
- Add
genversionas devDependency - Update build script:
genversion --es6 src/version.ts && tsc - Add
src/version.tsto.gitignoreandturbo.jsonoutputs
Turbo Caching for Generated Files
When a build step generates files, add them to the package's turbo.json outputs array to ensure proper caching.
Architecture Notes
executionContext Field
The executionContext field on workflow runs is a flexible JSONB/CBOR object that can store arbitrary data without schema changes. It flows through all worlds (local, postgres, vercel).
Observability Data Hydration
packages/core/src/observability.ts contains hydrateResourceIO which strips certain fields (like executionContext) before UI display. If you need to display data from stripped fields, extract it before the stripping occurs.