
migrating-to-workflow-sdk
Migrates Temporal, Inngest, Trigger.dev, and AWS Step Functions workflows to the Workflow SDK. Use when porting Activities, Workers, Signals, step.run(), step.waitForEvent(), Trigger.dev tasks / wait.forToken / triggerAndWait, ASL JSON state machines, Task/Choice/Wait/Parallel states, task tokens, or child workflows.
- Installs
- 735
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdk- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads migrating-to-workflow-sdk automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Migrating to the Workflow SDK
Use this skill when converting an existing orchestration system to the Workflow SDK.
Intake
- Identify the source system:
- Temporal
- Inngest
- Trigger.dev
- AWS Step Functions
- Identify the target runtime:
- Managed hosting -> keep examples focused on
start(),getRun(), hooks/webhooks, and route handlers. - Self-hosted -> also read
references/runtime-targets.mdand explicitly say the workflow/step code can stay the same, but deployment still needs aWorldimplementation and startup bootstrap.
- Managed hosting -> keep examples focused on
- Extract the source constructs:
- entrypoint
- waits / timers
- external callbacks / approvals
- retries / failure handling
- child workflows / fan-out
- progress streaming
- external side effects
Default migration rules
- Put orchestration in
"use workflow"functions. - Put side effects, SDK calls, DB calls, HTTP calls, and stream I/O in
"use step"functions. - Use
sleep()only in workflow context. - For Signals,
step.waitForEvent(), and.waitForTaskToken, choose exactly one resume surface:resume/internal->createHook()+resumeHook()when the app resumes from server-side code with a deterministic business token.resume/url/default->createWebhook()when the external system needs a generated callback URL and the default202 Acceptedresponse is fine.resume/url/manual->createWebhook({ respondWith: 'manual' })only when the prompt explicitly requires a custom response body, status, or headers.- If a callback-URL prompt does not specify response semantics, default to
resume/url/defaultand make the assumption explicit in## Open Questions.
- Never pair
createWebhook()withresumeHook(), and never passtoken:tocreateWebhook(). - Wrap
start()andgetRun()inside"use step"functions for child runs. - Use
getStepMetadata().stepIdas the idempotency key for external writes. - Use
getWritable()in workflow context to obtain the stream, but interact with it (write, close) only inside"use step"functions. - Prefer rollback stacks for multi-step compensation.
- Choose app-boundary syntax in this order:
- If the prompt explicitly asks for framework-agnostic app-boundary code, use plain
Request/Responseeven when a framework like Hono is named. - Otherwise, if the target framework is named, shape app-boundary examples to that framework.
- Otherwise, keep examples framework-agnostic with
Request/Response. Do not default to Next.js-only route signatures unless Next.js is explicitly named.
- If the prompt explicitly asks for framework-agnostic app-boundary code, use plain
Fast memory aid:
- Callback URL + default ack ->
createWebhook()- Callback URL + custom ack ->
createWebhook({ respondWith: 'manual' })- Deterministic server-side resume ->
createHook()+resumeHook()
Fast-path router
Load references/resume-routing.md when the source pauses for Signals, step.waitForEvent(), or .waitForTaskToken.
Fast defaults:
- callback URL only ->
resume/url/default - callback URL + explicit custom response ->
resume/url/manual - deterministic server-side resume ->
resume/internal - self-hosted -> add
runtime/self-hosted - named framework -> add
boundary/named-framework - explicit framework-agnostic request -> add
boundary/framework-agnostic
Before drafting ## Migrated Code, write the selected route keys in ## Migration Plan.
Source references
- Temporal ->
references/temporal.md - Inngest ->
references/inngest.md - Trigger.dev ->
references/trigger-dev.md - AWS Step Functions ->
references/aws-step-functions.md
Shared references
references/shared-patterns.md: Reusable code templates for hooks, child workflows, idempotency, streaming, and rollback.references/runtime-targets.md: Managed vs. customWorldguidance.references/resume-routing.md: Route-key selection, obligations, and exact## Migration Planshape.references/retries.md: Canonical retry mechanics, includingstepFn.maxRetries,RetryableError({ retryAfter }), andFatalError.
Required output shape
Return the migration in this structure:
## Migration Plan
## Source -> Target Mapping
## Migrated Code
## App Boundary / Resume Endpoints
## Verification Checklist
## Open Questions
Verification checklist
Fail the draft if any of these are true:
-
## Migration PlanomitsRoute keys -
## Migration PlanomitsWhy these route keys -
## Migration Planlists route keys that do not match the prompt -
## Migration Planlists required code obligations that do not match the selected route keys - Source-framework primitives remain in the migrated code
- Side effects remain in workflow context
-
sleep()appears inside a step - Stream interaction (
getWriter(),write(),close()) appears inside a workflow function - Child workflows call
start()/getRun()directly from workflow context - External writes omit idempotency keys
- Hooks/webhooks are missing where the source used signals, waitForEvent, or task tokens
- A callback-URL flow uses
createHook()+resumeHook()instead ofcreateWebhook() - A
resume/url/defaultorresume/url/manualmigration invents a user-authored callback route orresumeWebhook()wrapper whenwebhook.urlshould be the only resume surface -
createWebhook()is given a customtokenor paired withresumeHook()
Validation note:
- Reading webhook request data in workflow context is allowed. Only
request.respondWith()is step-only.
Additional fail conditions:
resume/internaloutput omitsresumeHook()in app-boundary coderesume/internaloutput omits a deterministic business tokenresume/internaloutput emitscreateWebhook()orwebhook.urlresume/url/defaultoutput does not passwebhook.urlto the external systemresume/url/defaultoutput emitsresumeHook(),respondWith: 'manual', orRequestWithResponsewithout a custom-response requirement in the promptresume/url/defaultoutput invents a user-authored callback route orresumeWebhook()wrapper whenwebhook.urlis the intended resume surfaceresume/url/manualoutput does not passwebhook.urlto the external systemresume/url/manualoutput omitsRequestWithResponseorawait request.respondWith(...)resume/url/manualoutput callsrequest.respondWith(...)outside a"use step"functionresume/url/manualoutput invents a user-authored callback route orresumeWebhook()wrapper whenwebhook.urlis the intended resume surfacecreateWebhook()is paired withresumeHook()- self-hosted output omits
World extends Queue, Streamer, Storage,startWorkflowWorld(), or the explicit note that the workflow and step code can stay the same while the app still needs a customWorld - named-framework output mixes framework syntax with plain
Request/Responseapp-boundary code without a framework-agnostic override
For concrete passing code, load:
references/shared-patterns.md->## Generated callback URL (default response)references/shared-patterns.md->## Generated callback URL (manual response)references/runtime-targets.md->## Self-hosted output blockreferences/aws-step-functions.md->## Combined recipe: callback URL on self-hosted Hono
Sample prompt
Migrate this Inngest workflow to the Workflow SDK.
It uses step.waitForEvent() with a timeout and step.realtime.publish().
Expected response shape:
## Migration Plan
## Source -> Target Mapping
## Migrated Code
## App Boundary / Resume Endpoints
## Verification Checklist
## Open Questions
Example references
Load a worked example only when the prompt needs concrete code:
references/shared-patterns.md->## Named-framework internal resume example (Hono)references/shared-patterns.md->## Generated callback URL (default response)references/shared-patterns.md->## Generated callback URL (manual response)references/runtime-targets.md->## Self-hosted output blockreferences/aws-step-functions.md->## Combined recipe: callback URL on self-hosted Hono
Reject these counterexamples:
resume/url/defaultorresume/url/manual+ user-authored callback route whenwebhook.urlis the intended resume surfacecreateWebhook()paired withresumeHook()- named-framework app-boundary output mixed with plain
Request/Responsewithout a framework-agnostic override
FAQ
What does the migrating-to-workflow-sdk skill do?
Migrates Temporal, Inngest, Trigger.dev, and AWS Step Functions workflows to the Workflow SDK. Use when porting Activities, Workers, Signals, step.run(), step.waitForEvent(), Trigger.dev tasks / wait.forToken / triggerAndWait, ASL JSON state machines, Task/Choice/Wait/Parallel states, task tokens, or child workflows.
How do I install migrating-to-workflow-sdk?
Run npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdk in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/migrating-to-workflow-sdk/ (personal) or .claude/skills/migrating-to-workflow-sdk/ (project).
Which AI agents can use migrating-to-workflow-sdk?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is migrating-to-workflow-sdk safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains migrating-to-workflow-sdk?
It is published by vercel in vercel/workflow, and it is an official skill from the maker of the technology it covers. It has 735 recorded installs.
More from vercel/workflow
workflow
vercel/workflow
Creates durable, resumable workflows using Vercel's Workflow SDK. 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", "resumable", "workflow sdk", "queue", "event", "push", "subscribe", or step-based orchestration.
workflow-init
vercel/workflow
Install and configure Vercel Workflow SDK before it exists in nodemodules. Use when the user asks to "install workflow", "set up workflow", "add durable workflows", "configure workflow sdk", or "init workflow" for Next.js, Express, Hono, Fastify, NestJS, Nitro, Nuxt, Astro, SvelteKit, or Vite.
internal-dev-workbench
vercel/workflow
Spin up a portless + tmux dev session for the Workflow SDK that gives each git worktree isolated . .localhost URLs for the Next.js workbench and the observability UI, plus a Claude statusline that surfaces those URLs. Use only when the user asks for a "portless dev session", a "tmux dev layout for workflow", "worktree-isolated dev URLs", or wants to wire workflow dev URLs into the Claude statusline. Do not activate for the generic "start the dev server" / "run pnpm dev" task.
migrating-workflow-v4-to-v5
vercel/workflow
Upgrades an app from Workflow SDK 4.x to 5.0. Use when bumping the workflow / @workflow/ dependencies to v5, or when hitting removed v4 APIs — runStep, stepEntrypoint, workflow/internal/private, @workflow/core/private, writeToStream / closeStream / readFromStream on a World, world.steps.get without a runId, hook.getConflict() returning { runId }, hook.metadata read synchronously off a getHookByToken() result, experimentalsetAttributes, createLocalWorld / createVercelWorld, NestLocalBuilder imported from @workflow/nest, or an SWC transform invoked with mode: 'client'.
migrating-world-v4-to-v5
vercel/workflow
Upgrades a custom Workflow SDK World implementation from the v4 spec, or from a 5.0.0 beta, to the current v5 spec (spec version 8). Use when a package implements the World interface from @workflow/world and is moving to 5.x, or is on a 5.0.0 beta and the runtime reports This Workflow runtime supports Worlds with spec version 6 through 8, but the configured World declares spec version N; or when it shows event IDs that are ULIDs rather than slot positions, Event id is not slot-numbered at replay time, a specVersion the runtime refuses, writeToStream / closeStream / readFromStream as top-level World methods, steps.get or events.listByCorrelationId without a runId, a 'step' queue kind or wkfstep topics, a preconditionGuard capability, or a createLocalWorld / createVercelWorld factory.
Popular productivity & automation skills
agent-browser
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.
lark-doc
open.feishu.cn
飞书云文档(Docx / Wiki)内容操作:读取、创建、编辑文档,插入或下载图片附件,以及操作思维笔记。用户提供文档 URL/token(包括 doubao.com 的 /docx/、/wiki/)时使用;按 URL 路径/token 而非域名路由;/page/ 是妙搭应用,非飞书云文档。文档内嵌资源按读取参考中的统一规则分流。独立评论操作走 lark-drive;随正文读取评论使用 docs +fetch。表格或 Base 内部数据操作不在本 skill。
lark-base
open.feishu.cn
飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、应用模式(BaseApp/AppMode 页面与组件)、Workspace 目录、workflow、角色权限、模板中心(多维表格模板分类/列表/搜索);遇到 Base/多维表格/bitable、BaseApp/AppMode、/base/ 或 /app/ 链接时使用。BaseApp 不走 lark-apps;文件导入/导出转 lark-drive,认证/授权转 lark-shared。
lark-drive
open.feishu.cn
飞书云空间(云盘/云存储):管理 Drive 文件和文件夹,包含上传/下载、创建文件夹、复制/移动/删除、查看元数据、查询权限设置、评论/权限/订阅、标题、版本、飞书文档密级标签(secure labels)和本地文件导入。用户需要整理云盘目录、处理云空间资源 URL/token、判断链接类型/真实 token/标题,或导入 Word/Markdown/Excel/CSV/PPTX/.base 为 docx/sheet/bitable/slides 时使用;doubao.com 云空间 URL/token 也按资源路径和 token 路由,不回退 WebFetch。不负责:文档内容编辑(走 lark-doc)、表格/Base 表内数据操作(走 lark-sheets/lark-base)、知识空间节点/成员管理(走 lark-wiki)、原生 Markdown 文件读写/patch/diff(走 lark-markdown)。
lark-shared
open.feishu.cn
Use for lark-cli setup/auth tasks: auth login/status/logout, user vs bot identity, business-domain permissions (--domain, including all/docs/drive), missing scopes, revoking authorization, or handling notice JSON.
lark-im
open.feishu.cn
飞书即时通讯:收发消息和管理群聊。发送和回复消息、搜索聊天记录、管理群聊成员、上传下载图片和文件、管理表情回复、发送应用内/短信/电话加急、发送和处理交互卡片(Interactive Card)、监听卡片按钮回调(card.action.trigger)。当用户需要发消息、查看或搜索聊天记录、下载聊天中的文件、查看群成员、搜索群、创建群聊或话题群、管理标记数据、管理 Feed 置顶(添加/移除/查询置顶会话)、管理标签数据、处理卡片回调时使用。