Installs into .claude/skills of the current project.
Are you the author of Migrating To Workflow Sdk?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/pleaseai-migrating-to-workflow-sdk-claude-code-plugins)
---
name: migrating-to-workflow-sdk
description: 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.
metadata:
author: Vercel Inc.
version: 0.3.0
---
# 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:
```md
## 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 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
```text
Migrate this Inngest workflow to the Workflow SDK.
It uses step.waitForEvent() with a timeout and step.realtime.publish().
```
Expected response shape:
```md
## 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 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