Dynamic Workflow
目次
計画をコードに持たせた並列展開、反証による検証、段階ごとの投入。
skill の情報
| 提供元 | 追加で入れるもの — hermes skills install official/autonomous-ai-agents/dynamic-workflow で導入します |
| パス | optional-skills/autonomous-ai-agents/dynamic-workflow |
| バージョン | 2.0.0 |
| 作者 | Teknium + Hermes Agent |
| ライセンス | MIT |
| 対応プラットフォーム | linux, macos, windows |
| タグ | orchestration, fan-out, subagents, delegation, verification, migration, audit, research, campaign |
| 関連 skill | hermes-agent, simplify-code |
参考: SKILL.md 全文
Dynamic Workflow Skill
大量の作業を並列に展開するとき、それをワークフローとして実行します。計画もループも途中の結果も すべてスクリプトとディスクに置くので、親のコンテキストには検証済みの結果だけが残ります。 1回きりの並列展開、反証による収束(複数の試行と反証役)、そして何十もの作業ブランチを統合する 複数段階の大規模作業までを扱います。ただし、delegate_task を再起動後も生き残るようにするものではありません。 それは kanban swarm の役割です。
使う場面
作業の単位がはっきりしていて(ファイル1つ、エンドポイント1つ、レコード1件)、1つのコンテキストに 収まらないほど単位が多いときに使います。単位が10件ほどに満たないときや、順番に処理するしかない作業には使いません。 hermes-agent そのもののリファクタリングや修正をまとめて行う場合は、開発の進め方を定めた hermes-agent も一緒に読み込みます。並列展開の形はこの skill が受け持ちます。
前提条件
delegate_taskが使えて、delegation.max_concurrent_childrenが1回の投入分に見合う大きさであること
(既定は10。それを超える tasks=[] を渡すと、実行環境は待ち行列に回さず、はっきりしたエラーで拒否します)。 子がさらに並列展開する必要があるときだけ delegation.max_spawn_depth >= 2 にします。
- 書き込みできる実行用ディレクトリを、ターミナル環境の一時ディレクトリから決めること
($TMPDIR、なければプラットフォームの一時ディレクトリ)。/tmp を直接書いてはいけません。Termux には そうしたディレクトリがなく、ネイティブの Windows ではそこで壊れます。<tmp>/wf_<name>_<uuid>/ を実行ごとに一意に使い、 中断した以前の実行が残した古い出力を取り違えないようにします。
- 決定的な処理の層に
execute_codeがあること(その中で使えるのはweb_search、web_extract、
read_file、write_file、search_files、terminal、patch だけです)。
実行のしかた
2つの層に分けます。分け目は、実際にできることの境界です。
層 A - execute_code スクリプト |
層 B - delegate_task のまとめ投入 |
|
|---|---|---|
| 向いている作業 | 決定的な作業: N 個の URL の取得、N 個のファイルの解析、N 個のコマンドの実行、N 個の出力の雛形作成、マニフェストの作成、出力の統合 | LLM の判断が要る作業: 1単位ごとの分類、レビュー、判断、執筆、反証、リファクタリング |
| 持つもの | ループ、分岐、途中の変数 | 何も持ちません。tasks=[...] で1回呼び、各タスクがそれぞれ独立したエージェントになります |
| ツール | 上に挙げたサンドボックスのツール群。delegate_task は呼べません |
親のツールセットをそのまま引き継ぎます(タスクごとの絞り込みはできません)。子からは delegate_task、clarify、memory、send_message、cronjob_manage が外れます |
| 並列度 | 自分で決めます(ThreadPoolExecutor、バッチ) |
delegation.max_concurrent_children が上限です |
| コスト | ツール呼び出しの分だけ | タスクごとにエージェント一式が動きます。件数に比例して増えます |
まず層 A で決定的な部分を済ませ、どうしても LLM が要る手順だけを層 B で並列展開し、 最後に親で取りまとめます。
バックグラウンドが前提: 結果はメッセージとして戻ってくる
最上位の delegate_task は、タスクごとのハンドルを返してすぐに戻ります。各子の結果は、 終わった時点で新しいメッセージとして会話に入ってきます。呼び出しの次の行で out_*.csv を読むことは できません。子に依存しない作業を終わらせ、状況を1行で伝えてから、ターンを終えてください。 結果のメッセージが届くたびに、それに応じて動きます。ユーザーが普通に続けてメッセージを送っても 子は止まりませんが、/stop、/new、プロセスの終了では止まります。同期的に動くのは、 取りまとめ役のサブエージェント(depth > 0)が出した委任だけです。
早見表
- 単位は、兄弟の出力なしで答えられるものにします。そうでなければ順番に処理する作業です。
- マニフェスト:
<run>/manifest.jsonlに1行1単位で書き、件数と実行用ディレクトリを表示します。 - 子1つあたりの目安: 機械的な編集なら約8〜12か所、読むなら約2〜3千行、資料なら約50〜70 KB。
いちばん大きい単位に合わせて決めます。構造のある出力はファイルに書き、summary フィールドには 入れません(負荷がかかると切り詰められます)。JSON より区切り文字で分けた行を使います。
- 親は、統合する前にファイルの件数と、今回の実行で書かれたものかを確かめます。
- 「止まった」ように見える子は、たいてい書き込みを終えています。まずファイルシステムを見ます。
- まず範囲を絞って試し(ディレクトリ1つ、20レコード)、トークンのコストを報告してから規模を広げます。
手順
1回きりの並列展開
- 互いに独立した単位に分けます。
- 層 A の下処理でマニフェストを書きます。
- 上の目安に照らしてまとまりの大きさを決めます。タスクが
max_concurrent_children より多いときは、上限内の投入を自分で段階的に出します。
- 層 B:
delegate_task(tasks=[...])を1回呼びます。各タスクは自分の担当分を読み、
<run>/out_<i>.csv に書き、状態を表す一語を出して止まります。
- ターンを終えます。結果のメッセージが届いたらファイルを読み、検証して統合します。
全体をまたぐ取りまとめは親が行います。
反証による収束(指摘の質が問われる作業)
- 独立した試行: 同じ問いを N 個(2〜4)の子に出し、それぞれの
contextで問いの切り口を変えます。
各子は <run>/attempt_<i>.md に1行1主張で書きます。場所を特定でき、1つずつ反証できる主張だけにします (「src/routes/users.ts:142 の POST /api/users/:id/role にはロールの確認がない」)。 「認証の層に問題がある」では、反証役は崩しようがありません。
- 親で統合して重複を除き、主張ごとに何人が一致したかを記録します。
- 反証役: 2回目の投入では、各主張を反証の根拠を示して崩すよう指示し、
claim_idx|survives|counter_evidence の形で出させます。渡すのは元の資料で、 試行側の推論は渡しません。
- 生き残った主張だけを出します。反証された主張は、理由を1行添えて落とします。
- 2巡目で出てきた新しい主張も、もう一度反証にかけます。生き残りが増えなかった巡で止め、
多くても3巡までにします。
同じ仕組みは、親自身の誤った前提からも親を守ります。子に経験則 (「ファサード上のパッチ対象はすべて使われていない継ぎ目だ」)を渡すときは、 それに従って動く前に、根拠を示して反証するよう指示します。4つの班がそうした結果、 647か所の一括書き換えが59件の本当の修正になり、130以上の通っていたテストが守られました。
大規模作業の形(何十もの作業者、数段階、数時間)
1回きりの手順は、コードベース全体に手を入れる作業には広げられません。うまくいったのは次のやり方です。
- まず計測し(行数、よく変更される箇所、使われていないシンボル、判定の基準になる資料)、共有の
BRIEF.md を1つと、まとまりごとの task_<cluster>.md を書きます。子はすべて両方を読みます。 全体が方向を外れたら(子がコードを削らずに docstring を削っているなど)、指示書を1回直して 向きを変えます。出し直した子は、その修正を引き継ぎます。
- 排他的な担当: 作業者1人につきファイルのまとまり1つを持たせ、担当外の編集は統合の段階で捨てます。
1つのファイルの中でさらに分けるときは行の範囲を担当させ、補助関数もその範囲内に定義させると、 差分がきれいに統合できます。
- 検証済みの手順ごとにローカルでコミットします。子には push も PR も rebase もさせません。
コミットされた状態だけが引き継ぎになります。途中で落ちた作業者は、どれもコミットしていない 末尾の分をちょうど失いました。作業ツリーのインデックスを共有する作業者は、 git commit -- <paths> でだけコミットします。何も指定しないコミットは、兄弟がステージした変更まで持っていきました。
- 同時に動かすのは12〜16個です。1つの OAuth 許可で約40プロセスを超えると、1時間ごとの
トークン更新が一斉に起きて 401 になり、その段階の投入が全滅します。残りは待ち行列に回します。
- 親による生存確認:
completedと報告してもログが数十行しかない子や、
ブランチのコミットが0件の子は、終わっていません。その子のサブブランチを探すか、 前任の作業ツリーと差分を渡して出し直します。
- 巡ごとの統合: 基準にするコミットの SHA を固定し、衝突のないブランチは機械的に rebase し、
衝突するブランチにはそれぞれ専用の rebase 担当を付け(「main の挙動を優先し、新しい構造の中に 入れ直す」)、1本の統合ブランチにマージして、合わせたツリーでテスト一式をすべて流します。 どのブランチも単独では通っていた衝突は、ここでしか現れません。次の巡は統合したコミットから ブランチを切るので、作業者どうしが衝突しなくなります。
- 巡の統合が済んだと言う前に:
git rev-list --count <integration>..<branch>
がすべてのブランチで0であることを確かめます。作業者は、先端をマージしたあともコミットを続けます。 そのせいで、6つの担当分にわたる168件のコミットが取り残されたことがあります。
- テストの実行: マシン上で動かすのはちょうど1つだけにし、ロックファイルで守り、
-jを高くします。
-j の低い実行を並列にたくさん動かすと、遅いうえに互いのプロセスグループを落としました。 失敗したファイルは、同じ venv の素の origin/main の作業ツリーで流し直します。 ファイルごとの失敗の集合が同じなら、もともとあった失敗で、自分のせいではありません。
- main への追従は巡ごとでなく最後に行います: main の SHA を固定し、衝突したファイルを
ディレクトリ単位で作業者に分け、コミットせずに1つのマージ用作業ツリーを編集させて、 最後に親が1回だけマージをコミットします。衝突のある PR では CI が走らないので、 push のたびに先に main をマージし直します。
- 実際に動かしての QA はそれ自体を1つの段階にします: 画面や入口ごとに1班、
HERMES_HOMEを分け、
確認する前に期待する結果を書き、証拠はディスクに残し、報告だけを行います。退行と数えるのは PR と main で違いが出たものだけです。単体テストが通っていても、唯一の P0 (どのテストも通らないログイン後のコード経路)は見逃されました。
- レビュアーの主張も子の主張と同じように扱います: 何かを「元に戻す」前に、基準と比べて A/B で確かめます。
自信を持って指摘された違いのいくつかは、基準の側でもすでにそう動いていました。
- 親を再起動するときは
HANDOFF.mdが要ります: なぜ落ちたか、どのハンドルが使えなくなったか、
ブランチごとの成績表(行数の増減、import の簡易確認、対象を絞ったテスト)、そして出し直すときの 指示文そのもの。その前に、未コミットの変更がある作業ツリーをすべて wip: コミットとして保存します。
落とし穴
execute_codeのスクリプトの中でdelegate_taskを呼ぶ: サンドボックスにはありません。- 並列展開を呼んだのと同じターンで取りまとめる: ファイルはまだ存在しません。
delegate_taskが何日もバックグラウンドで生き続けると約束する: ターンの範囲でしか動かず、
プロセスとともに終わります。長く続く作業の流れなら kanban swarm、1回きりなら cronjob です。
- 内容を
summaryで判断する、完了をstatus=completedで判断する。 - 「独立した」試行すべてに同じ切り口を使う: 答えが1つにまとまってしまいます。
- 作業ツリーを使う大規模作業のどこかで
git stashを使う:refs/stashは作業ツリーをまたいで
共有されるので、別の作業者があなたの編集を pop してしまいます。比べるときは一時的な作業ツリーを使います。
- 本当の数字が低いのに、目標に届いたと報告する。「今のところ16%で、30%まではこう進めます」と伝え、
次の巡を回します。
検証
- マニフェストの行数が、想定した単位の数と一致している。
out_*.csvがすべて存在し、今回の実行で書かれている。- 落とした主張にはすべて反証の根拠が記録され、出した主張はすべて反証を通っている。
- 大規模作業では: すべてのブランチで未マージのコミットが0件、統合したツリーでテスト一式を流して
失敗は素の main と比べて振り分け済み、画面や入口ごとに実際に動かした QA の報告があり、 全体を流す前に絞った範囲でトークンのコストを報告している。