このページを終えるころには、小さな決定論的FlowをTypeScript SDKとYAMLの 両方で作成し、AIを介さずにローカルで実行できるようになります。その後、 その実行を検査し、オフラインでリプレイし、まったく同じFlowを HTTPエンドポイントとして再起動します。賢さが発揮されるのは 作成の時点であり、実行は素直な決定論的実行です。
1

最小限のFlowを作成する

Flowは一度だけ書きます。ここでは2つのサーフェスで示します。HTTP経由で JSONを取得し、それを純粋なtransformで整形する2手順のFlowです。どちらも、 同じcontent-addressed sha256 digestを持つ同一の正規化されたFlowSpecに コンパイルされます。そのdigestこそがバージョンです。
import { flow, http, transform } from "@browserflow/sdk";
import { z } from "zod";

export default flow("ip-info")
  .input("url", z.string().url())

  // 手順1: effectfulなHTTP tool。capabilityを持つ唯一の手順。
  .step("fetch", http.get((c) => c.input.url))

  // 手順2: 純粋なtransform。決定論的なJSON → JSONで、I/Oなし。
  .step("shape", transform((c) => ({
    ip: c.steps.fetch.output.ip,
    at: c.now,
  })))

  .output((c) => ({ ip: c.steps.shape.output.ip }));
flow: ip-info

inputs:
  - { name: url, type: string }

steps:
  - id: fetch
    use: http.get
    with: { url: ${{ input.url }} }

  - id: shape
    use: transform
    with:
      expr: { ip: ${{ steps.fetch.output.ip }}, at: ${{ now }} }

output: { ip: ${{ steps.shape.output.ip }} }
データエッジ fetch → shape は、c.steps.fetch.output への参照から 推論されます。needs を手で書くことはほとんどありません。c.now は 注入されたクロックで、リプレイ時にも決定論的なので、タイムスタンプまで 再現可能です。
片方のサーフェスがすでにあり、もう片方が必要ですか? browserflow emit flows/ip-info.yaml --to ts(または --to yaml)で IRを経由して往復変換できます。正規化されたemitterは決定論的なので、 GitにチェックインしたFlowのdiffは安定します。
2

CLIで実行する

日常的なinner loopは、1秒未満で、かつ破壊的でないことを意図しています。 まず型チェックしてdigestを表示し、次に --dry で実行を計画し、その後に 実際に実行します。
browserflow init                                          # 初回のみ: プロジェクトをscaffold
browserflow compile flows/ip-info.yaml --check            # 型 + digest、副作用なし
browserflow run flows/ip-info.yaml --input url=https://api.ipify.org?format=json --dry
browserflow run flows/ip-info.yaml --input url=https://api.ipify.org?format=json
  • --check は純粋です。型チェックしてdigestを表示するため、CIや pre-commitに最適です。固定されたToolの解決以外でネットワークに 触れることはありません。
  • --dry は実行を計画します。DAGを解決し、入力を検証し、どの手順が 実行されるはずか、どのeffectが実行されるはずかを、実際には effectを実行せずに表示します。
--yes なしの run は、これから実行するeffect(ネットワークホスト、 ファイル書き込み、spawn)を要約し、最初の外向きeffectの前に一度だけ 確認します。--dry と純粋なFlowでは確認は表示されません。
3

実行を検査してリプレイする

すべての実行はcontent-addressedで、リプレイ可能です。最新の実行を見つけ、 そのタイムラインを時間移動し、オフラインでリプレイできるポータブルな Journalを記録します。
browserflow inspect $(browserflow runs last)                    # タイムライン、手順、journal
browserflow run flows/ip-info.yaml \
  --input url=https://api.ipify.org?format=json \
  --record-journal ./fix/ip-info.journal.json
# 後で、どこでも、オフラインで:
browserflow replay ./fix/ip-info.journal.json --verify
記録されたJournalは、ポータブルで実行可能なfixtureです。--verify は hermeticに再実行し、すべての手順の出力がまだ一致することをassertします。 Toolのアップグレードで挙動が変わった場合、リプレイは最初に分岐した 手順ではっきり失敗します。これにより「このリファクタリングで何か 変わったか?」を1コマンドの決定論的チェックに変え、ライブ依存なしで CI上でFlowをテスト可能にします。
browserflow inspect <run-id> --step shape は、単一手順のマスク済み入力と Journal frameに直接移動します。シークレットはすべてのストリームで マスクされます。ログ、inspect、エラー、--dry の計画も同様です。
4

同じFlowを別の方法で起動する

同じFlowSpecは、どのLauncher上でも変更なしに実行されます。変わるのは、 環境に対してcapabilityをどう配線するかだけです。Bun上のHono経由で、 FlowをHTTPエンドポイントとして提供します。
browserflow serve --registry ./registry --port 8080
# POST /flows/ip-info/runs   { "url": "https://api.ipify.org?format=json" }  → Run
公開された各Flowは POST /flows/:name/runs になります。同じFlowは、 MCPサーバーとしてagent ecosystemに公開することもできます。Flowの型付き inputs は、MCPツールの入力スキーマに自動的になります。
browserflow mcp --registry ./registry        # stdio or SSE transport
Flowの結果は、どのfrontが呼び出したかには依存しません。同じRider、同じ digest、同じ結果です。その不変性がプロダクトです。

次に進む場所

コンセプトとドメインモデル

Flow、Step、Tool、Pack、Run、Registry、Launcher。以降のドキュメントが 土台とする語彙です。

オーサリング: SDKとYAML

両方のサーフェス、式言語、制御フロー、そして1つのIRを通じてそれらが どのように往復変換されるかを詳しく説明します。

CLIリファレンス

完全なコマンドマップ、inner loop、ワークフローとしての再現性、 そして安全なデフォルト。

Launcherとポータビリティ

CLI、REST、MCP、cron、CI、container、edge。1つのエンジン、多くのホスト。