Hermes Agent 入門 — 初心者のためのハンズオンガイド|2026-09 版
第 9 章

サブエージェントと委譲 — 並列化とゼロコンテキスト RPC

delegate_task の使いどころ、バッチ並列、execute_code との RPC、ワークツリー隔離

この章で分かること

これは何か

Hermes のエージェントは、会話の途中で自分自身に似た子エージェントを何体でも呼び出せる。これを担うのが delegate_task という組み込みツールで、これ自体はユーザーがコマンドとして打つものではなく、エージェントが状況に応じて自分の判断で呼び出す。子エージェントは AIAgent のインスタンスとして隔離されたコンテキストで起動され、親と同じツールセットを引き継ぎつつ、独自のターミナルセッションを持つ。子が何をしたかの詳細は親の会話には流れ込まず、最終的な要約だけが戻ってくる。

もうひとつ、性質の異なる委譲手段が execute_code である。こちらは新しい推論主体を作るのではなく、エージェント自身が書いた Python スクリプトを子プロセスとして実行し、スクリプトからツールを呼び戻すための仕組みだ。両者は「コンテキストを圧迫せずに多くの作業をこなす」という同じ問題を、まったく違うやり方で解いている。

ユーザー側から直接触れる入口は主に 2 つある。ひとつは会話の中で「これは別のサブエージェントに任せて」のように明示的に頼む自然言語の指示(もっとも、公式ドキュメントも明言するとおり、エージェントはタスクの複雑さを見てほぼ自動的に委譲を判断するので、明示的に頼む必要は必ずしもない)。もうひとつは、直前の会話が生んだ成果物をレビューさせる /review スラッシュコマンドで、これは対話 CLI・TUI・Desktop・全ゲートウェイプラットフォームで使える。細かな挙動の調整は ~/.hermes/config.yaml の delegation セクションで行う。~/.hermes/ 配下の全体像は 第 2 章 を参照してほしい。

いつ使うのか

典型的な使いどころは次の 4 つである。

delegate_task と execute_code は名前こそ似た文脈で語られるが、中身は「推論するかどうか」で根本的に違う。迷ったらこの表で選ぶ。

要素delegate_taskexecute_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 に自動で埋め込まれる。つまりリポジトリの規約を守らせたいだけなら、それは自動で伝わる。

ゴールと文脈だけを渡す 最終サマリのみ 親エージェント (今の会話) サブエージェント 隔離コンテキスト・独自ターミナル サブエージェント 隔離コンテキスト・独自ターミナル サブエージェント 隔離コンテキスト・独自ターミナル
図 9-1 delegate_task は隔離済みの子エージェントを起動し、渡した goal と context 以外の会話履歴は一切引き継がない。親に戻るのは各子の最終サマリだけである(点線)。

バッチモードの並列実行と 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 スクリプトを書き、それを子プロセスとして実行させるツールである。流れは次のとおりだ。

  1. エージェントが hermes_tools をインポートする Python スクリプトを書く
  2. Hermes が RPC スタブ関数を持つ hermes_tools.py を生成する
  3. Hermes が Unix ドメインソケットを開き、RPC リスナースレッドを起動する
  4. スクリプトは子プロセスとして実行され、ツール呼び出しはソケット越しに Hermes 側へ飛ぶ
  5. 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 回以上のツール呼び出しをループや条件分岐で組み合わせる場面が、このツールの主戦場だと考えるとよい。

スクリプトを生成・実行 ツール呼び出し 結果 print() 出力のみが戻る LLM(エージェント) (今の会話) Pythonスクリプト (子プロセス) Hermesのツール群 (RPCリスナー)
図 9-2 execute_code はスクリプトを子プロセスで動かし、ツール呼び出しは Unix ドメインソケット越しの RPC で完結する。LLM のコンテキストに戻るのは print() の出力だけで、途中のツール結果は含まれない。

ブロックされるツール・ネスト・タイムアウト・ワークツリー隔離

ブロックされるツールと role="orchestrator"

子エージェントは親と同じツールセットを引き継ぐが、無制限ではない。既定の role="leaf"(葉)の子エージェントでは、次のツールがブロックされる。

一方 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 等のリモートバックエンドではエラーにはならず、静かに既定の共有ワークスペース動作へ切り替わる。

同時に書き込む 分岐 分岐 既定(isolation: false) isolation: true 子1 子2 共有の作業ディレクトリ 衝突の恐れ 共通の起点(HEAD) 子1のworktree branch: subagent-1 子2のworktree branch: subagent-2 親が git merge で統合
図 9-3 delegation.worktree_isolation を有効にすると、既定の共有ディレクトリ編集(左)に代わり、各子が HEAD から分岐した専用の git worktree で作業する(右)。git 管理下かつローカルバックエンド限定の機能で、条件を満たさない環境では黙って左の既定動作に戻る。

設定例と /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 単発のサブエージェントに調べ物を任せる

  1. hermes で対話セッションを開始し、独立して調べられるタスクを明示的にサブエージェントへ任せるよう頼む(例:「このリポジトリでテストが失敗している原因を、別のサブエージェントに調べさせて」)。
  2. 実行中は対話 CLI のツリービュー表示に注目する。

子エージェントが呼び出しているツールがリアルタイムに流れる様子が見えるはずだ。完了すると、親の会話には途中のツール呼び出しは表示されず、子がまとめた最終サマリだけが差し込まれる。「サブエージェントは何も知らない」ため、依頼するときは対象のファイルパスやエラー内容など、子が判断に必要な情報をできるだけ具体的に伝えるとよい。

ハンズオン 9-2 バッチモードで複数の調べ物を並列に進める

課金に注意 — バッチで並列に走る子エージェントは、それぞれが独立してモデルへの API 呼び出しを行う。直列で 1 つずつ頼むより短時間で終わる代わりに、同時に消費するトークン量・API 呼び出し回数もほぼ並列数だけ増える。既定の最大並列数は 3 だが、調べ物の本数や1本あたりの重さによっては想定より高くつくことがある。

  1. 互いに独立した複数の調べ物を一度に頼む(例:「トピック A・B・C についてそれぞれ別のサブエージェントで並行して調べて、まとめて教えて」)。
  2. 実行中の様子を確認する。

対話 CLI ではツリービュー表示に複数の子が同時に進む様子が並んで表示される。すべて完了すると、結果は完了した順ではなく、依頼した順(A・B・C の順)にソートされて 1 つの応答にまとまって返ってくる。並列数を増減したい場合は ~/.hermes/config.yaml の delegation.max_concurrent_children を変更する。

ハンズオン 9-3 /review でコードレビューを走らせる

  1. エージェントに何らかのコード変更や PR 作成を行わせた直後に、次のコマンドを打つ。
/review

独立したフル権限のバックグラウンドサブエージェントが起動し、直前の会話が生んだ成果物(PR・diff・コードなど)を実際に開いて調べ始める。

  1. 特定の観点を重視してほしいときは、指示を添えて呼ぶ。
/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" を指定しても孫は作れない。

まとめ

参考リンク