mcpField
W
write-flow

write-flow

github.com/windmill-labs開発541 回インストール1 日前に更新
リポジトリ

write-flow について

write-flowは、Windmill CLIでWindmillのワークフローを作成・テストするAIエージェント向けガイドです。正しい初期化と構造ルールを示し、ユーザーの意図に応じてローカルプレビューとデプロイを使い分けます。

主な機能

  1. 01`wmill flow new`による初期化
  2. 02OpenFlowルールに沿ったモジュール定義
  3. 03全体または単一ステップのプレビュー選択
  4. 04ローカルメタデータとロックファイルの再生成
  5. 05テストとデプロイの分離

活用シーン

  1. 01指定パスと概要でWindmillワークフローを作成
  2. 02デプロイせずにローカル変更をテスト
  3. 03編集中に単一モジュールを検証
  4. 04インラインスクリプトのメタデータを更新

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/windmill-labs/windmill-cli-docs --skill write-flow

インストール後、Claude Code で/write-flowを入力して読み込まれたか確認します。

詳細

Windmill Flow CLI ガイド

Flow の作成

AI エージェントであるあなた自身が、適切なフラグを付けて wmill flow new <path> を実行し、フローのひな形を作成します。フォルダーと flow.yaml を手動で作成してはいけません。また、ユーザーに「wmill flow new を実行して、プロンプトに従ってください」と伝えてはいけません。

wmill flow new は、正しいサフィックス(ワークスペースの nonDottedPaths 設定に応じて __flow または .flow)を付けてフォルダーを作成し、最小限の flow.yaml のひな形を書き込み、Claude 固有の次の手順に関するヒントを表示します。手動でひな形を作成すると、これらがすべて省略され、サフィックスも誤りがちです。

Step 1 — ユーザーに尋ねてパスと概要を確認する

必要な情報は次の 2 つです。

  1. path — windmill のパスです。例:f/folder/my_flow または u/username/my_flow。
  2. summary — フローの簡単な説明です。

ユーザーの依頼に両方の情報が含まれていない場合は、1 回のやり取りで両方を尋ねます。実行環境で利用できる対話型の質問機能(利用可能であれば構造化された複数選択ツール、そうでなければ通常のチャット)を使い、それぞれに 1 つまたは 2 つの入力例と、「その他」/自由入力の選択肢を用意します。パスや概要を推測してはいけません。

Step 2 — 自分でコマンドを実行する
wmill flow new f/folder/my_flow --summary "Short description"

概要とは別に残す価値のある詳しい説明をユーザーから受け取っている場合は、--description "..." を追加します。

Step 3 — flow.yaml を記入する

生成された flow.yaml(コマンドが作成したフォルダー内)を開き、空の value.modules と schema を実際のフロー定義に置き換えます。

rawscript モジュールでは、コンテンツキーに !inline path/to/script.ts を使用します。インラインスクリプトファイルの名前に .inline_script. を含めてはいけません(例:a.inline_script.ts ではなく a.ts を使用します)。

フローに実際の内容が入ったら、次の手順としてビジュアルプレビューを開くことを一文で提案します(例:「ビジュアルプレビューを開きますか?」)。自動的に開いてはいけません。開発ページを開くと、ブラウザーウィンドウや launch.json のエントリなどの副作用が発生するため、ユーザーの同意が必要です。

避けるべきアンチパターン
  • ❌ wmill flow new を実行せずに __flow フォルダーと flow.yaml を手動で作成すること。サフィックス設定の解決、既定の構成、Claude のヒントが省略されます。
  • ❌ ユーザーに「wmill flow new <path> を実行してください」と伝えること。自分で実行できますし、実行するべきです。
  • ❌ ユーザーに尋ねずにパスや概要を作り出すこと。

CLI コマンド — 実行、プレビュー、デプロイ

記述した後は、コマンドを列挙するだけでなく、ユーザーの意図に沿って操作してください。適切な場合は、こちらで wmill flow preview を実行してください(以下の「記述後 — 待つのではなく、実行を申し出る」を参照)。wmill generate-metadata はローカルのロック/ハッシュファイルを再生成します(デプロイではありません)が、依存関係を再解決します。プロジェクトの AGENTS.md でメタデータの自動実行が許可されていない限り、実行を提案し、合意を得てから実行してください。デプロイである wmill sync push は名前を挙げるだけにして、ユーザーの承認を待ってください。選択肢は次のとおりです。

  • wmill flow preview <flow_path> — ローカルフローを反復編集するときのデフォルトです。 デプロイせずに、ローカルの flow.yaml をローカルのインラインスクリプトに対して実行します。PathScript ステップでローカルファイルの代わりにデプロイ済みのワークスペーススクリプトを使用するには、--remote を追加します。モジュールを1つだけ単独で実行するには、--step <step_id> を追加します(以下の「単一ステップのプレビューとフロー全体のプレビュー」を参照)。
  • wmill flow run <path> — ワークスペースにすでにデプロイされているフローを実行します。デプロイ済みバージョンのテストをユーザーが明示的に希望している場合に限って使用してください。ローカルの編集内容には使用しないでください。
  • wmill generate-metadata — フローとそのインラインスクリプトの古くなったローカル .lock ファイルを再生成し、wmill-lock.yaml 内のコンテンツハッシュを更新します。ローカルファイルのみを書き換えます(デプロイではありません)。インポートまたは引数を変更するインラインスクリプトを編集した後に実行し、wmill-lock.yaml がずれて git-sync/CI に不要なノイズが追加されないようにしてください。デフォルトではワークスペース全体のスクリプト、フロー、アプリをスキャンしますが、古くなったものだけを再生成します。対象を編集したフローに絞るには、そのフローのフォルダーを引数として渡すか、そのサブディレクトリから実行してください。変更された共有スクリプトをインポートするフロー(またはスクリプト)も対象になることに注意してください。適用前に何が古くなっているか、その理由(content changed か depends on <path> か)を正確に確認するには、wmill generate-metadata --dry-run を実行してください。
  • ローカルの変更をワークスペースにデプロイします — リポジトリの設定に応じて、git push または wmill sync push を使用します(AGENTS.wmill.md のデプロイセクションを参照)。ユーザーがデプロイ/公開/プッシュを明示的に希望した場合に限って、デプロイを提案または実行してください。「実行」「試す」「テストする」と言われただけの場合は、デプロイしないでください。
プレビューと実行 — 習慣ではなく、意図に応じて選ぶ

ユーザーが「フローを実行して」「試して」「テストして」「動くか確認して」と言い、flow.yaml にローカルの編集内容がある場合は、flow preview を使用してください。フローをプッシュしてから flow run を実行してはいけません。プッシュはデプロイであり、テストのためだけにデプロイすると、未テストの変更でワークスペースのバージョンが上書きされます。

flow run を使用するのは、次の場合に限ります。

  • ユーザーが「デプロイ済みのバージョンを実行して」/「サーバー上のものを実行して」と明示的に指示した場合。
  • 編集中のローカル flow.yaml がなく、既存のフローを呼び出すだけの場合。

sync push を使用するのは、次の場合に限ります。

  • ユーザーがデプロイ、公開、プッシュ、またはリリースを明示的に希望した場合。
  • プレビューで変更がすでに検証されていて、ユーザーがそれをワークスペースに反映したい場合。
単一ステップのプレビューとフロー全体のプレビュー

ユーザーが1つのモジュールを反復編集しており、検証対象にフローの上流ステップが含まれない場合は、flow preview <flow_path> --step <step_id> を使用してください。そのステップの実行可能なもの(rawscript の場合はインラインスクリプト、script の場合は PathScript〔利用可能であればローカルのもの〕、flow の場合はパスで指定するサブフロー)だけを実行するため、前のステップに時間や費用がかかる場合、フロー全体を実行するより大幅に速くなります。ステップ ID は、入れ子になった branchone/branchall/forloopflow/whileloopflow モジュールをたどって解決されます。また、特別な preprocessor モジュールと failure モジュールも含まれます。

各ステップが互いの出力に依存する場合、ユーザーが全体の制御フローを検証している場合、または --step を適用できない場合は、flow preview <flow_path>(--step なし)を使用してください。branchone、branchall、forloopflow、whileloopflow、identity、および AI エージェントの各ステップは、それ自体を単独でテストできません。ただし、branchone/branchall/forloopflow/whileloopflow の場合は、内部のステップ ID を渡せば、その中に含まれるステップをテストできます。

作成後 — 実行を提案し、受け身で待たない

これはプログラムによる実行(wmill flow preview -d '<args>')についての説明です。実際にフローを実行するため、副作用が発生します。ビジュアルプレビュー(preview スキル)は別途提案します。下の「ビジュアルプレビュー」を参照してください。

ユーザーがまだフローの実行やテストを依頼していない場合は、次のステップとして1文で提案してください(例:「サンプル引数を使って wmill flow preview を実行しますか?」)。複数の選択肢を並べてはいけません。

ユーザーが最初のリクエストですでにフローのテスト、実行、試行を依頼している場合は、提案を省略し、フローの入力スキーマから妥当な引数を選んで wmill flow preview <path> -d '<args>' を直接実行してください。

スキーマでリソースとして型指定された入力(format: resource-<type>)には、値全体として "$res:<path>" という文字列を指定します。例:-d '{"db": "$res:f/databases/postgres_prod"}'。{"db": {"$res": "..."}} や通常のパスを指定するのではありません。変数も同様で、"$var:<path>" を指定します。resources スキルを参照してください。

wmill flow preview は安全に実行できます(デプロイは行いません)。wmill generate-metadata もデプロイは行いません(ローカルのロック/ハッシュファイルを書き込むだけです)が、依存関係を再解決します。提案したうえで、ユーザーの同意を得てから実行してください。ただし、プロジェクトの AGENTS.md でメタデータの自動生成が許可されている場合は除きます。実行後は再生成された .lock の差分を確認し、インラインスクリプトのどの依存関係のバージョンが変わったかをユーザーに伝えて、デプロイ前に意図しない更新がないか確認できるようにしてください。デプロイを行うのは wmill sync push だけです。ユーザーが明示的に依頼した場合に限り実行してください。

ビジュアルプレビュー

開発ページでフローを視覚的に表示する(グラフ+ライブリロード)には、preview スキルを使用してください。自動で開くのではなく、次のステップとして必ず1文で提案してください(例:「ビジュアルプレビューを開きますか?」)。開発ページを開くと副作用(ブラウザーウィンドウの表示や、MCP-preview ブランチでの launch.json エントリーの追加など)が発生するため、ユーザーの同意が必要です。ユーザーが最初のリクエストですでにフローの表示、プレビュー、可視化を依頼している場合は、提案を省略してスキルを呼び出してください。

Windmill フロー構築ガイド

OpenFlow スキーマ

OpenFlow スキーマ(openflow.openapi.yaml)はフロー構造の信頼できる唯一の情報源です。完全な型定義については OPENFLOW_SCHEMA を参照してください。

