Scriptノード
Scriptノードはミニオン上でインラインのPython/Node.jsスクリプトを実行します。Skill / Transform と異なりLLMは介在しません — ミニオンが python3 または node を child_process で直接起動します。LLMトークンを使うのが無駄な決定的処理や、出力形式のブレが許容できないケース向けです。
ミニオンパッケージ 3.54.0 以降で利用可能です。
- フィルタ・ソート・数値計算・正規表現抽出・JSON整形など、LLMだと取りこぼしうるルールベースの整形。
- 下流のコードがJSONとしてパースするため、出力形式がバイト単位で決定的である必要がある。
- 変換が短く明白で、プロンプトを書く方がコードを書くより手間がかかる場合。
意味的な処理(セマンティック重複排除、要約、分類、自然言語処理)が必要なときは、SkillまたはTransformを使ってください。
| フィールド | 説明 |
|---|---|
assigned_role | "pm" または "engineer" — Scriptを実行するロール。pending-nodes のclaim filterはこれを見ます。 |
script_runtime | "python" または "node"。ミニオンがspawnするインタープリタを選択します。 |
script_source | インラインのソースコード(非空)。 |
script_timeout_seconds(任意) | 実時間タイムアウト。デフォルト 60 秒、[1, 600] の範囲。超過するとプロセスが SIGKILL され、ノードはfailedになります。 |
出力エッジに contract が貼ってあれば、HQが node-complete 時に output_data を検証します(Skill / Transform と完全に同じ経路)。
I/Oプロトコル
Section titled “I/Oプロトコル”Scriptノードはstdinとstdoutを通じて他のノードとやり取りします。
- 入力:
input_data(入力エッジから伝播するJSONオブジェクト)が、JSON値1つとしてスクリプトのstdinに流し込まれます。1回読み込んでJSONとしてパースしてください。 - 出力: スクリプトはJSONオブジェクトを1つだけstdoutに書き出します。これがそのまま
output_dataとなり、HQがノードを完了として記録した時点で次ノードのinput_dataに流れます。
Python — 次ノードへのデータ渡し
Section titled “Python — 次ノードへのデータ渡し”import sys, json
# 1. 上流ノードからの input_data を受け取るdata = json.load(sys.stdin)
# 2. 何か処理するitems = [it for it in data["items"] if it["score"] >= 0.8]
# 3. 次ノードに渡したいデータを dict にまとめるoutput = { "items": items, "total": len(items), "filtered_at": "2026-05-10",}
# 4. JSON で stdout に書く(json.dump が安全。print でも動くが、# この1つのJSON値以外を絶対に出力しないこと)json.dump(output, sys.stdout)Node.js — 次ノードへのデータ渡し
Section titled “Node.js — 次ノードへのデータ渡し”// 1. stdin を全部受け取ってから処理する(チャンクで届くので結合が必要)let raw = ''process.stdin.on('data', c => raw += c)process.stdin.on('end', () => { const data = JSON.parse(raw)
// 2. 何か処理する const items = data.items.filter(it => it.score >= 0.8)
// 3. 次ノードに渡したいデータを object にまとめる const output = { items, total: items.length, filtered_at: '2026-05-10', }
// 4. stdout に JSON だけを書く(これ以外何も出力しない) process.stdout.write(JSON.stringify(output))})次ノードからの参照
Section titled “次ノードからの参照”stdoutに書いたオブジェクトのトップレベルキーが、そのまま次ノードの input_data のフィールドとして見えます。
- 次ノードがScriptノード — 同じプロトコルを逆にやるだけ。
json.load(sys.stdin)/JSON.parse(raw)でオブジェクトを取り出し、data["items"]/data.totalで上で書いたフィールドにアクセスできます。 - 次ノードがSkillまたはTransformノード — オブジェクトはミニオンのプロンプトの
## Input Dataセクションに展開され、LLMがitems/totalを名前付きフィールドとして見ながら処理します。 - 次ノードがfan-outノード — fan-outに
fan_out_source: ".items"を設定しておけば、items配列の各要素が子インスタンスごとのinput_dataになります。
fan-outへの受け渡し — 最小例
Section titled “fan-outへの受け渡し — 最小例”# stdin: { "raw_text": "apple\nbanana\ncherry" }import sys, json
data = json.load(sys.stdin)lines = [s.strip() for s in data["raw_text"].split("\n") if s.strip()]
# fan-out は `fan_out_source` で指定したフィールドが配列であることを期待。# 各要素がそのまま子インスタンスの input_data になるので、子ノードが# 期待するフィールドを持つオブジェクトでラップして渡す。json.dump({"items": [{"name": x} for x in lines]}, sys.stdout)下流のfan-outに fan_out_source: ".items" を設定しておけば、各子は { "name": "apple" }、{ "name": "banana" }、{ "name": "cherry" } を input_data として受け取ります。
ハマりどころ
Section titled “ハマりどころ”- stdoutにJSON以外を絶対に書かない。
print("debug")を1つ混ぜるだけで出力が壊れノードがfailedになります。デバッグログはstderrに出してください(Pythonならprint("...", file=sys.stderr)、Node.jsならconsole.error(...))。stderrはoutput_summaryに格納され、実行詳細ページから確認できます。 - トップレベルの値はJSONオブジェクト必須。 配列だけ(
[1, 2, 3])やプリミティブ(42、"ok"、null)を返すとfailedになります。配列を渡したいときはオブジェクトでラップしてください:{"items": [1, 2, 3]}。 - 末尾の改行はOK。
json.dumpもJSON.stringifyも末尾改行は付けませんが、付いていてもパース時にトリムされるので問題ありません。 - outgoing edgeにcontractを貼っている場合はHQが検証する。 edgeに設定したcontractに対し、Skill / Transform と同じランタイムバリデータが走ります。required フィールドの欠落や型不一致があれば、たとえスクリプト自体が成功していてもノードはfailedになります。contractを設定していない場合は、出力オブジェクトはそのまま検証なしで下流に渡ります。
いずれの失敗も status: failed となり、stderr は output_summary に格納されるので実行詳細ページからデバッグできます。
| 原因 | 結果 |
|---|---|
| 非0終了 | failed、stderrがsummaryに格納 |
| stdoutが不正なJSON | failed、stdoutの先頭500文字がsummaryに格納 |
| stdoutはJSONだがオブジェクトでない(配列・数値・文字列・null) | failed |
| 実時間タイムアウト超過 | failed、プロセスは SIGKILL |
未対応の script_runtime | failed |
| 出力エッジのcontract検証不適合 | HQランタイムバリデータがfailedに書き換え |
バリデーションルール
Section titled “バリデーションルール”assigned_roleは必須。script_runtimeは"python"または"node"。script_sourceは非空。script_timeout_seconds(指定時)は[1, 600]の数値。
- 初期リリースではパッケージインストール非対応。 ミニオンに同梱されている各ランタイムの標準ライブラリ・組み込みモジュールのみ利用可能。
pip install/npm installは(まだ)サポートしていません — セキュリティとサプライチェーンの表面積を小さく保つため。 - スクリプトはミニオンのエージェントプロセスから
child_process.spawnで実行されます。別ユーザー・サンドボックス・ファイルシステム分離はありません。信頼境界はSkill実行と同一: グラフを編集できるのはプロジェクトメンバーだけなので、Skillに書けることはScriptにも書けるという扱いです。 - 並列実行はSkill / Transform と共有の
concurrency-manager(ミニオンあたりデフォルトMAX_CONCURRENT=2)。 - tmuxセッションは作成しません — ScriptノードはダッシュボードのTerminal一覧には現れません。
flowchart LR Search["Skill: search"] -- SearchResults --> Script["Script: filter & rank"] Script -- TopItems --> Report["Skill: write-report"]上流のSkillは余計なフィールドを含む SearchResults を出します。短いPythonスクリプトでスコアでフィルタし上位N件を残します — 決定的、ノートークン、LLMの揺れなし。下流のSkillは整形済みの TopItems を受け取って人間向けレポートを書きます。