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, o

By vercel · 521 installs

npx skills add vercel/workflow --skill migrating-to-workflow-sdk

Source repository · Upstream listing

Migrating to the Workflow SDK Use this skill when converting an existing orchestration system to the Workflow SDK. Intake 1. Identify the source system: Temporal Inngest Trigger.dev AWS Step Functions 2. Identify the target runtime: Managed hosting keep examples focused on start() , getRun() , hooks/webhooks, and route handlers. Self hosted also read references/runtime targets.md and explicitly say the workflow/step code can stay the same, but deployment still needs a World implementation and startup bootstrap. 3. 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 default 202 Accepted response 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/default and make the assumption explicit in Open Questions . Never pair createWebhook() with resumeHook() , and never pass token: to createWebhook() . Wrap start() and getRun() inside "use step" functions for child runs. Use getStepMetadata().stepId as 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: 1. If the prompt explicitly asks for framework agnostic app boundary code, use plain Request / Response even when a framework like Hono is named. 2. Otherwise, if the target framework is named, shape app boundary examples to that framework. 3. Otherwise, keep examples framework agnostic with Request / Response . Do not default to Next.js only route signatures unless Next.js is explicitly named. 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. custom World guidance. references/resume routing.md : Route key selection, obligations, and exact Migration Plan shape. references/retries.md : Canonical retry mechanics, including stepFn.maxRetries , RetryableError({ retryAfter }) , and FatalError . Required output shape Return the migration in this structure: Verification checklist Fail the draft if any of these are true: [ ] Migration Plan omits Route keys [ ] Migration Plan omits Why these route keys [ ] Migration Plan lists route keys that do not match the prompt [ ] Migration Plan lists 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 of createWebhook() [ ] A resume/url/default or resume/url/manual migration invents a user authored callback route or resumeWebhook() wrapper when webhook.url should be the only resume surface [ ] createWebhook() is given a custom token or paired with resumeHook() Validation note: Reading webhook request data in workflow context is allowed. Only request.respondWith() is step only. Additional fail conditions: resume/internal output omits resumeHook() in app boundary code resume/internal output omits a deterministic business token resume/internal output emits createWebhook() or webhook.url resume/url/default output does not pass webhook.url to the external system resume/url/default output emits resumeHook() , respondWith: 'manual' , or RequestWithResponse without a custom response requirement in the prompt resume/url/default output invents a user authored callback route or resumeWebhook() wrapper when webhook.url is the intended resume surface resume/url/manual output does not pass webhook.url to the external system resume/url/manual output omits RequestWithResponse or await request.respondWith(...) resume/url/manual output calls request.respondWith(...) outside a "use step" function resume/url/manual output invents a user authored callback route or resumeWebhook() wrapper when webhook.url is the intended resume surface createWebhook() is paired with resumeHook() 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 custom World named framework output mixes framework syntax with plain Request / Response app 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 block references/aws step functions.md Combined recipe: callback URL on self hosted Hono Sample prompt Expected response shape: 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 block references/aws step functions.md Combined recipe: callback URL on self hosted Hono Reject these counterexamples: resume/url/default or resume/url/manual + user authored callback route when webhook.url is the intended resume surface createWebhook() paired with resumeHook() named framework app boundary output mixed with plain Request / Response without a framework agnostic override