migrating-to-workflow-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Migrating to the Workflow SDK

迁移至Workflow SDK

Use this skill when converting an existing orchestration system to the Workflow SDK.
当你需要将现有编排系统转换为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
  1. 识别源系统:
    • Temporal
    • Inngest
    • Trigger.dev
    • AWS Step Functions
  2. 识别目标运行时:
    • 托管部署 -> 示例重点关注
      start()
      getRun()
      、钩子/webhooks以及路由处理器。
    • 自托管 -> 同时阅读
      references/runtime-targets.md
      ,并明确说明工作流/步骤代码可保持不变,但部署仍需实现
      World
      并完成启动引导。
  3. 提取源系统构造:
    • 入口点
    • 等待/计时器
    • 外部回调/审批
    • 重试/故障处理
    • 子工作流/扇出
    • 进度流
    • 外部副作用

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()
  • 将编排逻辑放在
    "use workflow"
    函数中。
  • 将副作用、SDK调用、数据库调用、HTTP调用以及流I/O放在
    "use step"
    函数中。
  • 仅在工作流上下文中使用
    sleep()
  • 对于Signals、
    step.waitForEvent()
    以及
    .waitForTaskToken
    ,精确选择一种恢复方式:
    • resume/internal
      -> 当应用从服务器端代码通过确定性业务令牌恢复时,使用
      createHook()
      +
      resumeHook()
    • resume/url/default
      -> 当外部系统需要生成的回调URL且默认
      202 Accepted
      响应即可时,使用
      createWebhook()
    • resume/url/manual
      -> 仅当明确要求自定义响应体、状态码或请求头时,使用
      createWebhook({ respondWith: 'manual' })
    • 如果回调URL需求未指定响应语义,默认使用
      resume/url/default
      并在
      ## 待确认问题
      中明确说明该假设。
  • 切勿将
    createWebhook()
    resumeHook()
    配对使用,也不要向
    createWebhook()
    传递
    token:
    参数。
  • 对于子工作流运行,将
    start()
    getRun()
    包裹在
    "use step"
    函数中。
  • 使用
    getStepMetadata().stepId
    作为外部写入的幂等键。
  • 在工作流上下文中使用
    getWritable()
    获取流,但仅在
    "use step"
    函数中进行流交互(写入、关闭)。
  • 优先使用回滚栈处理多步骤补偿操作。
  • 按以下顺序选择应用边界语法:
    1. 如果明确要求框架无关的应用边界代码,即使提到了Hono等框架,也使用原生
      Request
      /
      Response
    2. 否则,如果指定了目标框架,调整应用边界示例以适配该框架语法。
    3. 否则,保持示例为框架无关的
      Request
      /
      Response
      格式。除非明确指定Next.js,否则不要默认使用Next.js专属的路由签名。
快速记忆口诀:
  • 回调URL + 默认响应 ->
    createWebhook()
  • 回调URL + 自定义响应 ->
    createWebhook({ respondWith: 'manual' })
  • 确定性服务器端恢复 ->
    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
.
当源系统因Signals、
step.waitForEvent()
.waitForTaskToken
暂停时,参考
references/resume-routing.md
快速默认规则:
  • 仅需回调URL ->
    resume/url/default
  • 回调URL + 明确自定义响应 ->
    resume/url/manual
  • 确定性服务器端恢复 ->
    resume/internal
  • 自托管 -> 添加
    runtime/self-hosted
  • 指定框架 -> 添加
    boundary/named-framework
  • 明确要求框架无关请求 -> 添加
    boundary/framework-agnostic
在编写
## 迁移后代码
之前,将选定的路由键写入
## 迁移计划

Source references

源系统参考文档

  • Temporal ->
    references/temporal.md
  • Inngest ->
    references/inngest.md
  • Trigger.dev ->
    references/trigger-dev.md
  • AWS Step Functions ->
    references/aws-step-functions.md
  • 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:
    stepFn.maxRetries
    ,
    RetryableError({ retryAfter })
    ,
    FatalError
    .
  • references/shared-patterns.md
    — 钩子、子工作流、幂等性、流处理和回滚的可复用代码模板。
  • references/runtime-targets.md
    — 托管部署与自定义
    World
    的指导说明。
  • references/resume-routing.md
    — 路由键选择、规范要求以及
    ## 迁移计划
    的标准格式。
  • references/retries.md
    — 标准重试机制:
    stepFn.maxRetries
    RetryableError({ retryAfter })
    FatalError

Required output shape

要求的输出格式

Return the migration in this structure:
md
undefined
请按以下结构返回迁移结果:
md
undefined

Migration Plan

迁移计划

Source -> Target Mapping

源系统 -> 目标系统映射

Migrated Code