予約済みモジュール ID

  • failure - 失敗ハンドラーモジュール用に予約済み
  • preprocessor - プリプロセッサーモジュール用に予約済み
  • Input - フロー入力参照用に予約済み

構造上の厳格なルール

以下は Windmill スキーマの厳格なルールです。必ずそのとおりにしてください。

  • value.modules は通常の順次ステップにのみ使用します
  • value.preprocessor_module と value.failure_module は、value 内の特別なトップレベルフィールドであり、value.modules のエントリーではありません
  • フローでプリプロセッサーが必要な場合は、id: preprocessor を指定して value.preprocessor_module を作成します
  • フローで失敗ハンドラーが必要な場合は、id: failure を指定して value.failure_module を作成します
  • preprocessor または failure という名前の通常モジュールを value.modules 内に作成してはいけません
  • preprocessor_module と failure_module で使用できるのは script または rawscript のみです
  • preprocessor_module は通常のモジュールより先に実行され、results.* を参照できません
  • failure_module では、error.message、error.step_id、error.name、error.stack を含む error オブジェクトを使用できます
  • failure_module が実行されたフローは、ハンドラーが recover: true を含むオブジェクトを返さない限り、失敗として終了します。その場合、フローは成功として終了します。失敗したステップがループ、分岐、またはサブフロー内にある場合も同様です。recover によって実行されるステップが変わることはありません。ループや分岐が失敗後も続行するかどうかは、引き続きそれぞれの設定(skip_failures、continue_on_error)によって決まります

正しい形式:

value:
  preprocessor_module:
    id: preprocessor
    value:
      type: rawscript
      ...
  failure_module:
    id: failure
    value:
      type: rawscript
      ...
  modules:
    - id: process_event
      value:
        type: rawscript
        ...

誤った形式:

value:
  modules:
    - id: preprocessor
      ...
    - id: process_event
      ...
    - id: failure
      ...

モジュール ID のルール

  • フロー全体で一意である必要があります
  • スペースではなくアンダースコアを使用します(例:fetch data ではなく fetch_data)
  • ステップの目的が伝わる説明的な名前を使用します

AI エージェントモジュール

aiagent モジュールは、ツールを呼び出せる LLM を実行します。value.tools の各エントリは、追加の value.tool_type を持つモジュール形式のオブジェクトです。script/flow ツールには flowmodule、MCP サーバーツールには mcp、ウェブ検索には websearch、組み込みの ask_question ツールには question を指定します(エージェントは停止し、実行ページまたはチャットから誰かが回答するまでワーカーを占有しません。秒単位の任意の value.timeout のデフォルトは 1800 です)。flowmodule または mcp ツールに requires_approval: true を設定すると、実行前に各呼び出しについて人が承認または拒否できます。

{
  "id": "support_agent",
  "summary": "AI agent for customer support",
  "value": {
    "type": "aiagent",
    "input_transforms": {
      "provider": {
        "type": "static",
        "value": { "kind": "openai", "resource": "$res:f/ai_providers/openai", "model": "gpt-4o" }
      },
      "output_type": { "type": "static", "value": "text" },
      "user_message": { "type": "javascript", "expr": "flow_input.query" },
      "system_prompt": { "type": "static", "value": "You are a helpful assistant." }
    },
    "tools": [
      {
        "id": "search_docs",
        "summary": "search_documentation",
        "description": "Search the product documentation. Use it whenever the user asks how a feature works.",
        "value": {
          "tool_type": "flowmodule",
          "type": "rawscript",
          "language": "bun",
          "content": "export async function main(query: string) { return ['doc1', 'doc2']; }",
          "input_transforms": { "query": { "type": "static", "value": "" } }
        }
      }
    ]
  }
}
  • provider はリソース文字列だけではなく、オブジェクトです。{ "kind": <provider kind>, "resource": "$res:<path>", "model": <model id> } の形式です。モジュールが value.agent を通じて保存済みエージェントにリンクされている場合を除き、必須です。フォームからフローを実行する場合は静的な設定が適しています。チャットフローでは、代わりにフィールドをフロー入力に接続します。詳細は以下を参照してください。
チャットモードのフロー

value.chat_input_enabled: true のフローは、フォームではなくチャットから実行されます。入力欄からターンごとに 1 つのメッセージが送信され、会話が表示されます。エージェントが読み取る、必須の文字列入力 user_message が必要です。入力欄で編集されないその他のフロー入力は、[入力の設定]で質問されます。

静的な provider では、モデルを変更できないチャットになります。 代わりにフロー入力から値を渡してください。方法は 2 つあります。オブジェクト全体を保持する 1 つの入力("expr": "flow_input.model_config")を使うと、すべてのフィールドを編集できます。または、フィールドごとに接続して、一部を固定し、その他を公開します。チャットから書き込めるフィールドは、入力欄にプロバイダー選択、モデル一覧、思考の制御などのコントロールとして表示されます。静的なままのフィールドは固定され、コントロールは表示されません。例外は kind です。プロバイダーは resource と組み合わせて選択されるため、入力欄から kind を書き込むのは resource と一緒の場合のみです。そのため、kind 入力だけを接続すると、[入力の設定]で引き続き質問され、実行に必要なものが到達不能になることはありません。

{
  "id": "chat_agent",
  "value": {
    "type": "aiagent",
    "input_transforms": {
      "provider": {
        "type": "javascript",
        "expr": "({ kind: 'anthropic', resource: '$res:f/ai/claude', model: flow_input.model, reasoning_effort: flow_input.thinking })"
      },
      "user_message": { "type": "javascript", "expr": "flow_input.user_message" },
      "user_attachments": { "type": "javascript", "expr": "flow_input.files" },
      "memory": { "type": "static", "value": { "kind": "compaction" } },
      "streaming": { "type": "static", "value": true },
      "output_type": { "type": "static", "value": "text" }
    },
    "tools": []
  }
}
  • フィールドごとに接続する場合は、値がリテラルまたはそのままの flow_input.x 参照である、1 つのオブジェクトリテラルを使います。スプレッド、呼び出し、計算されたキーを使うと、入力欄はどの入力がどのフィールドに渡されるかを判別できないため、コントロールは一切表示されません。オブジェクト全体に対するそのままの flow_input.x は、すべてのフィールドを保持する 1 つの入力として読み取られます
  • 保存済みエージェントにリンクされたステップ(agent が設定済み)には、独自の provider はありません。model と reasoning_effort の入力を通じて、同じ 2 つのコントロールを公開し、エージェントに保存された設定を置き換えます。"model": { "type": "javascript", "expr": "flow_input.model" } のように指定します。モデルが空なら保存済みのモデルが維持され、思考の強度が空なら何も送信されません。プロバイダーのリソースは常にエージェントのものが使われます
  • エージェントが前のターンを参照できるようにするには、memory が必要です。これがないと、メッセージごとに何もない状態から始まります
  • streaming をオンにすると、回答と思考が一度にすべてではなく、トークンごとに表示されます
  • user_attachments は、S3 オブジェクトの配列として型指定されたフロー入力を参照します({ "type": "array", "items": { "type": "object", "resourceType": "s3object" } })。これにより、メッセージに添付されたファイルがエージェントに届きます
  • 実行には、ターンが属する会話を指定する memory_id クエリパラメーター(フロー引数ではありません)が必要です。新しい UUID を使うと会話が開始され、同じ UUID を再利用すると会話が続きます。チャットではこの値が自動的に渡されます。その他の方法で実行する場合は、値を渡す必要があります。渡さないと、サーバーはジョブを拒否します
ツールの命名規則

これらの規則は、エージェントが名前で呼び出す flowmodule ツールを対象とします。websearch ツールや question ツールの summary は単なるラベル(Web Search)であり、mcp ツールは MCP サーバー独自のツール名を公開するため、いずれも名前のチェック対象にはなりません。これらの summary はそのままにしてください。

  • flowmodule ツールの summary は、人間向けのラベルではなく、エージェントが呼び出す名前です。人間向けの説明は description に記載してください
  • summary は ^[a-zA-Z0-9_]+$ に一致する必要があります。使用できるのは英字、数字、アンダースコアのみです。スペース、ハイフン、ピリオド、アクセント記号は使用できません。Search documentation ではなく、search_documentation にしてください
  • 必ず summary を設定してください。エージェントのツール間で一意である必要があり、予約済み ID(do、bg、ctx、state、if、else、for、delete、while、new、in、failure、preprocessor、as、Input、Result、Trigger)は使用できません
  • 使用可能な文字以外を含むツール名をエージェントに提供すると、そのツールを提供する実行はすべて Invalid tool name で失敗します。wmill lint <flow folder> を実行すると、実行開始前に報告されます
  • ツールの id にも、モジュール ID と同じ規則が適用されます。フロー全体で一意である必要があり、スペースではなくアンダースコアを使用してください
  • description は任意の自由記述で、ツールをいつ、どのように呼び出すかをエージェントに伝えます。名前だけでは明らかでない場合は設定してください。基になるスクリプトから導出される説明よりも優先されます

AI Decision モジュール

aidecision モジュールは、判断モデル(TypeSafe の Jev、Cloudflare の Clef、または OpenAI の Decisions API)に state について型付きの質問をし、テキストではなく、調整済みの確率でそれぞれに回答します。ツールも自由記述も必要としない判断(分類、振り分け、スコア付け、またははい/いいえの確認)を行うステップでは、aiagent よりこちらを優先してください。処理が速く、コストも低く、回答の形式が固定されています。

