セルフホスト型LLMワークフローにおけるHermesエージェントの看板
セルフホスト型LLMにおけるHermesカーンボードの負荷を制御する
Hermes AgentにはKanbanスタイルのボードとHermes Gatewayが標準で搭載されていますが、一度に多数のタスクがディスパッチされると、セルフホスト型のLLMが過負荷状態に陥る可能性があります。
この方法で、あなた自身のLLMをDoS(サービス拒否)攻撃の状態に簡単に追い込むことができると言えます。
Hermes Kanbanは ~/.hermes/kanban.db にバックアップされた耐久性のあるマルチプロフィールボードです。
各レーン(列)は作業のフェーズを表し、各カードは特定のHermesプロフィールによって引き受けることができるタスクです。
デフォルト設定では、ディスパッチャは複数の「ready(準備完了)」状態のタスクを一度に促進(実行へ移行)できます。これは伸縮性のあるクラウドAPIでは問題ありませんが、小規模なセルフホスト型GPUクラスターではオーバーロードを引き起こす可能性があります。
このスタックに慣れていない場合は、まずはより広範なHermesのセットアップと運用ガイドと、AI Systemsの柱を参照して、周辺のアーキテクチャを理解してください。

本記事では、以下の方法を解説します:
- 理解する:Hermes KanbanのディスパッチがLLMゲートウェイとどのように相互作用するか。
- 制御する:重いタスクに対して並列性を安全に制御する方法。
- バッチ処理する:Cronを使用して促進をバッチ化し、バックグラウンドジョブが対話型使用と衝突しないようにする。
- 監視・調整する:GPUが過負荷になることなく、稼働状態を維持するようにシステムを監視・調整する。
Hermes Kanbanとディスパッチャの仕組み
高レベルで見て、このシステムには3つのレイヤーがあります:
- ボード:タスク、列、関係、履歴のための耐久性のあるSQLite状態管理。
- ワーカー:タスクを処理するために隔離されたワークスペースで起動されるHermesプロフィール。
- ディスパッチャ:ディスパッチ可能なカードをスキャンし、実行を開始する長期稼働プロセス。
CLIまたはダッシュボードから作成されたタスクは、通常 backlog または ready 状態で開始されます。
ディスパッチャは適格なカードをスキャンし、原子的操作で1つをクレーム(確保)し、割り当てられたプロフィールとそのツール・メモリで実行を開始します。
各ワーカーはその後、LLMゲートウェイまたはローカルランタイム(例えば、Ollama、vLLM、llama.cppでバックアップされたOpenAI互換エンドポイント)を呼び出します。これらのランタイム間のデプロイメント選択については、LLMホスティング 2026 ローカルセルフホスト型とクラウドインフラストラクチャの比較を参照してください。Ollama自体のリクエストファノアウトをチューニングしている場合、Ollamaが並列リクエストを処理する方法と組み合わせることで効果的です。
多数の重いタスクを追加し、促進(Promotion)に上限を設定しないと、ゲートウェイは並行リクエストで溢れてしまいます。
シングルGPUまたはCPU制約のあるホストでは、それによりスループットの向上ではなく、キューイング、スラッシング、タイムアウトが発生することがよくあります。
今日の実際的な制限
現在のHermesビルドで多くのチームが運用している状況では、ディスパッチャ設定はKanbanディスパッチ用のキーを2つしか公開しておらず、設定からグローバルなアクティブタスクの上限を適用しません:
kanban:
dispatch_in_gateway: false
dispatch_interval_seconds: 10
アクティブタスクの制御については、明示的なディスパッチ周期(hermes kanban dispatch --max ...)と依存関係モデリングに依存してください。
既知の落とし穴:
- ゲートウェイに埋め込まれたディスパッチと
hermes kanban daemon --forceを同じボードに対して実行しないでください。そうしないと、クレームの競合が発生する可能性があります。 - ゲートウェイがダウンしている場合、
readyタスクはディスパッチされず、サービスが復旧した際にバースト(一時的な大量発生)を引き起こす可能性があります。 - 長いディスパッチ間隔は、クレームがティック単位で行われるため、不均一に感じられる場合があります。
- ラン状態とリクレームの境界条件が時間の経過とともに修正されたため、バージョン間で動作が異なる場合があります。
動作が正しくないように見える場合のクイック検証:
# 1) 正確に1つのディスパッチャパスがアクティブであることを確認
pgrep -af "hermes gateway start|hermes kanban daemon"
# 2) 接続されたKanbanディスパッチャキーを確認
rg "dispatch_in_gateway|dispatch_interval_seconds" ~/.hermes/config.yaml
# 3) キューの形状を検査
hermes kanban list --status ready
hermes kanban list --status running
重要な概念:
- ディスパッチャ設定は
dispatch_in_gatewayとdispatch_interval_secondsを接続します。 dispatch --maxは、そのパス(一連の処理)での新しい生成のみを制限し、実行中の総タスク数ではありません。- 小規模なセルフホスト型クラスターの場合、保守的な値から始め、レイテンシが安定してからのみ増加させてください。
HermesをLLMゲートウェイの近くに初めてデプロイする際:
- 設定にはサポートされているKanbanディスパッチャキーのみを含めます。
- 実際のキュー負荷下でのGPUおよびCPU使用率を観察します。
- 決定論的なペース配分のために戦略1または戦略2を使用します。
調査結果と根本原因
hermes kanban dispatch は config.yaml から max_active_tasks を読み込みません。
hermes_cli/kanban.py では、ディスパッチコマンドは --max をCLIの上限(デフォルト None)として公開し、args.max のみを kb.dispatch_once(...) に渡します。このパスには max_active_tasks の設定lookupはありません。hermes_cli/kanban.py 元ファイルを参照してください。
次に kanban_db.dispatch_once では、唯一の上限は max_spawn で、論理は以下と同等です:
if max_spawn is not None and spawned >= max_spawn:
break
すでに実行中のタスクのチェックはなく、そのディスパッチパスには max_active_tasks の参照もありません。hermes_cli/kanban_db.py 元ファイルを参照してください。
実際の動作:
hermes kanban dispatch
そのパスでは無制限(readyキューのサイズで制限)。
hermes kanban dispatch --max 2
そのパスでの新しい生成のみを制限し、実行中の総タスク数ではありません。
ゲートウェイディスパッチ回りの接続された設定ノブは kanban.dispatch_in_gateway と kanban.dispatch_interval_seconds です。
したがって、max_active_tasks は実装されていないため、このディスパッチパスでは無視されます。
戦略1 - 厳密にシーケンシャルなフローのための依存関係のエンコーディング
一部のワークフローは厳密に1つずつ連続して実行されるべきです。例えば:
- 共有中間アーティファクトを持つマルチステップデータパイプライン
- マイグレーションまたはインフラストラクチャの変更
- 同じオブジェクトストアまたはデータベースに書き込むバッチジョブ
Hermes Kanbanはタスク間の親子依存関係をサポートしており、子カードは親が完了した後にのみディスパッチ可能になります。
Hermes CLIの周りに小さなヘルパースクリプトを作成することで、これをモデル化できます:
#!/usr/bin/env bash
set -euo pipefail
parent_id="$(hermes kanban add \
--title '4月の顧客ログをインジェクト' \
--profile 'etl-worker' \
--column backlog)"
hermes kanban add \
--title '4月の異常レポートを生成' \
--profile 'analytics-worker' \
--column backlog \
--parent "${parent_id}"
hermes kanban add \
--title '4月のサマリーをダッシュボードに公開' \
--profile 'reporting-worker' \
--column backlog \
--parent "${parent_id}"
適切なボードポリシーと低いディスパッチャ制限があれば、親タスクのみが最初に実行されます。
それが完了すると、子タスクは徐々に準備完了状態になり、ディスパッチャは並行性の上限を超えずに1つずつ引き受けます。
戦略2 - 実行中のタスクを認識するディスパッチキャップを持つLinux cronを使用
決定論的なペース配分を望む場合、ホストのcronと小さなラッパー・スクリプトを使用してください。
常に dispatch --max 2 を呼び出すのではなく、まず現在実行中のタスクをカウントし、残りのスロット分のみをディスパッチします。
hermes-kanban-dispatch-capped.sh を作成します:
#!/usr/bin/env bash
set -euo pipefail
MAX_PARALLEL="${MAX_PARALLEL:-2}"
BOARD="${BOARD:-}"
board_args=()
if [[ -n "$BOARD" ]]; then
board_args=(--board "$BOARD")
fi
# またはhermesがインストールされている場所
export PATH="/home/abc/.local/bin:$PATH"
running_out="$(hermes kanban "${board_args[@]}" list --status running)"
if [[ "$running_out" == *"(no matching tasks)"* ]]; then
running_count=0
else
running_count="$(printf '%s\n' "$running_out" | wc -l)"
fi
slots=$(( MAX_PARALLEL - running_count ))
if (( slots <= 0 )); then
echo "Already at limit running=$running_count max=$MAX_PARALLEL dispatch skipped"
exit 0
fi
echo "running=$running_count max=$MAX_PARALLEL slots=$slots dispatching up to $slots"
hermes kanban "${board_args[@]}" dispatch --max "$slots"
実行可能にします:
chmod +x ./hermes-kanban-dispatch-capped.sh
以下で実行します:
MAX_PARALLEL=2 ./hermes-kanban-dispatch-capped.sh
特定のボードの場合:
BOARD=my-board MAX_PARALLEL=2 ./hermes-kanban-dispatch-capped.sh
Cronで1分ごとにスケジュールします:
* * * * * /opt/hermes/scripts/hermes-kanban-dispatch-capped.sh >> /var/log/hermes/kanban-cron.log 2>&1
運用上の注意点:
- Cronは頻繁に最小限の
PATHを持つため、hermesが見つからない場合は、スクリプト内でフルパス(例:/usr/local/bin/hermes)を使用してください。 /var/log/hermes/...にログを記録する場合は、まずそのディレクトリを作成し、cronユーザーが書き込みアクセス権を持っていることを確認してください。
例:
sudo mkdir -p /var/log/hermes
sudo chown "$USER":"$USER" /var/log/hermes
以下でcronエントリを作成または編集します:
crontab -e
次に以下で検証します:
crontab -l
1つのcronエントリによる1分未満の周期
Cronは1分ごとにティックしますが、スクリプト内で短いループを実行することで、より頻繁にディスパッチできます。
hermes-kanban-dispatch-subminute.sh の例:
#!/usr/bin/env bash
set -euo pipefail
LOCK_FILE="/tmp/hermes-kanban-dispatch.lock"
RUNS_PER_MINUTE="${RUNS_PER_MINUTE:-4}" # 4回実行 => 15秒ごと
CAP_SCRIPT="${CAP_SCRIPT:-/opt/hermes/scripts/hermes-kanban-dispatch-capped.sh}"
exec 9>"$LOCK_FILE"
flock -n 9 || exit 0
sleep_seconds=$(( 60 / RUNS_PER_MINUTE ))
for ((i=1; i<=RUNS_PER_MINUTE; i++)); do
"$CAP_SCRIPT"
if (( i < RUNS_PER_MINUTE )); then
sleep "$sleep_seconds"
fi
done
実行可能にします:
chmod +x ./hermes-kanban-dispatch-subminute.sh
1分ごとにスケジュールします:
* * * * * /opt/hermes/scripts/hermes-kanban-dispatch-subminute.sh >> /var/log/hermes/kanban-subminute.log 2>&1
これにより、flock が重複する実行を防ぎながら、実質的に1分未満の周期が実現されます。
なぜこれでうまくいくのか:
list --status runningは現在の実行中負荷を示します。dispatch --max Nはそのパスでの新しい生成のみを制限します。Nを残りのスロットとして計算することで、実行中の総タスク数を目標の制限付近に保ちます。
重要な注意点:このキャップは、このスクリプトを通じて行われるディスパッチに対してのみ機能します。
ゲートウェイに埋め込まれたディスパッチを無効にしないでください。それ以外の場合、タスクを独立して促進し続ける可能性があります:
kanban:
dispatch_in_gateway: false
公式ドキュメントは、コマンド機能の両方とKanban機能ガイドにおけるゲートウェイディスパッチのデフォルトを記載しています:Hermes Kanban ドキュメント。
内部Hermes Cron
使用しないでください。
あなたのLLMに、特に有用な作業を忙しい時に、/path/hermes-kanban-dispatch-capped.sh のようなコマンドをターミナルで実行するといった定期的なプロンプトを処理させたいでしょうか?
Hermes Kanbanの監視と調整
どの戦略を選択しても、以下を監視する必要があります:
- LLMゲートウェイメトリクス — リクエストレート、レイテンシ、エラーレート、トークンスループット。
- ノードの健全性 — GPU利用率、VRAM使用量、CPU負荷およびRAM。
- Hermesメトリクス — バックログ、準備完了、アクティブ、完了の各状態にあるタスクの数。
本番環境のメトリクスベースラインとダッシュボードについては、PrometheusとGrafanaを使用した本番環境でのLLM推論の監視と、より広範なLLMパフォーマンスハブを参照してください。
低い並行性から始め、以下の兆候を観察しながら制限を徐々に引き上げます:
- 一定のスループットでのレイテンシ上昇
- 増加するタイムアウトまたはレート制限エラー
- 一部のタスクが非常に長期間アクティブなままになるロングテール
これらの兆候が見え次第、以前の安定した設定にロールバックし、それをデフォルトとして維持してください。
Kanbanが適切なツールとなる場合
Hermes Kanbanは、以下の場合に真価を発揮します:
- 長寿命の研究またはエンジニアリングのバックログ
- 名前付きプロフィールを持つマルチエージェント協力
- 再起動とホストの再起動に耐える必要があるワークフロー
- 作業をトリアージするためのダッシュボードを望む人間
単に数個の一時的なヘルパーを作成するための1回の実行のみが必要な場合、組み込みの委任タスクツールの方が通常シンプルです。
しかし、履歴、ダッシュボード、およびセルフホスト型LLMに対するエージェントのアクセス方法に対する厳密な制御を必要とした時点で、Kanbanボードとディスパッチャが適切な基盤となります。
いくつかの設定調整とオプションのcronベースのバッチ処理により、ゲートウェイとハードウェアを保護しながら、Hermes Kanbanを応答性の高い状態に保つことができます。