パイプライン: 作成、コンパイル、実行
すべては3つの段階を通ります。TypeScript SDK または YAML で Flow を一度作成すると、コンパイラーがそれをsha256 digest を持つ1つの正規化された FlowSpec に下げ、Rider がその FlowSpec をどこでも同一に実行します。2つのオーサリング面は対等な存在です(原則 T1)。どちらも同じ FlowSpec にコンパイルされ、その FlowSpec は YAML にラウンドトリップできます。
作成
Flow を一度書きます。SDK と YAML は対等な存在で、どちらも1つの IR に下げられます。
コンパイル
パース、解決、型チェック、正規化を行い、安定した digest へハッシュします。
実行
Rider が DAG をスケジュールし、Tool を呼び出し、Journal を書き込みます。
実行時の登場人物
実行時に働く名前付きコンポーネントは3つで、それらをホストする Launcher レイヤーがあります。それぞれに詳説ページがあります。| コンポーネント | それは何か | 1つの役割 |
|---|---|---|
| Rider | 実行エンジン | FlowSpec + 入力 + 注入された capability を受け取り、Journal を持つ Run を生成します。何かを実行する唯一のコンポーネントであり、モデルは実行しません。 |
| Launcher | 薄いホスト | 環境に応じた capability を構築して Rider を呼び出します。browserflow run(CLI)、HTTPルート(REST)、MCPツール、cron tick、CI step などです。 |
| Registry | Pack が置かれる場所 | Pack を公開、バージョン管理、解決します。他の registry へ複製し、digest で検証します。 |
Rider は実行時にモデルを実行しません。LLM に制御フローを決めさせるコードパスはありません。AI は Flow の作成を支援することがありますが、Flow が実行時に何をするかは決して決定しません。Step からモデルを呼び出すことはできますが、それは記録済みの入力と出力を持つ、通常の宣言された
model Tool としてだけです。Rider — 唯一の実行コンポーネント
Rider は FlowSpec、具体的な入力、注入された capability の集合を受け取り、Run を生成します。必要なものはすべてRunDeps を通じて注入されます(原則 T4)。グローバルを読まず、クラウド SDK をインポートせず、時計、RNG、ネットワーク、ファイルシステム、シークレットにはこれらのインターフェースを通じてだけ触れます。
Launcher — 薄いホスト
Launcher はengine.run() を包む薄いシェルです(原則 T5)。環境に適した capability を構築して Rider に渡します。同じ FlowSpec は、どの Launcher の下でも同じ結果で実行されます。ポータビリティ適合スイートは、まさにこの不変性を検証します。Launcher を参照してください。
Registry — Pack が置かれる場所
ローカル Registry はディレクトリで、チーム Registry はコントロールプレーンです。Registry は互いに複製します(push、pull、scheduled)。各転送は digest で検証されるため、ある環境で作成された Pack は、別の環境でも固定され、完全な状態で現れます。Tool はコンパイル時に Pack から解決され、実行時に Pack から呼び出されます。Tool と Pack を参照してください。すべての組み合わせ方
標準の実行例で各部品を動かしてみます。daily-price-watch Flow です。browser toolsearch-price@1.2.0 が価格を調べ、transform がそれを整形し、条件付きの http.post が、価格が下がったときだけシークレット webhook に通知します。
Pack が Tool と Flow を束ねる
search-price@1.2.0 browser tool、http.post、そして daily-price-watch Flow は、バージョン付きの content-addressed な Pack の中で一緒に存在します。これがデプロイ可能な「SDK」です。FlowSpec + digest にコンパイルする
Flow の
lookup Step と notify Step はそれらの Tool を参照します。コンパイラーは各 Tool を固定された ref とその contract_digest に解決し、Flow を正規化して、sha256 digest を持つ1つの FlowSpec を出力します。secret: true とマークされた入力は FlowSpec、Journal、ログ、公開された Pack のいずれにも入りません。その値が実体化するのは、secrets capability を宣言した http.post Step の内部だけであり、実行時だけです(原則 T8)。正確に名前付けされたすべての名詞については ドメインモデル を、境界と taint rule については シークレット を参照してください。
パッケージ構成: 矢印は core から外へ向かない
同じ構成上の規律はコードベースにも現れます。エンジン、つまり FlowSpec、Tool contract、コンパイラー、Rider、Journal はcore にあり、自身のインターフェースだけに依存します。すべての launcher と backend はそれらのインターフェースの実装です。エンジンがクラウド SDK をインポートすることはありません。
core は自分自身のインターフェース以外に何も依存しません。sdk と yaml は core に依存します。それ以外はすべて内側に依存します。依存の矢印が core から外へ向かうことはありません。 これにより、同じ FlowSpec をどこでも実行し、再現できます。
core が何もインポートしないことは、なぜ重要なのですか?
core が何もインポートしないことは、なぜ重要なのですか?
それがポータビリティを支える仕組みだからです。
core は時計、RNG、ネットワーク、ファイルシステム、シークレット、store、journal に、注入されたインターフェース(Store、Clock、Random、Secrets、Logger、ToolHost、Journal)を通じてだけ到達します。そのため、Flow を実行する場所は、エンジンに触れるのではなく、実装を差し替えることで変えられます。クラウドはアダプターであり、依存関係ではありません(原則 T4)。実行時にモデルを使わないという保証は、どこから来るのですか?
実行時にモデルを使わないという保証は、どこから来るのですか?
同じレイヤリングから来ます。Rider には、制御フローを決めるためにモデルを呼び出すコードパスがありません。また、
core はそのような経路を追加し得るものを何もインポートしません。model Tool が存在する場合でも、それは記録済みの入力と出力を持つ通常の宣言された Tool です。オーサリング時の利便性であり、実行時の意思決定者ではありません。大きなプロセスは、どうすれば読みやすいままでいられますか?
大きなプロセスは、どうすれば読みやすいままでいられますか?
Flow は
composite Tool として再公開でき、別の Flow の中で単一の Step として呼び出せます。ネストは効果を隠しません。composite が宣言する capability は、内側の Flow が呼び出すすべての Tool の和集合です。また、シークレット入力は参照として渡され、最も内側の secrets capability を持つ Tool でだけ解決されます。ドメインモデル を参照してください。関連
ドメインモデル
Tool、Step、Flow、FlowSpec、Run、Pack、Registry という7つの名詞を、それぞれ一度だけ定義します。
FlowSpec & IR
正規化、digest アルゴリズム、参照がグラフの辺になる仕組み。
実行
スケジューリング、Step ライフサイクル、リトライ、冪等性、再開、リプレイ。
Launcher
CLI、REST、MCP、cron、CI にまたがって Rider を変更せずに実行する薄いホスト。