{
  "id": "triage",
  "summary": "Classify the ticket",
  "value": {
    "type": "aidecision",
    "input_transforms": {
      "provider": {
        "type": "static",
        "value": { "kind": "typesafe", "resource": "$res:f/ai/typesafe", "model": "jev-latest" }
      },
      "state": { "type": "javascript", "expr": "flow_input.message" },
      "questions": {
        "type": "static",
        "value": {
          "intent": {
            "type": "choice",
            "instructions": "What does the customer want?",
            "criteria": { "refund": "Money back", "bug": "Something is broken", "other": "Anything else" }
          },
          "urgency": {
            "type": "score",
            "instructions": "How urgent is the ticket?",
            "criteria": ["Can wait", "This week", "Today", "Right now"]
          },
          "angry": { "type": "noul", "instructions": "Is the customer angry?" }
        }
      }
    }
  }
}
  • provider.kind は typesafe(バージョンを固定しない場合、model は jev-latest)、cloudflare(model は clef、より高速な回答には clef-flash)、または openai(model は gpt-6-luna。チャットモデルは使用しません)です。リソースも同じ種類のものを指定してください
  • state は評価対象の内容で、通常は分類するメッセージなどのテキストです。複数の値を組み合わせるには、質問に必要な値だけを説明的なキーに格納したオブジェクトを渡してください(({ message: flow_input.message, plan: results.get_account.plan }))。文字列の配列も使用できます
  • questions は、各質問名を { type, instructions, criteria } に対応付けます。
    • choice:criteria は各選択肢をその説明に対応付けます(最大255個の選択肢)。回答には choice、probabilities、confidence が含まれます
    • score:criteria は2~10個の段階の説明を順序付きで並べた配列です。回答には score、legend、probabilities、confidence が含まれます
    • noul:はい/いいえ形式です。criteria には任意で { "true": ..., "false": ... } の説明を指定できます。回答には noul が含まれ、はいである確率が0から1の範囲で示されます
  • 結果は { output, model, usage } で、output のキーは質問名です。そのため、後続のステップでは results.triage.output.intent.choice、results.triage.output.urgency.score、または results.triage.output.angry.noul > 0.7 のように読み取ります
  • openai では、同じ questions が Decisions API 用に変換され、回答も同じ方法で読み取れます(choice、score、noul)。ただし、probabilities は { value, probability } のリスト(スコアの場合は label も含む)であり、スコアに legend はありません。OpenAI が回答を拒否した質問があると、ステップは失敗します。ユーザーメッセージの配列である state([{ role: "user", content: [{ type: "input_text", text }, { type: "input_image", image_url: "data:image/png;base64,..." }] }])はそのまま送信され、画像を評価する場合はこの形式を使用します。それ以外のオブジェクトや配列は JSON テキストとして送信されます
回答に基づく分岐

回答に応じて処理を振り分けるには、判定の直後に branchone を配置し、各選択肢に1つずつ分岐を設け、それぞれの expr で判定を ID によって参照します。

{
  "id": "route",
  "value": {
    "type": "branchone",
    "branches": [
      { "summary": "refund", "expr": "results.triage.output.intent.choice === 'refund'", "modules": [...] },
      { "summary": "bug", "expr": "results.triage.output.intent.choice === 'bug'", "modules": [...] }
    ],
    "default": [...]
  }
}

はい/いいえの質問では、"expr": "results.triage.output.angry.noul >= 0.5" を指定した分岐を1つ用意し(しきい値は必要に応じて調整してください)、default を「いいえ」の経路にします。

エージェントツールとして

aidecision は、aiagent の flowmodule ツール("tool_type": "flowmodule", "type": "aidecision")として使用できます。state を { "type": "ai" } に設定すると、呼び出し元のモデルが値を指定し、output のみがモデルに返されます。summary にはツールの命名規則が適用されます。これを呼び出せるのは、フロー自身のエージェントステップのみであり、ツールとして使用されているエージェントからは呼び出せません。

よくある間違いとその回避方法

  • input_transforms がない:指定しないと、Rawscript のパラメーターに値が渡されません
  • 後続のステップを参照する:results.step_id が機能するのは、現在のステップより前に実行されるステップのみです
  • モジュール ID の重複:フロー内の各モジュール ID は一意である必要があります
  • AI エージェントの flowmodule ツール名にスペースが含まれている:summary がツール名となり、使用できるのは英字、数字、アンダースコアのみです

ステップ間のデータフロー

  • flow_input.property - フローの入力パラメーターにアクセスします
  • results.step_id - そのステップの結果がスコープ内にある場合に限り、前のステップの出力にアクセスします
  • results.step_id.property - そのステップの結果がスコープ内にある場合に限り、前のステップの出力から特定のプロパティにアクセスします
  • flow_input.iter.value - forloopflow 内の現在の反復値です。whileloopflow 内では反復インデックスのみを表します(通常の数値で、flow_input.iter.index と同じです)
  • flow_input.iter.index - ループ(forloopflow または whileloopflow)内の現在のループインデックスです
  • suspend ステップ(承認)の後、次のステップの JavaScript 式では以下も使用できます:
    • resume - 直近の再開ペイロード(再開フォームの値)です。continue_on_disapprove_timeout を指定した場合、拒否またはタイムアウト時には代わりに { error: { name: "SuspendedDisapproved" | "SuspendedTimedOut", message } } が返されます
    • resumes - 到着順に並んだ、すべての再開ペイロードです
    • approvers - 再開ごとに1つの文字列を含む通常の配列です。getResumeUrls(approver) の resume/cancel URL を介して再開した場合は、そこで渡された approver(指定されている場合)が含まれます。それ以外(approvalPage リンクを含む)の場合は、再開したユーザーのユーザー名が含まれます。ユーザー名がない場合は "anonymous" となります。例:approvers[0]。フローのステータスに保存される { resume_id, approver } オブジェクトではないため、approvers[0].approver は常に undefined です

ループ構造のルール

  • forloopflow は、配列を返す JavaScript 式(例:results.get_items)である iterator の各要素に対して、modules を 1 回ずつ実行します。parallel: true を指定すると各反復が並行して実行され、skip_failures: true を指定すると失敗した反復をスキップして続行します
  • whileloopflow のループを終了するには、モジュールレベルの stop_after_if を使います。ループモジュール自体、または内側のステップに指定します(そのステップが自身の results を介して状態を保持する場合は、以下の説明のとおり内側のステップに指定する必要があります)
  • stop_after_if は、フローモジュール上で id および value と同じ階層に必ず配置します。ループの value オブジェクトの直接のキーにしてはいけません
  • stop_after_all_iters_if は、ループ全体の終了後にチェックするためのものであり、通常の各反復の終了条件には使いません
  • stop_after_if は各反復の後に評価されます。ループモジュールに指定した場合、result はその反復の結果(最後のステップが返した値)です。内側のステップに指定した場合、result はそのステップの結果です
  • whileloopflow の flow_input.iter.value は反復インデックス(flow_input.iter.index と同じ数値)にすぎず、状態を保持することはありません。そのため、flow_input.iter.value.<field> は常に未定義であり、これに依存する終了条件を持つループは終了しません
  • 反復間で状態を保持するには、ステップで自身の前回の反復結果を results.<its_own_id> から読み取り、初回の反復用のフォールバックを指定します(例:results.b ?? flow_input.start)。ただし、この場合、ループの stop_after_if はループモジュールではなく、必ずその内側のステップに指定します。終了条件をループモジュールに置いた、通常のステップが 1 つだけの本体は、results.<step_id> がすべての反復で null になる高速パスで実行され、ループが終了しません(ステップが 2 つ以上ある本体、または 1 つだけのステップに独自の stop_after_if、リトライなどがある本体では、stop_after_if の配置に関係なく、反復間で results が解決されます)
  • 単なるカウンター状態を保持する場合は、代わりにインデックスから算出します(例:flow_input.iter.index + 1)。これは、stop_after_if をループモジュールに指定する場合も含め、どの構成でも機能します
  • ループ後に最終的なスカラー値またはオブジェクトが必要な場合は、ループ結果の配列全体を返すのではなく、ループの後に通常のステップを追加して最終値を取り出します

正しい whileloopflow の構造:

- id: loop_until_done
  stop_after_if:
    expr: result.done === true
    skip_if_stopped: false
  value:
    type: whileloopflow
    skip_failures: false
    modules:
      - id: advance_state
        value:
          type: rawscript
          input_transforms:
            count:
              type: javascript
              expr: flow_input.iter.index + 1
- id: return_final_state
  value:
    type: rawscript
    input_transforms:
      final_state:
        type: javascript
        expr: results.loop_until_done[results.loop_until_done.length - 1]

results を介して状態を保持する正しい whileloopflow の構造(終了条件は内側のステップに指定):

- id: loop_until_done
  value:
    type: whileloopflow
    skip_failures: false
    modules:
      - id: advance_state
        stop_after_if:
          expr: result.done === true
          skip_if_stopped: false
        value:
          type: rawscript
          input_transforms:
            state:
              type: javascript
              expr: results.advance_state ?? flow_input.initial_state

誤った whileloopflow のパターン:

- id: loop_until_done
  value:
    type: whileloopflow
    stop_after_if:
      expr: result.done === true
input_transforms:
  state:
    type: javascript
    # iter.value is a number (the iteration index); there is no previous-iteration state
    expr: flow_input.iter.value.count
input_transforms:
  final_state:
    type: javascript
    expr: results.loop_until_done

承認/一時停止の構造

承認ステップは通常の script ステップ(type: rawscript または type: script)であり、モジュールレベルの suspend を追加して承認ステップにします。このスクリプトは wmill.getResumeUrls(approver) を呼び出して、秘密の再開/キャンセル URL を生成し、承認者(Slack、メールなど)に送信するか、実行ページから承認できるように、それらの URL を返します。

  • suspend は、フローモジュールオブジェクト上で id および value と同じ階層に配置します
  • suspend を value の内側に配置してはいけません
  • 承認ステップに type: identity を使用しないでください。identity ステップは一時停止しますが、再開 URL を生成しないため、承認者が操作するリンクを持てず、機能する承認にはなりません

正しい構造:

- id: request_approval
  suspend:
    required_events: 1
    resume_form:
      schema:
        type: object
        properties:
          comment:
            type: string
        required: [comment]
  value:
    type: rawscript
    language: bun
    input_transforms:
      approver:
        type: static
        value: ''
    content: |
      import * as wmill from "windmill-client"

      export async function main(approver?: string) {
        const urls = await wmill.getResumeUrls(approver)
        // send urls.resume / urls.cancel to the approver(s), e.g. via Slack or email
        return urls
      }

誤った構造(suspend が value の内側に誤配置されています):

- id: request_approval
  value:
    type: rawscript
    suspend:
      required_events: 1

誤った構造(identity は再開 URL を生成しないため、実際の承認ではありません):

- id: request_approval
  suspend:
    required_events: 1
  value:
    type: identity

ブランチ結果のスコープルール

  • branchone は、branches のうち expr が true となる最初のブランチを順に実行し、該当するものがない場合は default モジュールを実行します。branchall はすべてのブランチを実行します(parallel: true の場合は並行して実行します)。
  • ブランチ内では、外側の先行ステップと同じブランチ内の先行ステップを参照できます。
  • branchone の外では、そのブランチまたはデフォルトブランチ内にしか存在しないステップの ID を参照してはいけません。代わりに results.<branchone_module_id> を使用します。
  • branchall の外では、そのブランチ内のステップの ID を参照してはいけません。代わりに results.<branchall_module_id> を使用します。
  • ブランチの後続ステップで安定したデータ構造が必要な場合は、各ブランチから同じフィールドを返すようにします。
  • 必要に応じて、ブランチの直後に正規化ステップを追加し、そのステップで results.<branch_module_id> を使用します。

branchone の後で正しい例:

- id: route_order
  value:
    type: branchone
    ...
- id: send_confirmation
  value:
    input_transforms:
      routed:
        type: javascript
        expr: results.route_order

branchone の後で誤った例:

expr: results.create_shipment
expr: results.create_backorder

branchall の後で正しい例:

- id: enrich_parallel
  value:
    type: branchall
    parallel: true
    ...
