この章で分かること
delegate_taskが隔離コンテキストの子エージェントをどう立ち上げるか、そして「サブエージェントは何も知らない」という大原則tasks配列によるバッチモードでの並列実行と、並列数が増える分だけ課金も増える点execute_codeが Python スクリプトから Unix ドメインソケット経由でツールを呼び、多段パイプラインを 1 ターンに畳む仕組みdelegate_taskとexecute_codeの使い分け、サブエージェントでブロックされるツール、role="orchestrator"によるネスト- タイムアウト・ワークツリー隔離・設定例・
/reviewコマンドで安全に運用する方法
これは何か
Hermes のエージェントは、会話の途中で自分自身に似た子エージェントを何体でも呼び出せる。これを担うのが delegate_task という組み込みツールで、これ自体はユーザーがコマンドとして打つものではなく、エージェントが状況に応じて自分の判断で呼び出す。子エージェントは AIAgent のインスタンスとして隔離されたコンテキストで起動され、親と同じツールセットを引き継ぎつつ、独自のターミナルセッションを持つ。子が何をしたかの詳細は親の会話には流れ込まず、最終的な要約だけが戻ってくる。
もうひとつ、性質の異なる委譲手段が execute_code である。こちらは新しい推論主体を作るのではなく、エージェント自身が書いた Python スクリプトを子プロセスとして実行し、スクリプトからツールを呼び戻すための仕組みだ。両者は「コンテキストを圧迫せずに多くの作業をこなす」という同じ問題を、まったく違うやり方で解いている。
ユーザー側から直接触れる入口は主に 2 つある。ひとつは会話の中で「これは別のサブエージェントに任せて」のように明示的に頼む自然言語の指示(もっとも、公式ドキュメントも明言するとおり、エージェントはタスクの複雑さを見てほぼ自動的に委譲を判断するので、明示的に頼む必要は必ずしもない)。もうひとつは、直前の会話が生んだ成果物をレビューさせる /review スラッシュコマンドで、これは対話 CLI・TUI・Desktop・全ゲートウェイプラットフォームで使える。細かな挙動の調整は ~/.hermes/config.yaml の delegation セクションで行う。~/.hermes/ 配下の全体像は 第 2 章 を参照してほしい。
いつ使うのか
典型的な使いどころは次の 4 つである。
- 途中経過まで含めて親の会話に流し込むとコンテキストを圧迫する大きな作業(複数ファイルにまたがるリファクタ、深い調査など)を切り出したい →
delegate_task(単発) - 互いに独立した複数の調べ物・作業を同時に進めたい(トピック A・B・C を並行調査するなど)→
delegate_task(バッチ) - 「ファイルを探す → 読む → 加工する → 出力する」のような機械的な多段処理を、途中結果をコンテキストに残さず 1 ターンで済ませたい →
execute_code - 直前にできあがった PR・diff・ドキュメントを、別の視点でレビューしてほしい →
/review
delegate_task と execute_code は名前こそ似た文脈で語られるが、中身は「推論するかどうか」で根本的に違う。迷ったらこの表で選ぶ。
| 要素 | delegate_task | execute_code |
|---|---|---|
| 中身 | フル LLM 推論ループを持つ隔離エージェント | Python コード実行のみ、推論なし |
| コンテキスト | 隔離された新規の会話 | 会話は無く、スクリプトが動くだけ |
| ツールアクセス | ブロックされていない全ツール + 推論 | RPC 経由の 7 ツール、推論なし |
| 並列度 | 既定で最大 3 並列(設定変更可) | 単一スクリプト |
| トークンコスト | 高め(フル LLM ループ分) | 低め(標準出力のみが返る) |
| 適する用途 | 判断力・多段の意思決定が要る複雑タスク | 機械的なデータ処理・定型パイプライン |
判断に迷ったときの目安はこうだ。「その場で状況を見て次の一手を決める必要がある」なら delegate_task、「手順そのものは決まっていて、ただ繰り返すだけ」なら execute_code。なお、定型の作業手順自体を再利用したいだけなら、そもそもエージェントを増やす必要はなく スキル(第 6 章)の出番であり、セッションを閉じても生き残る自動実行を組みたいなら cron スケジューラ(第 8 章)の役割になる。この章では、あくまで「今の会話の中で」作業を並列化・委譲する仕組みに絞る。
delegate_task の基本と「サブエージェントは何も知らない」
delegate_task は goal(達成してほしいこと)と context(そのために必要な背景情報)を渡して子エージェントを起動する。単発なら次のように呼ばれる。
delegate_task(
goal="Debug why tests fail",
context="Error: assertion in test_foo.py line 42"
)
ここで初心者がもっとも誤解しやすいのが、子エージェントに「何が引き継がれるか」である。公式ドキュメントは次のように明記している。
サブエージェントは完全にまっさらな会話として始まる。親の会話履歴、それ以前のツール呼び出し、委譲より前に話していたことについて、子エージェントはゼロから何も知らない。子エージェントが持つ文脈は、親が delegate_task を呼ぶときに渡した goal と context だけである。
つまり「あのエラーを直しておいて」のような曖昧な goal だけを渡すと、子エージェントは「あのエラー」が何かを知る手段を持たない。ファイルパス・エラーメッセージ・プロジェクトの前提など、子エージェントが必要とする情報は親が context に全部書き切る必要がある。例外は 1 つだけあり、親が解決済みのワークスペースディレクトリを持っている場合、そのワークスペースのプロジェクト規約ファイル(.hermes.md → AGENTS.md チェーン → CLAUDE.md → .cursorrules の優先順位、人格定義の SOUL.md は対象外)は全サブエージェントの system prompt に自動で埋め込まれる。つまりリポジトリの規約を守らせたいだけなら、それは自動で伝わる。
バッチモードの並列実行と execute_code による RPC
バッチモード(並列実行)
goal / context のペアを tasks 配列で複数渡すと、それぞれ独立した子エージェントとして並列に実行される。
delegate_task(tasks=[
{"goal": "Research topic A", "context": "..."},
{"goal": "Research topic B", "context": "..."},
{"goal": "Fix the build", "context": "..."}
])
既定の最大並列数は 3 で、delegation.max_concurrent_children(または環境変数 DELEGATION_MAX_CONCURRENT_CHILDREN)で変更でき、上限は無い。内部では ThreadPoolExecutor が設定した並列数をワーカー数として使う。対話 CLI ではツリービュー表示で各子の進行がリアルタイムに流れ、結果は完了した順ではなく、渡した tasks の並び順にソートされて返ってくる。
execute_code との RPC
execute_code は、エージェントが from hermes_tools import ... という書き出しで Python スクリプトを書き、それを子プロセスとして実行させるツールである。流れは次のとおりだ。
- エージェントが
hermes_toolsをインポートする Python スクリプトを書く - Hermes が RPC スタブ関数を持つ
hermes_tools.pyを生成する - Hermes が Unix ドメインソケットを開き、RPC リスナースレッドを起動する
- スクリプトは子プロセスとして実行され、ツール呼び出しはソケット越しに Hermes 側へ飛ぶ
print()の出力だけが LLM に返り、途中のツール結果はコンテキストウィンドウに一切入らない
from hermes_tools import web_search, web_extract
results = web_search("Python 3.13 features", limit=5)
for r in results["data"]["web"]:
content = web_extract([r["url"]])
# ... フィルタして加工 ...
print(summary)
スクリプト内から呼べるツールは web_search / web_extract / read_file / write_file / search_files / patch / terminal(フォアグラウンドのみ)の 7 種類に限られる。Windows では AF_UNIX が不安定なためループバック TCP ソケットにフォールバックし、Docker・SSH・Modal のようなリモートバックエンドではファイルベースの RPC トランスポートに切り替わる(バックエンド側に Python 3 が必要)。3 回以上のツール呼び出しをループや条件分岐で組み合わせる場面が、このツールの主戦場だと考えるとよい。
ブロックされるツール・ネスト・タイムアウト・ワークツリー隔離
ブロックされるツールと role="orchestrator"
子エージェントは親と同じツールセットを引き継ぐが、無制限ではない。既定の role="leaf"(葉)の子エージェントでは、次のツールがブロックされる。
delegate_task— さらに孫エージェントを作れない(既定)clarify— ユーザーに聞き返せないmemory— 共有の永続メモリへの書き込みができないsend_message— 他プラットフォームへの副作用を起こせないcronjob— 親の名前で新しいスケジュールを組めない
一方 execute_code はどちらの役割でも保持される。機械的な処理は子エージェントの中でも続けられるようにする、という設計である。
既定の flat delegation(親 → 子までで、子はさらに委任できない)を破りたいときは、role="orchestrator" を指定する。
delegate_task(
goal="Survey three code review approaches and recommend one",
role="orchestrator",
context="..."
)
ただし role="orchestrator" を指定しただけでは孫エージェントは作れない。ネストの深さは delegation.max_spawn_depth(既定 1 = flat)で管理されており、2 に上げて初めて orchestrator の子が孫(leaf)を持てるようになる。3 以上でさらに深いツリーも組めるが上限は無い。delegation.orchestrator_enabled: false にすると、role の指定に関わらず全ての子が強制的に leaf になる。
ネストの深さはコストに直結する — max_spawn_depth: 3 かつ max_concurrent_children: 3 の組み合わせでは、理論上 3 × 3 × 3 = 27 体の leaf エージェントが同時に動きうる。1 段深くするごとに支出は掛け算で増えるので、max_spawn_depth を上げるのは意図を持って行うべきである。
タイムアウトとワークツリー隔離
子エージェントには既定でハードなウォールクロックタイムアウトが無い。以前のバージョンには 300 秒・600 秒といった固定の打ち切りがあったが、深いコードレビューや大規模な調査のように、着実に進んでいても 10 分以上かかる子を誤って殺してしまう問題があったため撤廃された。完全に止まってしまった子はハートビート監視で検知される。コスト管理のために上限を設けたい場合は、delegation.child_timeout_seconds(既定 0 = 無効)にオプトインで正の値を設定する。
もうひとつの安全策がワークツリー隔離である。既定では、複数の子エージェントは親と同じ作業ディレクトリを共有するため、並列で同じリポジトリを編集すると衝突しうる。delegation.worktree_isolation: true にすると、各子は現在の HEAD から分岐した専用の git worktree(<repo>/.worktrees/subagent-<id>、ブランチ名 hermes-subagent/subagent-<id>)の中で作業するようになり、親のチェックアウトは触られない。子が完了すると結果にはコミット数や変更の有無が付き、親はブランチごとに git log や git merge でレビュー・統合できる。この機能は git 管理下かつローカルターミナルバックエンド限定で、git 管理外のディレクトリや Docker・SSH 等のリモートバックエンドではエラーにはならず、静かに既定の共有ワークスペース動作へ切り替わる。
設定例と /review コマンド
委譲まわりの設定は ~/.hermes/config.yaml の delegation セクションに集約されている。
delegation:
max_iterations: 50 # 子1体あたりの最大ターン数(既定: 50)
# max_concurrent_children: 3
# worktree_isolation: false
# max_spawn_depth: 1
# orchestrator_enabled: true
model: "google/gemini-3-flash-preview" # 子エージェント用のモデル上書き
provider: "openrouter"
# 直接エンドポイントを指定する場合
delegation:
model: "qwen2.5-coder"
base_url: "http://localhost:1234/v1"
api_key: "local-key"
delegation.model / delegation.provider を省略すると、子エージェントは親と同じモデル・プロバイダを引き継ぐ。よくある構成は「計画は高性能なフロンティアモデル、実行は安価なモデル」という役割分担だ。タスクを的確な粒度に分解するには高い判断力が要るが、ゴールと文脈が揃った後の実行そのものはそこまで要求が高くない。しかも並列バッチの子エージェントは、1 回のランで消費するトークンの大半を占めることが多い。そのため親のモデルはフロンティアモデルのまま、delegation.model だけ安価なモデルに固定すると、計画の質を落とさずに支出を抑えやすい。
成果物のレビューには /review を使う。これは独立したフル権限のバックグラウンドサブエージェントを起動し、直前の会話が生み出した PR・diff・コード・ドキュメントを実際に開いて調べさせるコマンドで、対話 CLI・TUI・Desktop・全ゲートウェイプラットフォームで動作する。
/review # 直前の成果物をレビュー
/review focus on security # 追加の指示を添える
典型的な流れは、メインのエージェントが PR を作成し、その直後に /review を打つというものだ。レビュー用のサブエージェントは delegate_task と同じバックグラウンド委譲の仕組みに乗るため、抜粋だけを読んで判断するのではなく、実際に diff を開きコードを実行して調べる。レビューが終わると、その結果は通常のバックグラウンドサブエージェント完了と同じ経路でメインのエージェントに戻り、指摘への対応を続けられる。
ハンズオン 9-1 単発のサブエージェントに調べ物を任せる
hermesで対話セッションを開始し、独立して調べられるタスクを明示的にサブエージェントへ任せるよう頼む(例:「このリポジトリでテストが失敗している原因を、別のサブエージェントに調べさせて」)。- 実行中は対話 CLI のツリービュー表示に注目する。
子エージェントが呼び出しているツールがリアルタイムに流れる様子が見えるはずだ。完了すると、親の会話には途中のツール呼び出しは表示されず、子がまとめた最終サマリだけが差し込まれる。「サブエージェントは何も知らない」ため、依頼するときは対象のファイルパスやエラー内容など、子が判断に必要な情報をできるだけ具体的に伝えるとよい。
ハンズオン 9-2 バッチモードで複数の調べ物を並列に進める
課金に注意 — バッチで並列に走る子エージェントは、それぞれが独立してモデルへの API 呼び出しを行う。直列で 1 つずつ頼むより短時間で終わる代わりに、同時に消費するトークン量・API 呼び出し回数もほぼ並列数だけ増える。既定の最大並列数は 3 だが、調べ物の本数や1本あたりの重さによっては想定より高くつくことがある。
- 互いに独立した複数の調べ物を一度に頼む(例:「トピック A・B・C についてそれぞれ別のサブエージェントで並行して調べて、まとめて教えて」)。
- 実行中の様子を確認する。
対話 CLI ではツリービュー表示に複数の子が同時に進む様子が並んで表示される。すべて完了すると、結果は完了した順ではなく、依頼した順(A・B・C の順)にソートされて 1 つの応答にまとまって返ってくる。並列数を増減したい場合は ~/.hermes/config.yaml の delegation.max_concurrent_children を変更する。
ハンズオン 9-3 /review でコードレビューを走らせる
- エージェントに何らかのコード変更や PR 作成を行わせた直後に、次のコマンドを打つ。
/review
独立したフル権限のバックグラウンドサブエージェントが起動し、直前の会話が生んだ成果物(PR・diff・コードなど)を実際に開いて調べ始める。
- 特定の観点を重視してほしいときは、指示を添えて呼ぶ。
/review focus on security
レビューが完了すると、その結果はメインのエージェントの会話に戻ってくる。指摘があれば、そのまま同じ会話で修正を依頼できる。
つまずきポイント
goal だけ渡して context を省略しない — 子エージェントは親の会話を一切知らない。「あのエラーを直して」のような曖昧な指示では、子は「あのエラー」が何を指すか判断できずに的外れな作業をするか、行き詰まって終わる。ファイルパス・エラーメッセージ・プロジェクトの前提など、子が必要とする情報は毎回 context に書き切る。
タイムアウトが無いことを「固まっても放置してよい」と誤解しない — 既定では子エージェントにハードな時間制限が無いため、深い調査などで長時間動くのは正常な挙動である。ただしコスト管理のために上限を設けたい場合は delegation.child_timeout_seconds にオプトインで正の秒数を設定できる(既定 0 は無効を意味する)。
role="orchestrator" だけでは孫エージェントは生まれない — ネストの深さは delegation.max_spawn_depth(既定 1 = flat)で制御されており、これを 2 以上に上げない限り、role="orchestrator" を指定しても孫エージェントは作れない。上げるほど並列数の掛け算でコストが跳ね上がる点も忘れないこと。
ワークツリー隔離は万能ではない — delegation.worktree_isolation: true は git 管理下かつローカルターミナルバックエンドでしか効かない。git 管理外のディレクトリや Docker・SSH などのリモートバックエンドではエラーにならず、黙って既定の共有ディレクトリ動作に戻ってしまう。隔離されているはずと思い込んで並列編集を任せると、想定外の衝突が起きうる。
理解度チェック
Q1. delegate_task で立ち上がる子エージェントが親から引き継ぐものと引き継がないものをそれぞれ説明してください。
引き継ぐのは親と同じツールセット。引き継がないのは会話履歴・過去のツール呼び出しなど、goal と context 以外のすべて。例外として、親が解決済みのワークスペースを持つ場合はプロジェクト規約ファイル(.hermes.md / AGENTS.md チェーン / CLAUDE.md / .cursorrules)だけは全サブエージェントの system prompt に自動で埋め込まれる。
Q2. バッチモードの既定の最大並列数はいくつで、何を変更すれば増減できますか。
既定は 3。delegation.max_concurrent_children(または環境変数 DELEGATION_MAX_CONCURRENT_CHILDREN)で変更でき、上限は無い。
Q3. delegate_task と execute_code の最大の違いを一言で説明してください。
delegate_task はフル LLM 推論ループを持つ隔離エージェントを立ち上げるのに対し、execute_code は推論を伴わず Python スクリプトの実行結果(print() 出力)だけを RPC 経由で返す。前者は判断力が要る複雑タスク向け、後者は機械的な多段処理向け。
Q4. leaf サブエージェントでブロックされるツールを 3 つ挙げてください。
delegate_task・clarify・memory・send_message・cronjob のうち任意の 3 つ。いずれも「さらに委任する」「ユーザーに聞き返す」「共有メモリに書く」「他プラットフォームへ副作用を起こす」「親の名前でスケジュールする」という、隔離された子には許すべきでない操作である。
Q5. role="orchestrator" を指定した子が、さらに孫エージェントを持てるようにするには何を変更する必要がありますか。
delegation.max_spawn_depth を既定の 1(flat)から 2 以上に引き上げる必要がある。1 のままでは role="orchestrator" を指定しても孫は作れない。
まとめ
- delegate_task は隔離コンテキストの子エージェントを起動する。子は親の会話を一切知らないため、goal と context に必要な情報をすべて書き切る必要がある
- tasks 配列によるバッチモードは既定で最大 3 並列。子が増えるほど短時間で終わる一方、API 呼び出しとトークン消費もほぼ並列に増える
- execute_code は推論を伴わない Python スクリプト実行で、Unix ドメインソケット越しの RPC で 7 種類のツールを呼べる。返るのは print() 出力だけ
- role="orchestrator" と max_spawn_depth でネストを許可できるが、深さは並列数の掛け算でコストに直結する。worktree_isolation は git かつローカルバックエンド限定で並列編集の衝突を避けられる
- 次の第 10 章では、これらの子エージェントが実際にコマンドを実行する場である 7 種類のターミナルバックエンドを扱う