### Global Setup Script for Dev Server Source: https://workflow-sdk.dev/v5/docs/testing/server-based Use this script to start a dev server before tests and tear it down afterwards. It logs server events and sets the WORKFLOW_LOCAL_BASE_URL environment variable. Ensure the server starts within 15 seconds or the setup will fail. ```typescript import { spawn } from "node:child_process"; import { setTimeout as delay } from "node:timers/promises"; import type { ChildProcess } from "node:child_process"; let server: ChildProcess | null = null; const PORT = "4000"; function emitSetupLog(event: string, fields: Record = {}) { console.log( JSON.stringify({ scope: "workflow-server-test", event, port: PORT, ...fields, }) ); } export async function setup() { const stdout: string[] = []; const stderr: string[] = []; emitSetupLog("server_starting", { command: `npx nitro dev --port ${PORT}`, }); server = spawn("npx", ["nitro", "dev", "--port", PORT], { stdio: "pipe", detached: false, env: process.env, }); const ready = await new Promise((resolve) => { const timeout = setTimeout(() => resolve(false), 15_000); server?.stdout?.on("data", (data) => { const output = data.toString(); stdout.push(output); emitSetupLog("server_stdout", { message: output.trim() }); if (output.includes("listening") || output.includes("ready")) { clearTimeout(timeout); resolve(true); } }); server?.stderr?.on("data", (data) => { const output = data.toString(); stderr.push(output); emitSetupLog("server_stderr", { message: output.trim() }); }); server?.on("error", (error) => { emitSetupLog("server_process_error", { name: error.name, message: error.message, }); clearTimeout(timeout); resolve(false); }); server?.on("exit", (code, signal) => { emitSetupLog("server_exit", { code, signal }); }); }); if (!ready) { const recentStdout = stdout.join("").trim().slice(-2000); const recentStderr = stderr.join("").trim().slice(-2000); throw new Error( [ "Server failed to start within 15 seconds.", `Command: npx nitro dev --port ${PORT}`, `WORKFLOW_LOCAL_BASE_URL: http://localhost:${PORT}`, `Recent stdout:\n${recentStdout || "(empty)"}`, `Recent stderr:\n${recentStderr || "(empty)"}`, ].join("\n\n") ); } await delay(2_000); process.env.WORKFLOW_LOCAL_BASE_URL = `http://localhost:${PORT}`; emitSetupLog("server_ready", { baseUrl: process.env.WORKFLOW_LOCAL_BASE_URL, }); } export async function teardown() { if (!server) return; emitSetupLog("server_stopping"); server.kill("SIGTERM"); await delay(1_000); if (!server.killed) { emitSetupLog("server_force_kill"); server.kill("SIGKILL"); } } ``` -------------------------------- ### Clone Flight Booking App Example Source: https://workflow-sdk.dev/v5/docs/ai Clone the example application repository to start with a pre-built chat interface and API route. This is useful for following along with the integration steps. ```bash git clone https://github.com/vercel/workflow-examples -b plain-ai-sdk cd workflow-examples/flight-booking-app ``` -------------------------------- ### Install Workflow SDK, Fastify, and Nitro Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify Install the necessary packages for your Fastify project to use the Workflow SDK and Nitro. This is the initial setup step. ```bash npm install workflow fastify nitro # or yarn add workflow fastify nitro ``` -------------------------------- ### Hono Project Setup: Install Dependencies Source: https://workflow-sdk.dev/v5/docs/getting-started/hono Install the necessary packages for your Hono project: workflow, nitro, and rollup. ```bash npm install workflow nitro rollup ``` -------------------------------- ### Install and Run Workflow CLI Source: https://workflow-sdk.dev/v5/docs/observability Installs and runs the Workflow CLI. If the package is not installed, npx will download and run it temporarily. ```bash npx workflow ``` -------------------------------- ### Server-Based Workflow Testing Example Source: https://workflow-sdk.dev/v5/docs/testing/server-based Demonstrates testing workflow execution using programmatic APIs in a server-based environment. Use start() to initiate a workflow and resumeHook() to interact with hooks. Ensure workflow state is reached before proceeding, potentially with delays or polling. ```typescript import { describe, it, expect } from "vitest"; import { start, getRun, resumeHook } from "workflow/api"; import { calculateWorkflow } from "./calculate"; import { approvalWorkflow } from "./approval"; describe("calculateWorkflow", () => { it("should compute the correct result", async () => { const run = await start(calculateWorkflow, [2, 7]); const result = await run.returnValue; expect(result).toEqual({ sum: 9, product: 14, combined: 23, }); }); }); describe("approvalWorkflow", () => { it("should publish when approved", async () => { const run = await start(approvalWorkflow, ["doc-1"]); // Use resumeHook and wakeUp to control workflow execution await resumeHook("approval:doc-1", { approved: true, reviewer: "alice", }); await getRun(run.runId).wakeUp(); const result = await run.returnValue; expect(result).toEqual({ status: "published", reviewer: "alice", }); }); }); ``` -------------------------------- ### Bun Integration: Server Setup Source: https://workflow-sdk.dev/v5/docs/how-it-works/framework-integrations Configure your Bun server to expose HTTP endpoints for workflow execution, step handling, webhooks, and starting workflows. ```typescript import flow from "./.well-known/workflow/v1/flow.js"; import step from "./.well-known/workflow/v1/step.js"; import * as webhook from "./.well-known/workflow/v1/webhook.js"; import { start } from "workflow/api"; import { handleUserSignup } from "./workflows/user-signup.js"; const server = Bun.serve({ port: process.env.PORT, routes: { "/.well-known/workflow/v1/flow": { POST: (req) => flow.POST(req), }, "/.well-known/workflow/v1/step": { POST: (req) => step.POST(req), }, // webhook exports handlers for GET, POST, DELETE, etc. "/.well-known/workflow/v1/webhook/:token": webhook, // Example: Start a workflow "/": { GET: async (req) => { const email = `test-${crypto.randomUUID()}@test.com`; const run = await start(handleUserSignup, [email]); return Response.json({ message: "User signup workflow started", runId: run.runId, }); }, }, }, }); console.log(`Server listening on http://localhost:${server.port}`); ``` -------------------------------- ### start Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-runtime Start and enqueue a new workflow run. ```APIDOC ## start ### Description Start and enqueue a new workflow run. ``` -------------------------------- ### Start Astro Development Server Source: https://workflow-sdk.dev/v5/docs/getting-started/astro Run this command in your terminal to start the Astro development server. ```bash npm run dev ``` -------------------------------- ### Passing Wrapper Function to start() Source: https://workflow-sdk.dev/v5/docs/errors/start-invalid-workflow-function This example demonstrates passing a wrapper function to `start()`, which is incorrect. The fix is to pass the imported workflow function directly and provide arguments separately. ```typescript import { start } from "workflow/api"; import { sendReminder } from "./workflows/send-reminder"; export async function POST() { // Does NOT work await start(async () => sendReminder("hello@example.com")); return new Response("ok"); } ``` ```typescript import { start } from "workflow/api"; import { sendReminder } from "./workflows/send-reminder"; export async function POST() { await start(sendReminder, ["hello@example.com"]); return new Response("ok"); } ``` -------------------------------- ### Install Migration Skill Source: https://workflow-sdk.dev/v5/docs/migration-guides Install the Workflow SDK migration skill using npx to facilitate the migration process. ```bash npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdk ``` -------------------------------- ### Install Workflow SDK Source: https://workflow-sdk.dev/v5/docs/migration-guides/migrating-from-inngest Install the Workflow SDK using pnpm. Framework integrations are available as subpath exports of the same package. ```bash pnpm add workflow ``` -------------------------------- ### start() Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-api Start/enqueue a new workflow run. ```APIDOC ## start() ### Description Start/enqueue a new workflow run. ### Method Not specified (likely a function call within the SDK) ### Endpoint Not applicable (SDK function) ### Parameters None explicitly documented. ### Request Example ```javascript // Example usage within the SDK await workflow.api.start({ name: "my-workflow", payload: { /* ... */ } }); ``` ### Response None explicitly documented. ``` -------------------------------- ### Start Workflow with StartOptions Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-api/start Starts a workflow with custom deployment ID and attributes. Useful for targeting specific deployments or adding metadata. ```typescript import { start } from "workflow/api"; import { myWorkflow } from "./workflows/my-workflow"; const run = await start(myWorkflow, ["arg1", "arg2"], { deploymentId: "custom-deployment-id", attributes: { source: "checkout" } }); ``` -------------------------------- ### Resume or Start Pattern Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-api/resume-hook Demonstrates the 'resume or start' pattern using `resumeHook` and `start`. It attempts to resume an existing hook and falls back to starting a new workflow run if the hook is not found. ```APIDOC ## POST /api/resume-or-start-workflow ### Description Implements a 'resume or start' pattern. It first attempts to resume an active workflow run using `resumeHook`. If the hook is not found (indicating no active run for the token), it starts a new workflow run using `start` and then retries resuming to ensure the payload is delivered. ### Method POST ### Endpoint `/api/resume-or-start-workflow` ### Parameters #### Request Body - **orderId** (string) - Required - Identifier for the order, used to construct the hook token. - **confirmed** (boolean) - Required - Confirmation status for the order. ### Response #### Success Response (200) - **runId** (string) - The ID of the workflow run (either resumed or newly started). - **reused** (boolean) - Indicates if an existing run was resumed (`true`) or a new one was started (`false`). ### Errors - Throws an error if the workflow does not register its hook within a reasonable time after starting. ``` -------------------------------- ### Starting a Workflow Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-api/start The `start` function allows you to initiate a workflow run. It supports multiple signatures depending on how you want to pass arguments and specify options. ```APIDOC ## Start Workflow ### Description Initiates a workflow run with specified arguments and options. ### Signatures #### Signature 1 ```typescript start( workflow: WorkflowFunction | WorkflowMetadata, args?: unknown[], options?: StartOptionsWithDeploymentId ): Promise> ``` #### Signature 2 ```typescript start( workflow: WorkflowMetadata, options?: StartOptionsWithDeploymentId ): Promise> ``` #### Signature 3 ```typescript start( workflow: WorkflowFunction | WorkflowMetadata, args: TArgs, options?: StartOptionsWithoutDeploymentId ): Promise> ``` #### Signature 4 ```typescript start( workflow: WorkflowMetadata, options?: StartOptionsWithoutDeploymentId ): Promise> ``` ### Parameters #### `workflow` - Type: `WorkflowFunction` or `WorkflowMetadata` - Description: The imported workflow function or its metadata to start. #### `args` - Type: `unknown[]` or `TArgs` (optional) - Description: The arguments to pass to the workflow. The type depends on the signature used. #### `options` - Type: `StartOptionsWithDeploymentId` or `StartOptionsWithoutDeploymentId` (optional) - Description: Configuration options for the workflow run. ### `StartOptions` #### `deploymentId` - Type: ` ``` ```APIDOC string & {} | undefined` - Description: The deployment ID to use. Defaults to inferring from environment variables. Can be set to `'latest'` to use the most recent deployment. #### `world` - Type: `World` - Description: The world to use for the workflow run. Defaults to inferring from environment variables. #### `specVersion` - Type: `number` - Description: The spec version to use. Defaults to the latest version. #### `attributes` - Type: `Record` - Description: Plaintext attributes to seed on the run. Available for spec version 4 and later. #### `allowReservedAttributes` - Type: `boolean` - Description: Permits reserved `$`-prefixed keys in `attributes`. Use with caution. ### Returns - Type: `Run` - Description: An object representing the workflow run, providing methods to manage and query its status and results. ### `Run` Object Properties - `runId`: `string` - The ID of the workflow run. - `wakeUp`: `(options?: StopSleepOptions | undefined) => Promise` - Interrupts pending `sleep()` calls. - `cancel`: `() => Promise` - Cancels the workflow run. - `exists`: `Promise` - Checks if the workflow run exists. - `status`: `Promise<"pending" | "running" | "completed" | "failed" | "cancelled">` - The current status of the workflow run. - `returnValue`: `Promise` - The return value of the workflow run. - `workflowName`: `Promise` - The name of the workflow. - `createdAt`: `Promise` - The timestamp when the workflow run was created. - `startedAt`: `Promise` - The timestamp when the workflow run started execution. - `completedAt`: `Promise` - The timestamp when the workflow run completed. - `readable`: `WorkflowReadableStream` - The readable stream of the workflow run. - `getReadable`: `(options?: WorkflowReadableStreamOptions | undefined) => WorkflowReadableStream` - Retrieves the workflow run's default readable stream. ``` -------------------------------- ### Writing an Integration Test for a Workflow Source: https://workflow-sdk.dev/v5/docs/testing This example demonstrates how to trigger a workflow using `start()` and assert its return value and status. The `run.returnValue` promise blocks until the workflow completes, providing a way to test workflow logic end-to-end. ```typescript import { describe, it, expect } from "vitest"; import { start } from "workflow/api"; import { calculateWorkflow } from "./calculate"; describe("calculateWorkflow", () => { it("should compute the correct result", async () => { const run = await start(calculateWorkflow, [2, 7]); expect(run.runId).toMatch(/^wrun_/); // Blocks until the workflow completes or fails const result = await run.returnValue; expect(result).toEqual({ sum: 9, product: 14, combined: 23, }); const status = await run.status; expect(status).toEqual("completed"); }); }); ``` -------------------------------- ### Example Workflow Steps Source: https://workflow-sdk.dev/v5/docs/testing Defines example step functions for a user signup workflow, including creating a user, sending emails, and using the sleep function. These steps can be unit tested directly. ```typescript import { sleep } from "workflow"; export async function handleUserSignup(email: string) { "use workflow"; const user = await createUser(email); await sendWelcomeEmail(user); await sleep("5d"); await sendOnboardingEmail(user); return { userId: user.id, status: "onboarded" }; } export async function createUser(email: string) { "use step"; return { id: crypto.randomUUID(), email }; } export async function sendWelcomeEmail(user: { id: string; email: string }) { "use step"; // Send email logic } export async function sendOnboardingEmail(user: { id: string; email: string }) { "use step"; // Send email logic } ``` -------------------------------- ### Start a New Workflow Run Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-api/start Use the `start` function to enqueue a new workflow. Ensure the workflow definition is imported correctly. ```typescript import { start } from "workflow/api"; import { myWorkflow } from "./workflows/my-workflow"; const run = await start(myWorkflow); ``` -------------------------------- ### Basic Chat Setup with WorkflowChatTransport Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-ai/workflow-chat-transport Demonstrates the fundamental setup for an AI chat interface using WorkflowChatTransport. Ensure you have the necessary imports for @ai-sdk/react and @workflow/ai. ```javascript "use client"; import { useChat } from "@ai-sdk/react"; import { WorkflowChatTransport } from "@workflow/ai"; import { useState } from "react"; export default function BasicChat() { const [input, setInput] = useState(""); const { messages, sendMessage } = useChat({ transport: new WorkflowChatTransport(), }); return (
{messages.map((m) => (
{m.role}: {m.content}
))}
{ e.preventDefault(); sendMessage({ text: input }); setInput(""); }} > setInput(e.currentTarget.value)} />
); } ``` -------------------------------- ### Install Workflow Dependencies Source: https://workflow-sdk.dev/v5/docs/getting-started/express Install the necessary packages for workflow, express, nitro, and rollup. ```bash npm install @astrojs/workflow @astrojs/express @astrojs/nitro @rollup/core ``` -------------------------------- ### Install Workflow, Fastify, and Nitro Dependencies Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify Install the necessary npm packages for workflow integration, Fastify, and Nitro's build system. ```bash npm i workflow fastify nitro rollup ``` -------------------------------- ### Install @workflow/serde Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-serde Install the @workflow/serde package using npm. This package is required for custom class serialization. ```bash npm i @workflow/serde ``` -------------------------------- ### Start a workflow run with Workflow SDK Source: https://workflow-sdk.dev/v5/docs/migration-guides/migrating-from-inngest Workflow SDK uses `start()` to launch workflows directly, returning a handle immediately. This replaces Inngest's event dispatching mechanism. ```typescript import { start } from 'workflow/api'; import { processOrder } from '@/workflows/order'; const run = await start(processOrder, [orderId]); ``` -------------------------------- ### Install Workflow SDK and Dependencies Source: https://workflow-sdk.dev/v5/docs/getting-started/express Install the necessary packages for your Express project, including the Workflow SDK, Express, Nitro, and Rollup. ```bash npm i workflow express nitro rollup ``` -------------------------------- ### Install Workflow and Nitro Packages Source: https://workflow-sdk.dev/v5/docs/getting-started/vite Install the 'workflow' and 'nitro' npm packages. Nitro is required for API routes and deployment. ```bash npm i workflow nitro ``` -------------------------------- ### Install Vercel Python SDK Source: https://workflow-sdk.dev/v5/docs/getting-started/python Install the `vercel` package using pip. This is the first step to using the Python SDK for Vercel workflows. ```bash pip install vercel ``` -------------------------------- ### Spawn a child workflow using start() Source: https://workflow-sdk.dev/v5/docs/migration-guides/migrating-from-aws-step-functions In v5, call `start()` directly from the workflow to launch a child. This replaces the ASL `StartExecution` call. ```typescript import { start } from 'workflow/api'; export async function parentWorkflow(item: string) { 'use workflow'; const run = await start(childWorkflow, [item]); return { childRunId: run.runId }; } ``` -------------------------------- ### Navigate to Project Directory Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify Change into the newly created project directory. ```bash cd my-workflow-app ``` -------------------------------- ### Configure Next.js for Workflow SDK Source: https://workflow-sdk.dev/v5/docs/ai Extend your Next.js config to transform workflow code. Ensure you have followed the Getting Started guide for more details. ```typescript import { withWorkflow } from "workflow/next"; import type { NextConfig } from "next"; const nextConfig: NextConfig = { // ... rest of your Next.js config }; export default withWorkflow(nextConfig); ``` -------------------------------- ### Initialize npm Project Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify Initialize a new Node.js project with npm. ```bash npm init --y ``` -------------------------------- ### Navigate to Project Directory Source: https://workflow-sdk.dev/v5/docs/getting-started/nitro Change into the newly created 'nitro-app' directory. ```bash cd nitro-app ``` -------------------------------- ### Run Local Development Server Source: https://workflow-sdk.dev/v5/docs/deploying Start your local development server. Workflows function out of the box without additional configuration. ```bash npm run dev ``` -------------------------------- ### Create SvelteKit Project Source: https://workflow-sdk.dev/v5/docs/getting-started/sveltekit Use this command to create a new SvelteKit project with a minimal setup. It initializes a directory named `my-workflow-app`. ```bash npx sv create my-workflow-app --template=minimal --types=ts --no-add-ons ``` -------------------------------- ### Get Deep-Link URL for a Workflow Run Source: https://workflow-sdk.dev/v5/docs/observability Prints the dashboard deep-link URL for a specific run to stdout without opening a browser or starting a local server. Useful for scripts and automation. Add --json to get a JSON output with a 'url' key. ```bash # Print the deep-link URL for a run (no browser, no server) npx workflow inspect run --url ``` -------------------------------- ### Navigate to Project Directory Source: https://workflow-sdk.dev/v5/docs/getting-started/nuxt Change into the newly created Nuxt project directory. ```bash cd nuxt-app ``` -------------------------------- ### Create a Route Handler for Workflow Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify Create a Fastify route handler that invokes a workflow. This example shows how to use the `start` function to initiate a workflow. ```typescript // server/api/hello.ts import { start } from 'workflow' import { hello } from '../workflows/hello' export default defineEventHandler(async (event) => { const result = await start(hello) return result }) ``` -------------------------------- ### Passing AbortSignal as Workflow Input Source: https://workflow-sdk.dev/v5/docs/foundations/cancellation Shows how to initiate a workflow with an external AbortSignal using the start() function. The example includes triggering the abort from external code. ```typescript import { start } from "workflow/api"; export async function POST(request: Request) { const controller = new AbortController(); const run = await start(myWorkflow, [controller.signal]); // Later, cancel from external code controller.abort(); } ``` -------------------------------- ### Get Workflow Run Details Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-api/get-run Fetches details of a specific workflow run by its ID. This includes its status, creation and start times, return value, and associated streams. ```APIDOC ## getRun(runId: string) ### Description Retrieves a `Run` object for a given workflow run ID. ### Parameters #### Path Parameters - **runId** (string) - Required - The workflow run ID obtained from starting a workflow. ### Returns Returns a `Run` object with the following properties: - **runId** (string) - The ID of the workflow run. - **wakeUp** - (options?: StopSleepOptions | undefined) => Promise - Interrupts pending `sleep()` calls, resuming the workflow early. - **cancel** - () => Promise - Cancels the workflow run. - **exists** - Promise - Whether the workflow run exists. - **status** - Promise<"pending" | "running" | "completed" | "failed" | "cancelled"> - The status of the workflow run. - **returnValue** - Promise - The return value of the workflow run. Polls the workflow return value until it is completed. - **workflowName** - Promise - The name of the workflow. - **createdAt** - Promise - The timestamp when the workflow run was created. - **startedAt** - Promise - The timestamp when the workflow run started execution. Returns undefined if the workflow has not started yet. - **completedAt** - Promise - The timestamp when the workflow run completed. Returns undefined if the workflow has not completed yet. - **readable** - WorkflowReadableStream - The readable stream of the workflow run. - **getReadable** - (options?: WorkflowReadableStreamOptions | undefined) => WorkflowReadableStream - Retrieves the workflow run's default readable stream. ### Example ```typescript const run = await workflow.getRun("your-run-id"); console.log(await run.status); ``` ``` -------------------------------- ### Start a Workflow and Access Run Object Source: https://workflow-sdk.dev/v5/docs/foundations/starting-workflows Initiates a workflow and provides a `Run` object to access its status and results. Await async properties like `status` and `returnValue` to get their values. ```typescript import { start } from "workflow/api"; import { processOrder } from "./workflows/process-order"; const run = await start(processOrder, [/* orderId */]); // The run object has properties you can await console.log("Run ID:", run.runId); // Check the workflow status const status = await run.status; // "running" | "completed" | "failed" // Get the workflow's return value (blocks until completion) const result = await run.returnValue; ``` -------------------------------- ### Basic Workflow Plugin Setup Source: https://workflow-sdk.dev/v5/docs/api-reference/vitest Use this to automatically handle SWC transforms, bundle building, and in-process handler registration for your workflow tests. ```javascript import { defineConfig } from "vitest/config"; import { workflow } from "@workflow/vitest"; export default defineConfig({ plugins: [workflow()], }); ``` -------------------------------- ### Get Workflow Metadata in a Workflow Function Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow/get-workflow-metadata Access workflow run IDs and timing information within workflow functions. This example demonstrates how to retrieve and log the workflow run ID. ```typescript import { getWorkflowMetadata } from "workflow" async function testWorkflow() { "use workflow" const ctx = getWorkflowMetadata() console.log(ctx.workflowRunId) } ``` -------------------------------- ### Stream Chat Response Source: https://workflow-sdk.dev/v5/docs/ai/chat-session-modeling Handles GET requests to stream chat messages for a given workflow run. It retrieves the run ID and an optional start index from the URL parameters to create a readable stream. ```typescript import { createUIMessageStreamResponse } from "ai"; import { getRun } from "workflow/api"; export async function GET( request: Request, { params }: { params: Promise<{ id: string }> } ) { const { id } = await params; const { searchParams } = new URL(request.url); const startIndex = searchParams.get("startIndex"); const run = getRun(id); const stream = run.getReadable({ startIndex: startIndex ? parseInt(startIndex, 10) : undefined, }); return createUIMessageStreamResponse({ stream }); } ``` -------------------------------- ### List Runs with Display Names Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-observability/parse-workflow-name This example demonstrates how to fetch workflow runs and display their parsed, human-readable names in the console. It utilizes `getWorld` to get workflow data and `parseWorkflowName` to format the names for display. If parsing fails, it falls back to the original workflow name. ```typescript import { getWorld } from "workflow/runtime"; import { parseWorkflowName } from "workflow/observability"; const world = await getWorld(); const runs = await world.runs.list({ resolveData: "none" }); for (const run of runs.data) { const parsed = parseWorkflowName(run.workflowName); console.log(`${parsed?.shortName ?? run.workflowName}: ${run.status}`); } ``` -------------------------------- ### Create Fastify Project Directory Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify Create a new directory for your Fastify project. ```bash mkdir my-workflow-app ``` -------------------------------- ### Launch Local UI via CLI Source: https://workflow-sdk.dev/v5/docs/deploying/world/vercel-world Use this command to launch the local observability UI instead of the Vercel dashboard. It requires specifying the Vercel backend. ```bash npx workflow web --backend vercel --localUi ``` -------------------------------- ### hydrateResourceIO Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-observability/hydrate-resource-io Hydrates (deserializes) the data fields of a resource returned by the World SDK. This is necessary before displaying step input/output in a UI. The function dispatches on the resource shape: steps get `input`/`output` hydrated, hooks get `metadata`, events get `eventData`, and runs get `input`/`output`. ```APIDOC ## hydrateResourceIO ### Description Hydrates (deserializes) the data fields of a resource returned by the World SDK — a workflow run, step, hook, or event. Workflow data is serialized using the devalue format, so this is required before displaying step input/output in a UI. The function dispatches on the resource shape: steps get `input`/`output` hydrated, hooks get `metadata`, events get `eventData`, and runs get `input`/`output`. ### Parameters #### Path Parameters - **resource** (`WorkflowRun | Step | Hook | Event`) - Required - The resource with serialized data fields. - **revivers** (`Revivers`) - Required - Reviver functions for deserialization. Use `observabilityRevivers` for standard use. ### Returns The same resource with its data fields hydrated into plain JavaScript values. Encrypted data fields pass through as raw `Uint8Array` values rather than being decrypted. ### Example ```javascript import { getWorld } from "workflow/runtime"; import { hydrateResourceIO, observabilityRevivers } from "workflow/observability"; declare const runId: string; // @setup declare const stepId: string; // @setup const world = await getWorld(); const step = await world.steps.get(runId, stepId); const hydrated = hydrateResourceIO(step, observabilityRevivers); console.log(hydrated.input, hydrated.output); ``` ``` -------------------------------- ### Start Workflow with Attributes Source: https://workflow-sdk.dev/v5/docs/observability/attributes Seed attributes directly when starting a workflow run. ```javascript const run = await start(orderWorkflow, ["ord_123"], { attributes: { source: "checkout" }, }) ``` -------------------------------- ### Start a workflow from an API route Source: https://workflow-sdk.dev/v5/docs/migration-guides/migrating-from-aws-step-functions Starting a Step Functions execution via the AWS SDK or API Gateway is replaced by using the 'start' function from the Workflow SDK within a route handler. ```typescript import { start } from 'workflow/api'; import { processOrder } from '@/workflows/order'; export async function POST(request: Request) { const { orderId } = (await request.json()) as { orderId: string }; const run = await start(processOrder, [orderId]); return Response.json({ runId: run.runId }); } ``` -------------------------------- ### Resume hook or start workflow Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-errors/hook-not-found-error Implements a common 'resume or start' pattern for idempotent workflows. It first attempts to resume an existing hook and, if a HookNotFoundError occurs, starts a new workflow run. ```typescript import { HookNotFoundError } from "workflow/errors" declare function resumeHook(token: string, data: unknown): Promise; // @setup declare function startWorkflow(name: string, data: unknown): Promise; // @setup async function handleIncomingEvent(token: string, data: unknown) { try { // Try to resume an existing hook await resumeHook(token, data); } catch (error) { if (HookNotFoundError.is(error)) { // Hook doesn't exist yet — start a new workflow run await startWorkflow("processEvent", data); } else { throw error; } } } ``` -------------------------------- ### Build Workflow Bundles with CLI Source: https://workflow-sdk.dev/v5/docs/how-it-works/framework-integrations Use the command-line interface to build workflow files. Defaults to scanning the './workflows' directory and outputs bundled files to the working directory. ```bash workflow build ``` -------------------------------- ### Bun Integration: Package.json Script Source: https://workflow-sdk.dev/v5/docs/how-it-works/framework-integrations Configure your package.json to build workflow handlers and start the development server using Bun. ```json { "scripts": { "dev": "bun x workflow build && PORT=3152 bun run server.ts" } } ``` -------------------------------- ### Install Express Types for TypeScript Source: https://workflow-sdk.dev/v5/docs/getting-started/express If you are using TypeScript, install the type definitions for Express. ```bash npm i -D @types/express ``` -------------------------------- ### Create Express App and Route Handler Source: https://workflow-sdk.dev/v5/docs/getting-started/express Sets up an Express application with a POST endpoint at /api/signup to initiate a user signup workflow. Requires express and workflow SDK imports. ```typescript import express from "express"; import { start } from "workflow/api"; import { handleUserSignup } from "../workflows/user-signup.js"; const app = express(); app.use(express.json()); app.post("/api/signup", async (req, res) => { const { email } = req.body; await start(handleUserSignup, [email]); return res.json({ message: "User signup workflow started" }); }); export default app; ``` -------------------------------- ### Step ID Generation Example Source: https://workflow-sdk.dev/v5/docs/how-it-works/code-transform Illustrates the pattern for generating stable IDs for steps based on file paths and function names. ```text step//workflows/user-signup.js//createUser ``` -------------------------------- ### Install Workflow SDK Dependencies Source: https://workflow-sdk.dev/v5/docs/getting-started/hono Install the 'workflow', 'nitro', and 'rollup' npm packages. ```bash npm i workflow nitro rollup ``` -------------------------------- ### buildWorkflowTests() Source: https://workflow-sdk.dev/v5/docs/api-reference/vitest Builds workflow and step bundles to disk. This function is called automatically by the `workflow()` plugin in `globalSetup`. It should only be used directly for manual setup purposes. ```APIDOC ## buildWorkflowTests() ### Description Builds workflow and step bundles to disk. Called automatically by the `workflow()` plugin in `globalSetup`. Use directly only for manual setup. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript import { buildWorkflowTests } from "@workflow/vitest"; export async function setup() { await buildWorkflowTests(); } ``` ### Response #### Success Response (200) None #### Response Example None ``` -------------------------------- ### Install TypeScript Dependencies (Optional) Source: https://workflow-sdk.dev/v5/docs/getting-started/fastify If using TypeScript, install the required type definition and TypeScript packages. ```bash npm i -D @types/node typescript ``` -------------------------------- ### Basic Agent with Tools Source: https://workflow-sdk.dev/v5/docs/api-reference/workflow-ai/durable-agent Demonstrates how to initialize a Durable Agent with a single tool and initiate a workflow. Ensure the tool's input schema is correctly defined using Zod. ```typescript import { DurableAgent, } from "@workflow/ai/agent"; import { getWritable, } from "workflow"; import { z } from "zod"; import type { UIMessageChunk, } from "ai"; async function getWeather({ location, }: { location: string; }) { "use step"; // Fetch weather data const response = await fetch(`https://api.weather.com?location=${location}`); return response.json(); } async function weatherAgentWorkflow(userQuery: string) { "use workflow"; const agent = new DurableAgent({ model: "anthropic/claude-haiku-4.5", tools: { getWeather: { description: "Get current weather for a location", inputSchema: z.object({ location: z.string(), }), execute: getWeather, }, }, instructions: "You are a helpful weather assistant. Always provide accurate weather information.", }); await agent.stream({ messages: [ { role: "user", content: userQuery, }, ], writable: getWritable(), }); } ``` -------------------------------- ### Payment Step ID Generation Example Source: https://workflow-sdk.dev/v5/docs/how-it-works/code-transform Illustrates the pattern for generating stable IDs for payment steps based on file paths and function names. ```text step//workflows/payments/checkout.ts//processPayment ``` -------------------------------- ### Start a Chat Session API Endpoint Source: https://workflow-sdk.dev/v5/docs/ai/chat-session-modeling This POST endpoint starts a new chat workflow session. It takes an initial user message, starts the workflow, and returns a stream response with the workflow run ID in the headers for follow-ups and reconnection. ```typescript import { createUIMessageStreamResponse, type UIMessage } from "ai"; import { start } from "workflow/api"; import { chat } from "@/workflows/chat"; export async function POST(req: Request) { const { initialMessage }: { initialMessage: UIMessage } = await req.json(); const run = await start(chat, [[initialMessage]]); return createUIMessageStreamResponse({ stream: run.readable, headers: { "x-workflow-run-id": run.runId, // For follow-ups and reconnection }, }); } ```