- id: combine_data
  value:
    input_transforms:
      enrichments:
        type: javascript
        expr: results.enrich_parallel

入力変換

すべての rawscript モジュールには、関数のパラメーターを値にマッピングする input_transforms が必要です。

静的変換(固定値): {"param_name": {"type": "static", "value": "fixed_string"}}

JavaScript 変換(動的な式): {"param_name": {"type": "javascript", "expr": "results.previous_step.data"}}

リソース参照

  • フロー入力の場合:型に "object" を指定し、形式に "resource-{type}"(例:"resource-postgresql")を使用します。
  • ステップ入力の場合:静的値 "$res:path/to/resource" を使用します。

既存のスクリプトとフローの再利用

ユーザーから新しいコードを求められていない限り、コードを記述する前に、ステップの処理をすでに行うワークスペースのスクリプトまたはフローがないか確認し、ロジックを rawscript にコピーせず、パスを指定して再利用します。

  • ワークスペースのスクリプト:path を持つ type: script(例:f/folder/send_email)
  • ワークスペースのフロー:サブフローとして実行する、path を持つ type: flow
  • Hub スクリプト:hub/<version>/<app>/<name> パスを持つ type: script

再利用するアイテムの入力を input_transforms で網羅する必要があるため、まず入力スキーマを確認します。ローカルツリー(各スクリプトの隣にある .script.yaml に入力スキーマが記載され、各フローフォルダーには flow.yaml があります)とワークスペースで、wmill script list / wmill flow list を使って候補を探します。wmill script get <path> と wmill flow get <path> でアイテムの詳細を確認できます。

AI 向けの追加プロンプト

フローの入力スキーマには、スクリプトと同様に、入力を選ぶ AI に対する作成者の指示として、トップレベルの prompt_for_ai 文字列を含めることができます。そのフローを実行する引数を選ぶときはこの指示に従い、スキーマを書き換える場合も保持してください。

フローの整理:グループとノート

グループとノートは、エディターでのフローの見え方を整えるものであり、フローの動作には影響しません。

特に指示されなくても、重要なフローはすべてグループに分割してください。 フローに数ステップを超える手順がある場合や、連続するステップが「取得」「変換」「通知」などの段階を構成する場合は、グループにまとめ、意味のあるステップがすべていずれかのグループに属するようにしてください。ノートは、フロー全体に関する情報で、ステップの範囲に属さないものに限って控えめに使用してください。たとえば、フローの目的、重要な前提、警告、TODO などです。通常はノートが 1 つあれば十分です。ステップのまとまりにノートを付けるのは避けてください。その用途にはグループを使います。

value.groups にはグループが列挙され、それぞれが start_id から end_id までのステップを含みます。

  • start_id、end_id(必須):グループの最初と最後のステップの ID。同じ ID を指定すると、1 ステップだけのグループになります
  • summary:グループのタイトル
  • note:タイトルの下に表示される Markdown
  • color:yellow、blue、green、purple、pink、orange、red、cyan、lime、gray のいずれか。16 進数コードや CSS の色は指定できません。省略すると、エディターが色を選びます
  • autocollapse:true にすると、グループはデフォルトで折りたたまれた状態で表示されます

グループが以下のルールに違反しているフローは、エディターで描画できません。

  • start_id と end_id は同じリスト内のステップである必要があります。両方とも最上位にあるか、同じループ本体または分岐内にある必要があります。グループにループまたは分岐のステップ全体を含めることはできますが、その外側から始めて内側で終えることはできません
  • そのリスト内で、start_id は end_id より後に配置できません
  • グループは入れ子にできますが(片方がもう片方の中に完全に含まれる状態)、部分的に重なってはいけません。また、2 つのグループが start_id と end_id の両方を共有してはいけません
  • グループに含められるのは通常のステップだけです。preprocessor、failure、Input、Result、Trigger、AI エージェントのツールは含められません

value.notes には付箋が列挙されます。それぞれに、一意の id、Markdown の text、同じリストから選んだ color、および type: free が必要です。group のノートタイプは非推奨です。代わりに value.groups を使用してください。 各ノートには position({ x, y })と size({ width, height })を設定してください。設定しない場合、エディターはノートを原点に描画し、サイズを変更できません。x: -400 と width: 275 を指定すると、グラフの横に配置できます。

最終的な構造のセルフチェック

フローを完成させる前に、以下を確認してください。

  • preprocessor が value.preprocessor_module にある
  • failure handler が value.failure_module にある
  • approval ステップにモジュールレベルの suspend がある
  • 分岐の外側にある下流のステップが、分岐内のステップ ID を参照していない
  • すべての AI エージェントの flowmodule ツールに、英字、数字、アンダースコアのみで構成される一意の summary がある
  • すべてのグループが同じリスト内のステップから始まり、そこで終わっている。開始位置が終了位置より前であり、部分的に重なることなく入れ子になっている
  • wmill lint <flow folder> でエラーが報告されない

S3 オブジェクト操作

Windmill には、S3 互換ストレージ操作のサポートが組み込まれています。

フローの入力として S3 オブジェクトを受け取るには、次のようにします。

{
  "type": "object",
  "properties": {
    "file": {
      "type": "object",
      "format": "resource-s3_object",
      "description": "File to process"
    }
  }
}

フローでのリソースの使用

Windmill では、認証情報と設定はリソースに保存されます。リソースタイプによって、リソースの形式が定義されます。

フロー入力として使用する場合

フロースキーマで、プロパティの型を "object" に、フォーマットを "resource-{type}" に設定します。

{
  "type": "object",
  "properties": {
    "database": {
      "type": "object",
      "format": "resource-postgresql",
      "description": "Database connection"
    }
  }
}
適合するリソースタイプがない場合

接続情報は、個別の文字列入力(URL やトークン)やステップ内で読み取る変数ではなく、1 つのリソース入力として渡します。入力の型を resource-c_<name> とし、サービスの接続フィールドを保持するカスタムリソースタイプを作成して、リソースが参照する変数にシークレットを保存します。カスタムタイプの c_ プレフィックスを付けることで、後から同じ名前で同期される Hub のタイプと区別できます。

  • インスタンスで Windmill Hub のリソースタイプが同期されていないと報告された場合は、スーパーユーザーが同期できることに触れてください。Hub には、ほとんどのサービス向けのタイプがあります。
  • それ以外の場合、またはユーザーが同期よりもこちらを希望する場合は、リソースタイプを提案し、作成する前に確認してください。
  • ユーザーが希望する場合は、通常の変数を使用してもかまいません。
ステップ入力として使用する場合(静的参照)

特定のリソースを参照するには、$res: プレフィックスを使用します。

{
  "database": {
    "type": "static",
    "value": "$res:f/folder/my_database"
  }
}

OpenFlow スキーマ

