SDK & YAML では、2つのオーサリング surface が同等であることを示しています。そして、最も重要なフィールド(idusewith、branch 経由の whenforeach)については実際に同等です。ただし、StepSchema01 — Concepts)は9つのフィールドを宣言しており、すべてのフィールドにビルダーメソッドや YAML キーが 現時点で 配線されているわけではありません。このページは、理想としての IR ではなく、parser と builder に直接照らして確認した、正直なギャップ一覧です。
この表は、本稿執筆時点の packages/sdk/src/index.tspackages/yaml/src/parse.ts を反映しています。配線は時間とともに変わります。「まだオーサリングできない」行に依存する場合は、それを前提に作り込む前にソースを再確認してください。

StepSchema フィールドSDKYAML現在
id.step(id, …) / .foreach(id, …) の step-id 引数、YAML の id: キー
usehttp.get/http.post/browser.tool(ref)/transform(…) によって lowering される。YAML の use: 文字列
withクロージャーは ${{ … }} バインディング文字列へ lowering される。YAML の with: mapping
needs⚠️ 推論のみ✅ 明示可能下の needs を参照
when⚠️ .branch() 経由のみ✅ 任意の手順下の when を参照
foreach.foreach(id, over, def)。YAML の foreach: バインディング
output_as❌ オーサリング不可下の output_as を参照
retry❌ オーサリング不可❌ オーサリング不可下の retry and timeout_ms を参照
timeout_ms❌ オーサリング不可❌ オーサリング不可retry と同じ
retrytimeout_msStepSchema01 §3)には存在しますが、両方の surface が lowering する先である、parse に依存しない RawStep 型(packages/core/src/compile/compile.ts)にすら存在しません。これは予約済みの IR surface であり、「parser branch の実装漏れ」ではありません。詳しくは下を参照してください。

needs: SDK では推論、YAML では明示

コンパイラーは常にデータ参照から依存エッジを導出します。つまり、手順の with/when/foreach 内にあるすべての steps.<id> 参照を集めてエッジを追加し、そのうえで raw step が持つ明示的な needs和集合 を取ります(03 §6)。
// packages/core/src/compile/compile.ts
needs: p.raw.needs ?? [],           // fed into buildGraph
...
const needs = node === undefined ? [] : [...node.deps];   // inferred ∪ explicit, on the built Step
YAML parser は、明示的な needs: sequence を step mapping から直接読み取ります。
- id: notify
  use: http.post
  needs: [audit-log]   # ordering edge with no data reference
  with: { url: ${{ secret.webhook }}, json: ${{ steps.shape.output }} }
SDK builder は RawStep.needs を設定しません。packages/sdk/src/index.ts 内のすべての .step(id, def) 呼び出しは、usewithwhenforeach だけから step object を構築します。.needs(...) メソッドはなく、明示的な依存リストを StepDef に渡す方法もありません。実務上、これはほとんど問題になりません。同じデータ参照があれば、SDK は YAML と同じエッジを推論するためです。ただし、ある特定のケースには SDK の等価表現がありません。B が A の生成物を何も読まないときに、step B を step A の後で強制的に実行するケースです(たとえば、共有データはないが、副作用のある step より先に audit-log 書き込みを完了させる必要がある場合)。YAML はその順序制約を直接表現できますが、現在の SDK ではできません。

when: SDK では branch 専用の糖衣構文

YAML では、任意の step が when: バインディングを直接持てます。
- id: notify
  use: http.post
  when: ${{ steps.shape.output.price < input.threshold }}
SDK には、これと等価な step ごとの setter がありません。step に when を付ける唯一の方法は .branch(label, pred, { yes, no }) です。これは yes arm 内のすべての step に pred を lowering し(when: pred)、no arm 内のすべての step にその否定を lowering します(when: !(pred))。packages/sdk/src/index.tscombineWhen/branchControl flow を参照してください。.step(id, def).when(pred) という chain はなく、branch arm の外側で任意の述語によって単一の step を gate する方法もありません。ネストした branch は合成されます(whenStack は AND されます)ので、この方法で述語の任意の論理積を表現できます。ただし常に .branch() 経由であり、裸の step ごとのフィールドとしては表現できません。

output_as: YAML 専用の糖衣構文

output_as を使うと、YAML の step は出力を alias の下で公開できるため、downstream のバインディングは producer step の実際の id ではなく steps.<alias>.output を読めます(03 §6)。YAML parser は、これを step mapping から直接読み取ります(packages/yaml/src/parse.tsparseStep)。
- id: lookup-search-price-v2
  use: browser:search-price@2.0.0
  output_as: lookup   # downstream: steps.lookup.output
packages/sdk/src/index.tsStepDefFlowBuilder には、output_as という概念がまったくありません。StepDef 上のフィールドも、builder method も、raw step にコピーされるものもありません。これは見落としではなく、意図的な非対称性です。SDK では、.step(id, …) を呼んだときに確立される型付きの c.steps.<id>.output handle を通じて step の出力をすでに参照するため、alias が rename する対象がありません。alias が役に立つのは YAML だけです。YAML では step の「handle」は、誰かが一度選んだ文字列 id にすぎず、downstream 参照をすべて触らずに表示上だけ変えたい場合があるためです。

retrytimeout_ms: IR では宣言済みだが、まだどこにも配線されていない

どちらのフィールドも StepSchema の一部であり、予約済み policy として文書化されています(「Defaults are derived from a tool’s kind」、01 §0)。現在の pipeline に照らして確認すると、どちらも end-to-end では到達できません。
  • packages/sdk/src/index.tsStepDefFlowBuilder.step.foreach、または http/browser/transform helper のどこにも retry/timeout_ms option はありません。
  • packages/yaml/src/parse.tsparseStep が読むのは idusewithneedswhenforeachoutput_as です。retry:timeout_ms: キーはまったく探しません。.flow.yaml ファイルでどちらかを作成しても、黙って捨てられます(parser が mapping からそれらのキーを単に読まないためです)。
  • packages/core/src/compile/compile.ts — parse に依存しない RawStep interface 自体に retry/timeout_ms フィールドがなく、最終的な compiled Step を構築する step-assembly 段階でも、結果にコピーされるのは withneedswhenforeachoutput_as だけです。それらのフィールドを持つ RawFlow を手作業で構築したとしても、コンパイルを経て FlowSpec まで生き残ることはありません。
これは予約済みの IR surface であり、client-side で回避すべき bug ではありません。現時点で retry や timeout の挙動が必要な場合、それは step-level policy ではなく、tool 自体(browser/http tool 自身の retry/timeout handling)に置く必要があります。どちらの surface にも、まだそれをオーサリングする path はありません。これが配線されるまでは、そうでないと主張する UI や doc は stale とみなしてください。

関連

SDK & YAML

2つのオーサリング surface を並べて、実際に同等であるフィールドを示します。

制御フロー

branchwhenforeach が、IR に実際に保存される2つの制御フィールドへどのように lowering されるか。

FlowSpec と IR

両方の surface が target とする canonical な StepSchema の形。needs inference と output_as resolution も含みます。

Diagnostics

alias_collisioncycle、およびこのページのフィールドが引き起こしうる catalogue 内のその他のコンパイル時エラー。