迁移后代码

App Boundary / Resume Endpoints

应用边界 / 恢复端点

Verification Checklist

验证检查清单

Open Questions

待确认问题

undefined
undefined

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
如果存在以下任意情况,则草稿不通过:
  • ## 迁移计划
    遗漏
    Route keys
  • ## 迁移计划
    遗漏
    Why these route keys
  • ## 迁移计划
    列出的路由键与需求不匹配
  • ## 迁移计划
    列出的代码规范要求与选定的路由键不匹配
  • 迁移后代码中仍保留源系统框架的原生语法
  • 副作用仍存在于工作流上下文中
  • sleep()
    出现在step函数中
  • 流交互(
    getWriter()
    write()
    close()
    )出现在工作流函数中
  • 子工作流直接在工作流上下文中调用
    start()
    /
    getRun()
  • 外部写入未使用幂等键
  • 当源系统使用signals、waitForEvent或任务令牌时,未添加钩子/webhooks
  • 回调URL流使用
    createHook()
    +
    resumeHook()
    而非
    createWebhook()
  • resume/url/default
    resume/url/manual
    迁移中自行编写了回调路由或
    resumeWebhook()
    包装器,而正确方式应为使用
    webhook.url
    作为恢复入口
  • createWebhook()
    被传递了自定义
    token
    或与
    resumeHook()
    配对使用
额外不通过条件:
  • resume/internal
    输出在应用边界代码中遗漏
    resumeHook()
  • resume/internal
    输出遗漏确定性业务令牌
  • resume/internal
    输出包含
    createWebhook()
    webhook.url
  • resume/url/default
    输出未将
    webhook.url
    传递给外部系统
  • resume/url/default
    输出包含
    resumeHook()
    respondWith: 'manual'
    RequestWithResponse
    ,但需求中未要求自定义响应
  • resume/url/default
    迁移中自行编写了回调路由或
    resumeWebhook()
    包装器,而正确方式应为使用
    webhook.url
    作为恢复入口
  • resume/url/manual
    输出未将
    webhook.url
    传递给外部系统
  • resume/url/manual
    输出遗漏
    RequestWithResponse
    await request.respondWith(...)
  • resume/url/manual
    输出在
    "use step"
    函数外部调用
    request.respondWith(...)
  • resume/url/manual
    迁移中自行编写了回调路由或
    resumeWebhook()
    包装器,而正确方式应为使用
    webhook.url
    作为恢复入口
  • createWebhook()
    resumeHook()
    配对使用
  • 自托管输出遗漏
    World extends Queue, Streamer, Storage
    startWorkflowWorld()
    或明确说明工作流和step代码可保持不变但仍需自定义
    World
    的注释
  • 指定框架的输出混合了框架语法与原生
    Request
    /
    Response
    应用边界代码,且无框架无关的覆盖说明
如需参考符合要求的代码,请查看:
  • references/shared-patterns.md
    ->
    ## 生成的回调URL(默认响应)
  • references/shared-patterns.md
    ->
    ## 生成的回调URL(手动响应)
  • references/runtime-targets.md
    ->
    ## 自托管输出代码块
  • references/aws-step-functions.md
    ->
    ## 组合方案:自托管Hono上的回调URL

Sample prompt

示例需求

Migrate this Inngest workflow to the Workflow SDK.
It uses step.waitForEvent() with a timeout and step.realtime.publish().
Expected response shape:
md
undefined
将此Inngest工作流迁移至Workflow SDK。
它使用了带超时的step.waitForEvent()和step.realtime.publish()。
预期响应格式:
md
undefined

Migration Plan

迁移计划

Source -> Target Mapping

源系统 -> 目标系统映射

Migrated Code

迁移后代码

App Boundary / Resume Endpoints

应用边界 / 恢复端点

Verification Checklist

验证检查清单

Open Questions

待确认问题

undefined
undefined

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
仅当需求需要具体代码时,才加载以下示例:
  • references/shared-patterns.md
    ->
    ## 指定框架的内部恢复示例(Hono)
  • references/shared-patterns.md
    ->
    ## 生成的回调URL(默认响应)
  • references/shared-patterns.md
    ->
    ## 生成的回调URL(手动响应)
  • references/runtime-targets.md
    ->
    ## 自托管输出代码块
  • references/aws-step-functions.md
    ->
    ## 组合方案:自托管Hono上的回调URL
以下反例需避免:
  • resume/url/default
    resume/url/manual
    + 自行编写的回调路由(正确方式应为使用
    webhook.url
    作为恢复入口)
  • createWebhook()
    resumeHook()
    配对使用
  • 指定框架的应用边界输出混合了框架语法与原生
    Request
    /
    Response
    ,且无框架无关的覆盖说明