{"OpenFlow":{"type":"object","description":"メタデータ、設定、フロー構造を含むトップレベルのフロー定義","properties":{"summary":{"type":"string","description":"このフローの動作を簡潔に説明します"},"description":{"type":"string","description":"このフローの詳細なドキュメントです"},"value":{"$ref":"#/components/schemas/FlowValue"},"schema":{"type":"object","description":"フロー入力のJSON Schemaです。入力パラメーター、その型、デフォルト値、検証ルールを定義するために使用します。リソース入力では、typeを'object'に設定し、formatを'resource-'(例:'resource-stripe')に設定します"},"on_behalf_of_email":{"type":"string","description":"フローが代理で実行されるアカウントのアドレスです。読み取り時はon_behalf_ofから導出されます。書き込み時にも指定でき、そのアドレスが示すアカウントに解決されます。"},"on_behalf_of":{"type":"string","description":"このフローは、次のいずれかのIDの権限で実行されます:u/{username}、g/{group}、またはユーザー名自体がメールアドレス形式の場合はメールアドレスのみ。このIDのうち保存されるのはこの値だけで、on_behalf_of_emailはこの値から導出されます。書き込み時に省略した場合は、代わりにそのアドレスから解決されます。"}},"required":["summary","value"]},"FlowValue":{"type":"object","description":"モジュールと、任意のプリプロセッサー/失敗ハンドラーを含むフロー構造","properties":{"modules":{"type":"array","description":"順番に実行されるステップの配列です。各ステップはスクリプト、サブフロー、ループ、または分岐です","items":{"$ref":"#/components/schemas/FlowModule"}},"failure_module":{"description":"フローが失敗したときに実行される特別なモジュールです。message、name、stack、step_idを含むエラーオブジェクトを受け取ります。idは'failure'である必要があります。script/rawscript型のみをサポートします","$ref":"#/components/schemas/FlowModule"},"preprocessor_module":{"description":"外部トリガーで最初のステップの前に実行される特別なモジュールです。idは'preprocessor'である必要があります。script/rawscript型のみをサポートします。他のステップの結果は参照できません","$ref":"#/components/schemas/FlowModule"},"same_worker":{"type":"boolean","description":"trueの場合、パフォーマンス向上のため、すべてのステップを同じワーカーで実行します"},"preserve_step_tags":{"type":"boolean","description":"フローがカスタムワーカータグで実行され、かつtrueの場合、独自の空でないタグを指定しているステップは、フロータグを継承せず、そのタグで実行されます。独自のタグを持たないステップは、引き続きフロータグを継承します。"},"concurrent_limit":{"type":"number","description":"このフローの同時実行数の最大値です"},"concurrency_key":{"type":"string","description":"同時実行をグループ化する式です(例:ユーザーIDによるグループ化)"},"concurrency_time_window_s":{"type":"number","description":"concurrent_limitの時間枠(秒)です"},"debounce_delay_s":{"type":"integer","description":"フロー実行をデバウンスする遅延時間(秒)です"},"debounce_key":{"type":"string","description":"デバウンスされた実行をグループ化する式です"},"debounce_args_to_accumulate":{"type":"array","description":"デバウンスされた実行間で蓄積する引数です","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"ジョブをデバウンスできる合計時間の最大値(秒)です"},"max_total_debounces_amount":{"type":"integer","description":"ジョブをデバウンスできる回数の最大値です"},"skip_expr":{"type":"string","description":"フロー全体を条件付きでスキップするJavaScript式です"},"cache_ttl":{"type":"number","description":"フロー結果のキャッシュ期間(秒)です"},"cache_ignore_s3_path":{"type":"boolean"},"delete_after_secs":{"type":"integer","description":"設定すると、ジョブ完了後、この秒数が経過した時点でフロージョブの引数、結果、ログを削除します"},"flow_env":{"type":"object","description":"すべてのステップで利用できる環境変数です。値には文字列、JSON値、または特別な参照('$var:path'(ワークスペース変数)または'$res:path'(リソース))を指定できます。","additionalProperties":{}},"priority":{"type":"number","description":"実行優先度です(数値が大きいほど先に実行されます)"},"early_return":{"type":"string","description":"同期Webhookが、指定したステップの完了時にその結果を返し、残りのフローは実行を継続するステップのIDです。そのステップが実行されない場合、またはフローにfailure_moduleがある状態で失敗した場合は、代わりにフローの最終結果が返されます。"},"chat_input_enabled":{"type":"boolean","description":"このフローがチャット形式の入力を受け付けるかどうかです"},"notes":{"type":"array","description":"フローに付属する付箋です","items":{"$ref":"#/components/schemas/FlowNote"}},"groups":{"type":"array","description":"整理のためのモジュールの意味的なグループです","items":{"$ref":"#/components/schemas/FlowGroup"}}},"required":["modules"]},"Retry":{"type":"object","description":"モジュール実行が失敗した場合の再試行設定","properties":{"constant":{"type":"object","description":"試行間の遅延を一定にして再試行します","properties":{"attempts":{"type":"integer","description":"再試行回数"},"seconds":{"type":"integer","description":"再試行間の待機秒数"}}},"exponential":{"type":"object","description":"指数バックオフで再試行します:n回目の再試行ではmultiplier × seconds^nだけ待機します","properties":{"attempts":{"type":"integer","description":"再試行回数"},"multiplier":{"type":"integer","description":"指数バックオフの乗数"},"seconds":{"type":"integer","minimum":1,"description":"指数の底(秒)です。n回目の再試行ではmultiplier × seconds^nだけ待機します。nには一定間隔での再試行も含みます"},"random_factor":{"type":"integer","minimum":0,"maximum":100,"description":"同時アクセス集中を避けるためのランダムなジッター率(0~100%)です"}}},"retry_if":{"$ref":"#/components/schemas/RetryIf"}}},"FlowNote":{"type":"object","description":"ドキュメントや注釈のためにフローに付属する付箋","properties":{"id":{"type":"string","description":"付箋の一意の識別子です"},"text":{"type":"string","description":"付箋の内容です"},"position":{"type":"object","description":"フローエディター内での付箋の位置です","properties":{"x":{"type":"number","description":"X座標"},"y":{"type":"number","description":"Y座標"}},"required":["x","y"]},"size":{"type":"object","description":"フローエディター内での付箋のサイズです","properties":{"width":{"type":"number","description":"幅(ピクセル)"},"height":{"type":"number","description":"高さ(ピクセル)"}},"required":["width","height"]},"color":{"type":"string","description":"付箋の色です。yellow、blue、green、purple、pink、orange、red、cyan、lime、grayのいずれかです。それ以外の値ではスタイルが適用されません。"},"type":{"type":"string","enum":["free","group"],"description":"付箋の種類です。'free'は単独の付箋です。'group'の付箋は非推奨です。代わりにFlowValue.groupsでフローを区分してください。"},"locked":{"type":"boolean","default":false,"description":"付箋がロックされ、編集や移動ができないかどうかです"},"contained_node_ids":{"type":"array","items":{"type":"string"},"description":"グループ付箋の場合、このグループに含まれるノードのIDです"}},"required":["id","text","color","type"]},"FlowGroup":{"type":"object","description":"整理のためのフローモジュールの意味的なグループです。実行には影響しません。モジュールはフロー内の元の位置に残ります。グループを使うと、エディターで名前を付けたり折りたたんだりできます。メンバーはstart_idとend_idの間のパス上にあるすべてのノードから動的に算出されます。","properties":{"summary":{"type":"string","description":"このグループの表示名です"},"note":{"type":"string","description":"グループヘッダーの下に表示されるMarkdown形式の注記です"},"autocollapse":{"type":"boolean","default":false,"description":"trueの場合、フローエディターでこのグループはデフォルトで折りたたまれます。UI上のヒントにすぎません。"},"start_id":{"type":"string","description":"このグループ内で最初のフローモジュールのID(トポロジカルな入口)です"},"end_id":{"type":"string","description":"このグループ内で最後のフローモジュールのID(トポロジカルな出口)です"},"color":{"type":"string","description":"フローエディターでのグループの色です。yellow、blue、green、purple、pink、orange、red、cyan、lime、grayのいずれかです。省略すると、エディターが色を選びます。"}},"required":["start_id","end_id"]},"RetryIf":{"type":"object","description":"エラーまたは結果に基づく条件付き再試行","properties":{"expr":{"type":"string","description":"'result'および'error'変数を使用でき、再試行する場合にtrueを返すJavaScript式です"}},"required":["expr"]},"StopAfterIf":{"type":"object","description":"モジュールの早期終了条件","properties":{"skip_if_stopped":{"type":"boolean","description":"trueの場合、この条件が成立すると後続のステップをスキップします"},"expr":{"type":"string","description":"モジュール実行後に評価されるJavaScript式です。'result'(ステップの結果)または'flow_input'を使用できます。停止する場合はtrueを返します"},"error_message":{"type":"string","nullable":true,"description":"エラーで停止する場合のカスタムエラーメッセージです。skip_if_stoppedとは同時に指定できません。空でない文字列を設定すると、このエラーでフローが停止します。空文字列の場合はデフォルトのエラーメッセージが使用されます。nullまたは省略した場合、エラーは発生しません。"},"error_include_result":{"type":"boolean","description":"エラーで停止する場合(error_messageを設定)、停止したステップ自身の結果を破棄せず、発生したエラーオブジェクト内に(error.resultとして)含めます。トップレベルの結果は{ error }のままです。デフォルトはfalseです。"}},"required":["expr"]},"FlowModule":{"type":"object","description":"フロー内の単一のステップです。スクリプト、サブフロー、ループ、または分岐を指定できます","properties":{"id":{"type":"string","description":"このステップの一意の識別子です。'results.step_id'で結果を参照するために使用します。有効な識別子(英数字、アンダースコア、ハイフン)である必要があります"},"value":{"$ref":"#/components/schemas/FlowModuleValue"},"stop_after_if":{"description":"このステップの完了後に評価される早期終了条件です","$ref":"#/components/schemas/StopAfterIf"},"stop_after_all_iters_if":{"description":"ループ専用です。すべての反復の完了後に評価される早期終了条件です","$ref":"#/components/schemas/StopAfterIf"},"skip_if":{"type":"object","description":"前の結果またはフロー入力に基づいて、このステップを条件付きでスキップします","properties":{"expr":{"type":"string","description":"スキップする場合にtrueを返すJavaScript式です。'flow_input'または'results.<step_id>'を使用できます"}},"required":["expr"]},"sleep":{"description":"このステップの実行前の遅延(秒、または式で指定)です","$ref":"#/components/schemas/InputTransform"},"cache_ttl":{"type":"number","description":"このステップの結果のキャッシュ期間(秒)です"},"cache_ignore_s3_path":{"type":"boolean"},"timeout":{"description":"最大実行時間(秒、固定値または式で指定)です","$ref":"#/components/schemas/InputTransform"},"delete_after_secs":{"type":"integer","description":"設定すると、ジョブ完了後、この秒数が経過した時点でステップの引数、結果、ログを削除します"},"summary":{"type":"string","description":"このステップの動作を簡潔に説明します"},"mock":{"type":"object","description":"実際のステップを実行せずにテストするためのモック設定です","properties":{"enabled":{"type":"boolean","description":"trueの場合、実行する代わりにモック値を返します"},"return_value":{"description":"モック時に返す値です"}}},"suspend":{"type":"object","description":"ユーザー入力を待つ承認/再開ステップの設定です","properties":{"required_events":{"type":"integer","description":"続行に必要な承認数です"},"timeout":{"type":"integer","description":"自動続行またはキャンセルまでのタイムアウト(秒)です"},"resume_form":{"type":"object","description":"再開時に入力を収集するフォームスキーマです","properties":{"schema":{"type":"object","description":"再開フォームのJSON Schemaです"}}},"user_auth_required":{"type":"boolean","description":"trueの場合、認証済みユーザーのみが承認できます"},"user_groups_required":{"description":"承認可能なグループの式またはリストです","$ref":"#/components/schemas/InputTransform"},"self_approval_disabled":{"type":"boolean","description":"trueの場合、フローを開始したユーザーは承認できません"},"hide_cancel":{"type":"boolean","description":"trueの場合、承認フォームのキャンセルボタンを非表示にします"},"continue_on_disapprove_timeout":{"type":"boolean","description":"trueの場合、タイムアウト時にキャンセルせずフローを続行します"},"skin":{"type":"string","enum":["detailed","minimal"],"description":"承認ページおよびSlack/Teamsの承認メッセージでの承認リクエストの表示方法です。'detailed'(未設定時に使用)はフローの詳細(引数、グラフ、承認者)を表示し、'minimal'はリクエスト(ステップの説明、フォーム、承認/却下の操作)のみを表示します"}}},"priority":{"type":"number","description":"このステップの実行優先度です(数値が大きいほど先に実行されます)"},"continue_on_error":{"type":"boolean","description":"trueの場合、このステップが失敗してもフローを続行します"},"job_token_scopes":{"type":"array","nullable":true,"items":{"type":"string"},"description":"このステップのジョブのトークンに許可するスコープ(domain:action[:resource]、例:oidc:write)です。フロー自体の制限に加えて指定します。ステップではスコープを狭めることのみ可能です。ループや分岐の本体、AIエージェントのツールを含め、このステップで実行するすべてに適用されます。"},"retry":{"description":"このステップが失敗した場合の再試行設定です","$ref":"#/components/schemas/Retry"},"debouncing":{"description":"このステップのデバウンス設定(EEのみ)です","type":"object","properties":{"debounce_delay_s":{"type":"integer","description":"フロー実行間でこのステップの実行をデバウンスする遅延時間(秒)です"},"debounce_key":{"type":"string","description":"デバウンスされた実行をグループ化する式です。$workspaceおよび$args[name]をサポートします。デフォルト:$workspace/flow/<flow_path>-<step_id>"},"debounce_args_to_accumulate":{"type":"array","description":"デバウンスされた実行間で蓄積する配列型の引数です","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"強制実行までの合計時間の最大値(秒)です"},"max_total_debounces_amount":{"type":"integer","description":"強制実行までにデバウンスできる回数の最大値です"}}}},"required":["value","id"]},"InputTransform":{"description":"ステップの入力パラメーターをマッピングします。静的な値、または以前の結果やフロー入力を参照するJavaScript式を指定できます","oneOf":[{"$ref":"#/components/schemas/StaticTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"StaticTransform":{"type":"object","description":"ステップに直接渡す静的な値です。ハードコードされた値や'$res:path/to/resource'のようなリソース参照に使用します","properties":{"value":{"description":"静的な値です。リソースには'$res:path/to/resource'形式を使用します"},"type":{"type":"string","enum":["static"]}},"required":["type"]},"JavascriptTransform":{"type":"object","description":"実行時に評価されるJavaScript式です。'results.step_id'で以前のステップの結果を参照したり、'flow_input.property'でフロー入力を参照したりできます。forループ内では、現在の反復値に'flow_input.iter.value'を使用します(whileループでは'flow_input.iter.index'と同じ値です)","properties":{"expr":{"type":"string","description":"値を返すJavaScript式です。利用できる変数:results(以前のすべてのステップの結果を含むオブジェクト)、flow_input(フロー入力)、flow_input.iter(ループ内)"},"type":{"type":"string","enum":["javascript"]}},"required":["expr","type"]},"AiTransform":{"type":"object","description":"この入力の値はAIランタイムによって解決されます。AIエンジンがパラメーターを満たす方法を決定します。","properties":{"type":{"type":"string","enum":["ai"]}},"required":["type"]},"AIProviderKind":{"type":"string","description":"サポートされているAIプロバイダーの種類","enum":["openai","azure_openai","azure_foundry","anthropic","mistral","deepseek","googleai","groq","openrouter","togetherai","customai","aws_bedrock","typesafe","cloudflare"]},"ProviderConfig":{"type":"object","description":"リソース参照とモデル選択を含む、完全なAIプロバイダー設定です","properties":{"kind":{"$ref":"#/components/schemas/AIProviderKind"},"resource":{"type":"string","description":"プロバイダーの認証情報を示す'$res:{resource_path}'形式のリソース参照です"},"model":{"type":"string","description":"モデル識別子です(例:'gpt-4'、'claude-3-opus-20240229'、'gemini-pro')"},"reasoning_effort":{"type":"string","description":"拡張思考をサポートするモデル向けの、プロバイダー固有の推論強度トークン(例:'low'、'high'、'none')です。省略可能です。未設定の場合、プロバイダーのデフォルトが使用されます。"}},"required":["kind","resource","model"]},"StaticProviderTransform":{"type":"object","description":"AIエージェントに直接渡す静的なプロバイダー設定です","properties":{"value":{"$ref":"#/components/schemas/ProviderConfig"},"type":{"type":"string","enum":["static"]}},"required":["type","value"]},"ProviderTransform":{"description":"プロバイダー設定です。静的な設定(ProviderConfig)、JavaScript式、またはAIによる決定を指定できます","oneOf":[{"$ref":"#/components/schemas/StaticProviderTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticProviderTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"MemoryOff":{"type":"object","description":"会話メモリ/コンテキストを使用しません","properties":{"kind":{"type":"string","enum":["off"]}},"required":["kind"]},"MemoryWindow":{"type":"object","description":"実行のmemory id(またはステップのmemory_id)で指定されたメモリの最新メッセージを保持します。メモリIDがない場合、エージェントはメモリなしで実行されます。\n","properties":{"kind":{"type":"string","enum":["window"]},"context_length":{"type":"integer","description":"読み込み、保存する最新メッセージの数です。0にするとメモリを無効にします。"}},"required":["kind","context_length"]},"MemoryAuto":{"type":"object","deprecated":true,"description":"非推奨ですが、書き込まれたとおりに引き続き読み取られます。実行のmemory idがあればそれを使用し、なければここで指定されたmemory_idを使用します。\nこの種類が設定されている間、ステップ独自のmemory_idは読み取られません。使用するには種類をwindowに切り替えてください。\ncontext_lengthがない場合、または0の場合はoffとなり、previous_messagesを読み取ります。\n","properties":{"kind":{"type":"string","enum":["auto"]},"context_length":{"type":"integer","description":"コンテキストに保持するメッセージ数の最大値です"},"memory_id":{"type":"string","description":"エージェントの呼び出し間で永続的に保持するメモリの識別子です"}},"required":["kind"]},"MemoryCompaction":{"type":"object","description":"実行のmemory id(またはステップのmemory_id)で指定されたメモリ全体を保持し、会話がモデルのコンテキストウィンドウに近づくと古い部分を要約に置き換えます。\nメモリIDがない場合、エージェントはメモリなしで実行され、圧縮によって実行自体のループが制限されます。\n","properties":{"kind":{"type":"string","enum":["compaction"]},"context_window":{"type":"integer","description":"モデルから取得するコンテキストウィンドウをトークン数で上書きします。Windmillが認識していないモデルにのみ必要です。その場合、デフォルトで128000が使用されます。\n"}},"required":["kind"]},"MemoryMessage":{"type":"object","description":"会話履歴内の単一メッセージです","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"MemoryManual":{"type":"object","deprecated":true,"description":"非推奨ですが、書き込まれたとおりに引き続き読み取られます。ステップをoffにし、代わりにprevious_messagesを使用してください。","properties":{"kind":{"type":"string","enum":["manual"]},"messages":{"type":"array","items":{"$ref":"#/components/schemas/MemoryMessage"}}},"required":["kind","messages"]},"MemoryConfig":{"description":"Windmillに保存され、各リクエストで再生される管理対象メモリです。メモリはmemory idで指定します。memory_idを参照してください。メモリが無効の場合、ステップはprevious_messagesで履歴を指定できます。","oneOf":[{"$ref":"#/components/schemas/MemoryOff"},{"$ref":"#/components/schemas/MemoryWindow"},{"$ref":"#/components/schemas/MemoryCompaction"},{"$ref":"#/components/schemas/MemoryAuto"},{"$ref":"#/components/schemas/MemoryManual"}],"discriminator":{"propertyName":"kind","mapping":{"off":"#/components/schemas/MemoryOff","window":"#/components/schemas/MemoryWindow","compaction":"#/components/schemas/MemoryCompaction","auto":"#/components/schemas/MemoryAuto","manual":"#/components/schemas/MemoryManual"}}},"StaticMemoryTransform":{"type":"object","description":"AIエージェントに直接渡す静的なメモリ設定です","properties":{"value":{"$ref":"#/components/schemas/MemoryConfig"},"type":{"type":"string","enum":["static"]}},"required":["type","value"]},"MemoryTransform":{"description":"メモリ設定です。静的な設定(MemoryConfig)、JavaScript式、またはAIによる決定を指定できます","oneOf":[{"$ref":"#/components/schemas/StaticMemoryTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticMemoryTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"FlowModuleValue":{"description":"フローステップの実際の実装です。スクリプト(インラインまたは参照)、サブフロー、ループ、分岐、または特別なモジュール型を指定できます","oneOf":[{"$ref":"#/components/schemas/RawScript"},{"$ref":"#/components/schemas/PathScript"},{"$ref":"#/components/schemas/PathFlow"},{"$ref":"#/components/schemas/ForloopFlow"},{"$ref":"#/components/schemas/WhileloopFlow"},{"$ref":"#/components/schemas/BranchOne"},{"$ref":"#/components/schemas/BranchAll"},{"$ref":"#/components/schemas/Identity"},{"$ref":"#/components/schemas/AiAgent"},{"$ref":"#/components/schemas/AiDecision"}],"discriminator":{"propertyName":"type","mapping":{"rawscript":"#/components/schemas/RawScript","script":"#/components/schemas/PathScript","flow":"#/components/schemas/PathFlow","forloopflow":"#/components/schemas/ForloopFlow","whileloopflow":"#/components/schemas/WhileloopFlow","branchone":"#/components/schemas/BranchOne","branchall":"#/components/schemas/BranchAll","identity":"#/components/schemas/Identity","aiagent":"#/components/schemas/AiAgent","aidecision":"#/components/schemas/AiDecision"}}},"RawScript":{"type":"object","description":"コードをフロー内に直接定義するインラインスクリプトです。言語が指定されていない場合、デフォルトとして'bun'を使用します。スクリプトはinput_transformsから引数を受け取ります","properties":{"input_transforms":{"type":"object","description":"パラメーター名とその値(静的値またはJavaScript式)のマップです。これらはスクリプトの入力引数になります","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"content":{"type":"string","description":"スクリプトのソースコードです。'main'関数をエクスポートする必要があります"},"language":{"type":"string","description":"このスクリプトのプログラミング言語です","enum":["deno","bun","bunnative","python3","go","bash","powershell","postgresql","mysql","bigquery","snowflake","mssql","oracledb","graphql","nativets","php","rust","ansible","csharp","nu","java","ruby","rlang","duckdb"]},"path":{"type":"string","description":"このスクリプトを保存するための任意のパスです"},"lock":{"type":"string","description":"依存関係のロックファイルの内容です"},"type":{"type":"string","enum":["rawscript"]},"tag":{"type":"string","description":"実行先を振り分けるワーカーグループタグです"},"concurrent_limit":{"type":"number","description":"このスクリプトの同時実行数の最大値です"},"concurrency_time_window_s":{"type":"number","description":"concurrent_limitの時間枠です"},"custom_concurrency_key":{"type":"string","description":"同時実行をグループ化するカスタムキーです"},"is_trigger":{"type":"boolean","description":"trueの場合、このスクリプトはフローを開始できるトリガーです"},"assets":{"type":"array","description":"このスクリプトがアクセスする外部リソース(S3オブジェクト、リソースなど)です","items":{"type":"object","required":["path","kind"],"properties":{"path":{"type":"string","description":"アセットへのパスです"},"kind":{"type":"string","description":"アセットの種類です","enum":["s3object","resource","ducklake","datatable","volume","dbt"]},"access_type":{"type":"string","nullable":true,"description":"このアセットのアクセスレベルです","enum":["r","w","rw"]},"alt_access_type":{"type":"string","nullable":true,"description":"代替のアクセスレベルです","enum":["r","w","rw"]}}}}},"required":["type","content","language","input_transforms"]},"PathScript":{"type":"object","description":"パスで既存のスクリプトを参照します。インラインコードを書く代わりに、保存済みのスクリプトを呼び出す場合に使用します","properties":{"input_transforms":{"type":"object","description":"パラメーター名とその値(静的値またはJavaScript式)のマップです。これらはスクリプトの入力引数になります","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"path":{"type":"string","description":"ワークスペース内のスクリプトへのパスです(例:'f/scripts/send_email')"},"hash":{"type":"string","description":"使用するスクリプトの特定バージョンのハッシュです(任意)"},"type":{"type":"string","enum":["script"]},"tag_override":{"type":"string","description":"スクリプトのデフォルトのワーカーグループタグを上書きします"},"is_trigger":{"type":"boolean","description":"trueの場合、このスクリプトはフローを開始できるトリガーです"}},"required":["type","path","input_transforms"]},"PathFlow":{"type":"object","description":"パスで既存のフローを参照します。別のフローをサブフローとして呼び出す場合に使用します","properties":{"input_transforms":{"type":"object","description":"パラメーター名とその値(静的値またはJavaScript式)のマップです。これらはサブフローの入力引数になります","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"path":{"type":"string","description":"ワークスペース内のフローへのパスです(例:'f/flows/process_user')"},"type":{"type":"string","enum":["flow"]}},"required":["type","path","input_transforms"]},"ForloopFlow":{"type":"object","description":"イテレーターを使用して、入れ子のモジュールをループ実行します。ループ内では、現在の反復値に'flow_input.iter.value'を、インデックスに'flow_input.iter.index'を使用します。I/Oバウンド処理のパフォーマンスを向上させるため、並列実行をサポートします","properties":{"modules":{"type":"array","description":"各反復で実行するステップです。'flow_input.iter.value'を使って反復値を参照できます","items":{"$ref":"#/components/schemas/FlowModule"}},"iterator":{"description":"反復処理する配列を返すJavaScript式です。'results.step_id'または'flow_input'を参照できます","$ref":"#/components/schemas/InputTransform"},"skip_failures":{"type":"boolean","description":"trueの場合、反復の失敗でループは停止しません。失敗した反復はnullを返します"},"type":{"type":"string","enum":["forloopflow"]},"parallel":{"type":"boolean","description":"trueの場合、反復を並行して実行します(I/Oバウンド処理で高速化できます)。parallelismと併用して並行数を制御します"},"parallelism":{"description":"parallel=trueの場合の同時実行反復数の最大値です。リソース使用量を制限します。固定値または式を指定できます","$ref":"#/components/schemas/InputTransform"},"squash":{"type":"boolean"}},"required":["modules","iterator","skip_failures","type"]},"WhileloopFlow":{"type":"object","description":"停止するまで入れ子のモジュールを繰り返し実行します。暗黙のイテレーターは反復カウンターです。そのため'flow_input.iter.value'は'flow_input.iter.index'と同じ値(0、1、2、...)であり、状態は保持されません。反復間で状態を保持するには、ステップ自身の前回の反復結果を、最初の反復用のフォールバックとともに'results.<its_own_id>'で読み取ります。その場合、ループのstop_after_ifはその内部ステップに設定する必要があります(stop_after_ifをループモジュールに設定した単一ステップの本体では、反復間で'results'を解決できないため、終了しません)。単純なカウンターは'flow_input.iter.index'から導出することもでき、これはどの設定でも機能します。stop_after_ifは各反復の後に評価されます。ループモジュールでは、'result'は最後の反復の結果です","properties":{"modules":{"type":"array","description":"各反復で実行するステップです","items":{"$ref":"#/components/schemas/FlowModule"}},"skip_failures":{"type":"boolean","description":"trueの場合、反復の失敗でループは停止しません。失敗した反復はnullを返します"},"type":{"type":"string","enum":["whileloopflow"]},"parallel":{"type":"boolean","description":"trueの場合、反復を並行して実行します(whileループでは注意して使用してください)"},"parallelism":{"description":"parallel=trueの場合の同時実行反復数の最大値です","$ref":"#/components/schemas/InputTransform"},"squash":{"type":"boolean"}},"required":["modules","skip_failures","type"]},"BranchOne":{"type":"object","description":"最初に一致した分岐のみが実行される条件分岐です。分岐は順番に評価され、式がtrueとなった最初の分岐が実行されます。どの分岐にも一致しない場合は、デフォルトの分岐が実行されます","properties":{"branches":{"type":"array","description":"順番に評価する分岐の配列です。exprがtrueと評価された最初の分岐が実行されます","items":{"type":"object","properties":{"summary":{"type":"string","description":"この分岐条件の簡潔な説明です"},"expr":{"type":"string","description":"ブール値を返すJavaScript式です。'results.step_id'または'flow_input'を使用できます。最初にtrueとなったexprが優先されます"},"modules":{"type":"array","description":"この分岐のexprがtrueの場合に実行するステップです","items":{"$ref":"#/components/schemas/FlowModule"}}},"required":["modules","expr"]}},"default":{"type":"array","description":"どの分岐式にも一致しない場合に実行するステップです","items":{"$ref":"#/components/schemas/FlowModule"}},"type":{"type":"string","enum":["branchone"]}},"required":["branches","default","type"]},"BranchAll":{"type":"object","description":"すべての分岐を同時に実行する並列分岐です。BranchOneとは異なり、条件に関係なくすべての分岐が実行されます。独立したタスクを並行して実行する場合に便利です","properties":{"branches":{"type":"array","description":"すべて実行される分岐(並列または順次実行)の配列です","items":{"type":"object","properties":{"summary":{"type":"string","description":"この分岐の目的の簡潔な説明です"},"skip_failure":{"type":"boolean","description":"trueの場合、この分岐で失敗してもフロー全体は失敗しません"},"modules":{"type":"array","description":"この分岐で実行するステップです","items":{"$ref":"#/components/schemas/FlowModule"}}},"required":["modules"]}},"type":{"type":"string","enum":["branchall"]},"parallel":{"type":"boolean","description":"trueの場合、すべての分岐を同時に実行します。falseの場合、順番に実行します"}},"required":["branches","type"]},"AgentTool":{"type":"object","description":"AIエージェントが利用できるツールです。フローモジュールまたは外部MCP(Model Context Protocol)ツールを指定できます","properties":{"id":{"type":"string","description":"このツールの一意の識別子です。空白は使用できません。代わりにアンダースコアを使用してください(例:'get user data'ではなく'get_user_data')"},"summary":{"type":"string","description":"AIエージェントがこのツールを呼び出す際に使用する名前であり、人間向けのラベルではありません。flowmoduleツールでは^[a-zA-Z0-9_]+$に一致する必要があり、必ず設定します(例:'Search documentation'ではなく'search_documentation')。mcp、websearch、questionツールでは通常のラベルです。人間向けの説明は'description'に記載してください。"},"description":{"type":"string","description":"いつ、どのように呼び出すかをAIが判断するために渡される、ツールの自由形式の説明です。基盤となるスクリプトから自動生成される説明を上書きします。"},"job_token_scopes":{"type":"array","nullable":true,"items":{"type":"string"},"description":"エージェントステップ自体の制限に加えて、このツールのジョブのトークンに許可するスコープです。ツールで可能なのはスコープを狭めることのみです。"},"requires_approval":{"type":"boolean","description":"flowmoduleおよびmcpツールのみ。呼び出しごとに、人がフローの実行ページまたはチャットから承認または却下するまで待機します。その間、エージェントはワーカーを保持しません。同じターン内で承認を必要としない呼び出しはすぐに実行されます。却下された呼び出し、または30分以内に応答がない呼び出しは、実行されなかったことがAIに報告されます。"},"value":{"$ref":"#/components/schemas/ToolValue"}},"required":["id","value"]},"ToolValue":{"description":"ツールの実装です。フローモジュール(スクリプト/フロー)またはMCPツール参照を指定できます","oneOf":[{"$ref":"#/components/schemas/FlowModuleTool"},{"$ref":"#/components/schemas/McpToolValue"},{"$ref":"#/components/schemas/WebsearchToolValue"},{"$ref":"#/components/schemas/QuestionToolValue"}],"discriminator":{"propertyName":"tool_type","mapping":{"flowmodule":"#/components/schemas/FlowModuleTool","mcp":"#/components/schemas/McpToolValue","websearch":"#/components/schemas/WebsearchToolValue","question":"#/components/schemas/QuestionToolValue"}}},"FlowModuleTool":{"description":"フローモジュール(スクリプト、フローなど)として実装されたツールです。AIは他のフローモジュールと同様にこのツールを呼び出せます","allOf":[{"type":"object","properties":{"tool_type":{"type":"string","enum":["flowmodule"]}},"required":["tool_type"]},{"$ref":"#/components/schemas/FlowModuleValue"}]},"WebsearchToolValue":{"type":"object","description":"ウェブ検索ツールとして実装されたツールです。AIは他のウェブ検索ツールと同様にこのツールを呼び出せます","properties":{"tool_type":{"type":"string","enum":["websearch"]}},"required":["tool_type"]},"QuestionToolValue":{"type":"object","description":"組み込みツールです。AIがask_questionとして呼び出すと、エージェントはワーカーを解放して停止します。フローの実行ページまたはチャットから誰かが回答するか、質問がタイムアウトすると、回答をツールの結果として受け取って再開します。","properties":{"tool_type":{"type":"string","enum":["question"]},"timeout":{"type":"integer","description":"回答を待つ秒数です。タイムアウトすると、質問がタイムアウトしたことがAIに報告されます。デフォルトは1800です。"}},"required":["tool_type"]},"McpToolValue":{"type":"object","description":"外部MCP(Model Context Protocol)ツールへの参照です。AIはMCPサーバーのツールを利用できます","properties":{"tool_type":{"type":"string","enum":["mcp"]},"resource_path":{"type":"string","description":"MCPリソース/サーバー設定へのパスです"},"include_tools":{"type":"array","description":"このMCPサーバーから含める特定のツールの許可リストです","items":{"type":"string"}},"exclude_tools":{"type":"array","description":"このMCPサーバーから除外するツールの拒否リストです","items":{"type":"string"}}},"required":["tool_type","resource_path"]},"AiAgent":{"type":"object","description":"タスクを遂行するためにツールを利用できるAIエージェントのステップです。エージェントは入力を受け取り、設定済みの任意のツールを呼び出してタスクを完了できます","properties":{"input_transforms":{"type":"object","description":"AIエージェントの入力パラメーターと値のマッピングです","properties":{"provider":{"$ref":"#/components/schemas/ProviderTransform"},"output_type":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"出力形式の種類です。\n有効な値:'text'(デフォルト)- プレーンテキストの応答、'image' - 画像生成\n"},"user_message":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"AIエージェントに渡すユーザーのプロンプト/メッセージです。\nflow.input構文による変数の補間をサポートします。メモリが無効でprevious_messagesにプロンプトが指定されている場合を除き、必須です。画像出力では常に必要です。\n"},"system_prompt":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"AIの動作、ペルソナ、応答スタイルを導くシステム指示です。省略可能です。"},"streaming":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"ブール値です。trueの場合、AIの応答を段階的にストリーミングします。\nストリーミングイベントには、token_delta、reasoning_token_delta、tool_call、tool_call_arguments、tool_execution、tool_resultがあります。\n"},"memory":{"$ref":"#/components/schemas/MemoryTransform"},"memory_id":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"文字列です。このステップが読み書きするメモリを指定し、実行開始時に指定されたmemory id\n(チャットの会話、アプリのチャットセッション、またはmemory_id実行パラメーター)を上書きします。未設定の場合は実行のmemory idを使用します。固定値を指定するとすべての実行で1つのメモリを共有し、\nflow_input.customer_idのような式を指定するとキーごとにメモリを保持します。空の値に評価された場合、エージェントはメモリなしで実行されます。読み取りはmemoryがwindowまたはcompactionの場合のみです。メモリが無効な場合は無視され、旧式のautoまたはmanualのメモリではどちらの履歴入力も読み取られません。\n"},"previous_messages":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"MemoryMessageの配列です。フローで指定する履歴で、システムプロンプトとユーザーメッセージの間に送信されます。読み取りはmemoryがoffまたは未指定の場合のみです。管理対象メモリでは無視され、旧式のautoまたはmanualのメモリではどちらの履歴入力も読み取られません。\n"},"output_schema":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"構造化出力形式を定義するJSON Schemaオブジェクトです。AIに特定の形でデータを返させる場合に使用します。\n標準的なJSON Schemaプロパティ(type、properties、required、items、enum、pattern、minLength、maxLength、minimum、maximumなど)をサポートします。\n例:{ type: 'object', properties: { name: { type: 'string' }, age: { type: 'integer' } }, required: ['name'] }\n"},"user_attachments":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"AIエージェント向けのファイル参照(画像またはPDF)の配列です。\n形式:Array<{ bucket: string, key: string }> - S3オブジェクト参照\n例:[{ bucket: 'my-bucket', key: 'documents/report.pdf' }]\n"},"enabled_tools":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"この実行でエージェントが呼び出せる、toolsに設定されたツール名の配列です。\n未設定の場合はすべてのツールが引き継がれ、空の配列の場合はどのツールも引き継がれません。\nツール名にはモデルに表示される名前を使用します。モデルに表示される情報がないツールは、代わりに識別子で名前を付けます。MCPサーバーはリソースパスで指定し、そのサーバーが公開するすべてのツールを引き継ぎます(実際に引き継がれるツールは、そのエントリーのinclude_tools/exclude_toolsに従います)。websearchエントリーは、summaryにかかわらず予約名'__wm_web_search'で指定します(この名前を他のツールに付けることはできません)。\n例:['get_user', 'u/admin/github_mcp', '__wm_web_search']\n"},"max_completion_tokens":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"整数です。AIが応答で生成するトークン数の最大値です。\n範囲:1~4,294,967,295。一般的な用途での目安:256~4096。\n"},"temperature":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"浮動小数点数です。応答のランダム性/創造性を制御します。\n範囲:0.0~2.0(プロバイダーによって異なります)\n- 0.0 = 決定論的で焦点の定まった応答\n- 0.7 = バランスの取れた応答(一般的なデフォルト)\n- 1.0以上 = より創造的/ランダム\n"},"max_iterations":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"数値です。エージェントが推論とツール使用を繰り返す回数を制限します。\n範囲:1~1000。\n"},"model":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"文字列です。保存済みエージェントにリンクされたステップ(agentを参照)でのみ使用できます。このステップの実行では、エージェント自身のプロバイダーリソース上に保存されたモデルを上書きします。\n空の値の場合、保存済みのモデルが使用されます。flow_input.modelのような式を設定すると、実行ごとにモデルを選択できます。\n"},"reasoning_effort":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"文字列です。保存済みエージェントにリンクされたステップ(agentを参照)でのみ使用できます。このステップの実行では、エージェントに保存された推論強度を、プロバイダー固有のトークン(例:'low'、'high'、'none')として上書きします。空の値の場合、推論強度を送信しないため、モデルのデフォルトが使用されます。入力を省略すると、ステップが保存済みモデルを実行する場合に限り、保存済みの推論強度が維持されます。保存済みエージェントにリンクされていないステップでは、両方をprovider内に設定します。\n"}}},"tools":{"type":"array","description":"エージェントが利用できるツールの配列です。エージェントはタスクに基づいて呼び出すツールを決定します","items":{"$ref":"#/components/schemas/AgentTool"}},"type":{"type":"string","enum":["aiagent"]},"tag":{"type":"string","description":"実行先を振り分けるワーカーグループタグです。未設定の場合、AIエージェントステップはフローのタグ(デフォルトflow)で実行されます"},"omit_output_from_conversation":{"type":"boolean","default":false,"description":"trueの場合、チャットモードが有効でも、このAIエージェントステップのアシスタントメッセージまたはツールメッセージはフローの会話に保存されません。"},"agent":{"type":"string","description":"再利用可能なai_agentリソースへのパス(ハイブリッドリンク)です。設定すると、エージェントの中核設定(プロバイダー/モデル/システムプロンプトなど)とツールセットは実行時にそのリソースから解決されます。モジュールのinput_transformsには、フロー固有の入力(user_message、user_attachments、enabled_tools、memory_idおよびprevious_messagesの履歴入力)のみが含まれ、必要に応じてエージェントに保存された値を上書きするmodelおよびreasoning_effortも含まれます。\n"},"tool_inputs":{"type":"object","description":"エージェントツールの入力をホスト側で接続する設定です。ツールID、次に入力キーをキーとして使用します。共有リソースを変更せず、参照先エージェントのツールをこのフローのコンテキスト(flow_input/results)にバインドします。実行時にツールのinput_transformsに重ねて適用されます。agentが未設定の場合も適用されます。編集用にフォークされたステップは、保存し直すかリンク解除するまでこれらの上書きを保持するためです。\n","additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}}},"parallel":{"type":"boolean","description":"trueの場合、エージェントは複数のツール呼び出しを並列実行できます"}},"required":["type","input_transforms"]},"AiDecision":{"type":"object","description":"AI判定ステップです。判定モデル(TypeSafeのJev、CloudflareのJev互換Clef、またはOpenAIのDecisions API)を1回呼び出し、テキストを生成する代わりに、状態に関する型付きの質問に校正済みの確率で回答します。\n分類、ルーティング、スコア付け、または確認には、AIエージェントよりもこちらを推奨します。高速かつ低コストで、回答が構造化されているためです。結果は{ output: { : answer },\nmodel, usage }となるため、後続のステップでは例えばresults..output.intent.choiceのように読み取ります。回答に基づいてルーティングするには、分岐のexprでresults..output..choiceを参照するbranchoneを後続に配置します。AIエージェントのツールとして使用することもでき、その場合、呼び出し元のエージェントが状態を渡します。\n","properties":{"input_transforms":{"type":"object","description":"判定への入力パラメーターと値のマッピングです","properties":{"provider":{"$ref":"#/components/schemas/ProviderTransform"},"state":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"質問の対象となる内容です。文字列、オブジェクト、または文字列の配列を指定します。\n質問に必要な情報のみを説明的なキーで保持するオブジェクトが最適です。\n例:{ message: flow_input.message, plan: results.a.plan }\n"},"questions":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"各質問名を{ type, instructions, criteria }に対応付けるオブジェクトです。typeは次のいずれかです。\n- 'choice':criteriaは各選択肢を説明するマップです(最大255個)。回答にはchoice、probabilities、confidenceが含まれます。\n- 'score':criteriaは2~10段階の説明の順序付き配列です。回答にはscore、legend、probabilities、confidenceが含まれます。\n- 'noul':はい/いいえです。criteriaには任意で{ true, false }の説明を指定できます。回答にはnoul(はいの確率、0~1)が含まれます。\n例:{ intent: { type: 'choice', instructions: 'What does the customer want?',\ncriteria: { refund: 'Money back', bug: 'Something is broken' } } }\n"}},"required":["provider","state","questions"]},"type":{"type":"string","enum":["aidecision"]},"tag":{"type":"string","description":"実行先を振り分けるワーカーグループタグです。未設定の場合、ステップはフローのタグ(デフォルトflow)で実行されます"}},"required":["type","input_transforms"]},"Identity":{"type":"object","description":"入力を変更せずに返すパススルーモジュールです。フロー構造やプレースホルダーとして便利です","properties":{"type":{"type":"string","enum":["identity"]},"flow":{"type":"boolean","description":"trueの場合、これをフローIDとしてマークします(特別な処理が適用されます)"}},"required":["type"]},"FlowStatus":{"type":"object","properties":{"step":{"type":"integer"},"modules":{"type":"array","items":{"$ref":"#/components/schemas/FlowStatusModule"}},"user_states":{"additionalProperties":true},"preprocessor_module":{"allOf":[{"$ref":"#/components/schemas/FlowStatusModule"}]},"failure_module":{"allOf":[{"$ref":"#/components/schemas/FlowStatusModule"},{"type":"object","properties":{"parent_module":{"type":"string"}}}]},"retry":{"type":"object","properties":{"fail_count":{"type":"integer"},"failed_jobs":{"type":"array","items":{"type":"string","format":"uuid"}}}}},"required":["step","modules","failure_module"]},"FlowStatusModule":{"type":"object","properties":{"type":{"type":"string","enum":["WaitingForPriorSteps","WaitingForEvents","WaitingForExecutor","InProgress","Success","Failure"]},"id":{"type":"string"},"job":{"type":"string","format":"uuid"},"count":{"type":"integer"},"progress":{"type":"integer"},"iterator":{"type":"object","properties":{"index":{"type":"integer"},"itered":{"type":"array","items":{}},"itered_len":{"type":"integer"},"args":{}}},"flow_jobs":{"type":"array","items":{"type":"string"}},"flow_jobs_success":{"type":"array","items":{"type":"boolean"}},"flow_jobs_duration":{"type":"object","properties":{"started_at":{"type":"array","items":{"type":"string"}},"duration_ms":{"type":"array","items":{"type":"integer"}}}},"branch_chosen":{"type":"object","properties":{"type":{"type":"string","enum":["branch","default"]},"branch":{"type":"integer"}},"required":["type"]},"branchall":{"type":"object","properties":{"branch":{"type":"integer"},"len":{"type":"integer"}},"required":["branch","len"]},"approvers":{"type":"array","items":{"type":"object","properties":{"resume_id":{"type":"integer"},"approver":{"type":"string"}},"required":["resume_id","approver"]}},"failed_retries":{"type":"array","items":{"type":"string","format":"uuid"}},"skipped":{"type":"boolean"},"agent_actions":{"type":"array","items":{"type":"object","oneOf":[{"type":"object","properties":{"job_id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"type":{"type":"string","enum":["tool_call"]},"module_id":{"type":"string"}},"required":["job_id","function_name","type","module_id"]},{"type":"object","properties":{"call_id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"resource_path":{"type":"string"},"type":{"type":"string","enum":["mcp_tool_call"]},"arguments":{"type":"object"}},"required":["call_id","function_name","resource_path","type"]},{"type":"object","properties":{"type":{"type":"string","enum":["web_search"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["approval"]},"call_id":{"type":"string"},"calls":{"type":"array","items":{"type":"object","properties":{"function_name":{"type":"string"},"arguments":{}},"required":["function_name","arguments"]}},"expires_at":{"type":"string","format":"date-time"}},"required":["type","call_id","calls","expires_at"]},{"type":"object","properties":{"type":{"type":"string","enum":["question"]},"call_id":{"type":"string"},"question":{"type":"string"},"choices":{"type":"array","items":{"type":"string"},"description":"モデルが提案する回答です。自由記述での回答も常に可能です"},"multi_select":{"type":"boolean","description":"複数の選択肢を同時に選べるかどうかです"},"expires_at":{"type":"string","format":"date-time"}},"required":["type","call_id","question","expires_at"]},{"type":"object","properties":{"type":{"type":"string","enum":["message"]}},"required":["content","type"]}]}},"agent_actions_success":{"type":"array","items":{"type":"boolean"}}},"required":["type"]}}

コメント