$npx -y skills add vercel-labs/open-agents --skill workflowCreates durable, resumable workflows using Vercel's Workflow DevKit. Use when building workflows that need to survive restarts, pause for external events, retry on failure, or coordinate multi-step operations over time. Triggers on mentions of "workflow", "durable functions", "re
| 1 | ## *CRITICAL*: Always Use Correct `workflow` Documentation |
| 2 | |
| 3 | Your knowledge of `workflow` is outdated. |
| 4 | |
| 5 | The `workflow` documentation outlined below matches the installed version of the Workflow DevKit. |
| 6 | Follow these instructions before starting on any `workflow`-related tasks: |
| 7 | |
| 8 | Search the bundled documentation in `node_modules/workflow/docs/`: |
| 9 | |
| 10 | 1. **Find docs**: `glob "node_modules/workflow/docs/**/*.mdx"` |
| 11 | 2. **Search content**: `grep "your query" node_modules/workflow/docs/` |
| 12 | |
| 13 | Documentation structure in `node_modules/workflow/docs/`: |
| 14 | |
| 15 | - `getting-started/` - Framework setup (next.mdx, express.mdx, hono.mdx, etc.) |
| 16 | - `foundations/` - Core concepts (workflows-and-steps.mdx, hooks.mdx, streaming.mdx, etc.) |
| 17 | - `api-reference/workflow/` - API docs (sleep.mdx, create-hook.mdx, fatal-error.mdx, etc.) |
| 18 | - `api-reference/workflow-api/` - Client API (start.mdx, get-run.mdx, resume-hook.mdx, etc.) |
| 19 | - `ai/` - AI SDK integration docs |
| 20 | - `errors/` - Error code documentation |
| 21 | |
| 22 | Related packages also include bundled docs: |
| 23 | |
| 24 | - `@workflow/ai`: `node_modules/@workflow/ai/docs/` - DurableAgent and AI integration |
| 25 | - `@workflow/core`: `node_modules/@workflow/core/docs/` - Core runtime (foundations, how-it-works) |
| 26 | - `@workflow/next`: `node_modules/@workflow/next/docs/` - Next.js integration |
| 27 | |
| 28 | **When in doubt, update to the latest version of the Workflow DevKit.** |
| 29 | |
| 30 | ### Official Resources |
| 31 | |
| 32 | - **Website**: https://useworkflow.dev |
| 33 | - **GitHub**: https://github.com/vercel/workflow |
| 34 | |
| 35 | ### Quick Reference |
| 36 | |
| 37 | **Directives:** |
| 38 | |
| 39 | ```typescript |
| 40 | "use workflow"; // First line - makes async function durable |
| 41 | "use step"; // First line - makes function a cached, retryable unit |
| 42 | ``` |
| 43 | |
| 44 | **Essential imports:** |
| 45 | |
| 46 | ```typescript |
| 47 | // Workflow primitives |
| 48 | import { sleep, fetch, createHook, createWebhook, getWritable } from "workflow"; |
| 49 | import { FatalError, RetryableError } from "workflow"; |
| 50 | import { getWorkflowMetadata, getStepMetadata } from "workflow"; |
| 51 | |
| 52 | // API operations |
| 53 | import { start, getRun, resumeHook, resumeWebhook } from "workflow/api"; |
| 54 | |
| 55 | // Framework integrations |
| 56 | import { withWorkflow } from "workflow/next"; |
| 57 | import { workflow } from "workflow/vite"; |
| 58 | import { workflow } from "workflow/astro"; |
| 59 | // Or use modules: ["workflow/nitro"] for Nitro/Nuxt |
| 60 | ``` |
| 61 | |
| 62 | ## Prefer Step Functions to Avoid Sandbox Errors |
| 63 | |
| 64 | `"use workflow"` functions run in a sandboxed VM. `"use step"` functions have **full Node.js access**. Put your logic in steps and use the workflow function purely for orchestration. |
| 65 | |
| 66 | ```typescript |
| 67 | // Steps have full Node.js and npm access |
| 68 | async function fetchUserData(userId: string) { |
| 69 | "use step"; |
| 70 | const response = await fetch(`https://api.example.com/users/${userId}`); |
| 71 | return response.json(); |
| 72 | } |
| 73 | |
| 74 | async function processWithAI(data: any) { |
| 75 | "use step"; |
| 76 | // AI SDK works in steps without workarounds |
| 77 | return await generateText({ |
| 78 | model: openai("gpt-4"), |
| 79 | prompt: `Process: ${JSON.stringify(data)}`, |
| 80 | }); |
| 81 | } |
| 82 | |
| 83 | // Workflow orchestrates steps - no sandbox issues |
| 84 | export async function dataProcessingWorkflow(userId: string) { |
| 85 | "use workflow"; |
| 86 | const data = await fetchUserData(userId); |
| 87 | const processed = await processWithAI(data); |
| 88 | return { success: true, processed }; |
| 89 | } |
| 90 | ``` |
| 91 | |
| 92 | **Benefits:** Steps have automatic retry, results are persisted for replay, and no sandbox restrictions. |
| 93 | |
| 94 | ## Workflow Sandbox Limitations |
| 95 | |
| 96 | When you need logic directly in a workflow function (not in a step), these restrictions apply: |
| 97 | |
| 98 | | Limitation | Workaround | |
| 99 | |------------|------------| |
| 100 | | No `fetch()` | `import { fetch } from "workflow"` then `globalThis.fetch = fetch` | |
| 101 | | No `setTimeout`/`setInterval` | Use `sleep("5s")` from `"workflow"` | |
| 102 | | No Node.js modules (fs, crypto, etc.) | Move to a step function | |
| 103 | |
| 104 | **Example - Using fetch in workflow context:** |
| 105 | |
| 106 | ```typescript |
| 107 | import { fetch } from "workflow"; |
| 108 | |
| 109 | export async function myWorkflow() { |
| 110 | "use workflow"; |
| 111 | globalThis.fetch = fetch; // Required for AI SDK and HTTP libraries |
| 112 | // Now generateText() and other libraries work |
| 113 | } |
| 114 | ``` |
| 115 | |
| 116 | **Note:** `DurableAgent` from `@workflow/ai` handles the fetch assignment automatically. |
| 117 | |
| 118 | ## Error Handling |
| 119 | |
| 120 | Use `FatalError` for permanent failures (no retry), `RetryableError` for transient failures: |
| 121 | |
| 122 | ```typescript |
| 123 | import { FatalError, RetryableError } from "workflow"; |
| 124 | |
| 125 | if (res.status >= 400 && res.status < 500) { |
| 126 | throw new FatalError(`Client error: ${res.status}`); |
| 127 | } |
| 128 | if (res.status === 429) { |
| 129 | throw new RetryableError("Rate limited", { retryAfter: "5m" }); |
| 130 | } |
| 131 | ``` |
| 132 | |
| 133 | ## Serialization |
| 134 | |
| 135 | All data passed to/from workflows and steps must be serializable. |
| 136 | |
| 137 | **Supported types:** string, number, boolean, null, un |