Hermes Agentにおけるセルフホスト型LLMワークフロー用カンバン

セルフホスト型LLMのHermesカンバンの負荷を制御する。

目次

Hermes Agentには、Kanbanスタイルのボードと、一度に多くのタスクがディスパッチされるとセルフホスト型LLMを飽和状態にしてしまう可能性のあるHermes Gatewayが同梱されています。

この方法で、ご自身のLLMを簡単にDDoS(分散型サービス拒否攻撃)状態にできる、とも言えます。

Hermes Kanbanは、~/.hermes/kanban.db によってバックエンドをサポートされる、耐久性のあるマルチプロファイルボードです。
各レーン(列)は作業のフェーズを表し、各カードは特定のHermesプロファイルによって引き受けることができるタスクです。
デフォルト設定のままでは、ディスパッチャーは一度のパス(処理サイクル)で多くの ready(準備完了)状態のタスクを昇格(実行開始)させることができます。これは弾力的なクラウドAPIであれば問題ありませんが、小規模なセルフホスト型GPUクラスタでは負荷が過大になる可能性があります。

このスタックが初めての場合は、より広範なHermeesセットアップおよび運用ガイド と、周辺のアーキテクチャを理解するためのAIシステムスパイラー(柱) から始めることをお勧めします。

制御されたワーカーを伴うHermes Kanbanボード

この記事では、以下の内容を紹介します:

  • 理解する:Hermes KanbanのディスパッチがあなたのLLMゲートウェイとどのように相互作用するか。
  • 制御する:重いタスクに対する並行性(パラレリズム)を安全に管理する方法。
  • バッチ処理する:cronを使用して昇格をバッチ処理し、バックグラウンドジョブが対話的な利用と衝突しないようにする。
  • 監視および調整する:GPUが過負荷にならずに忙しく保たれるように、システムを監視・チューニングする。

Hermes Kanbanとディスパッチャーの動作原理

ハイレベルな視点で、このシステムは3つのレイヤーから構成されています:

  1. ボード - タスク、カラム、関連関係、履歴のための耐久性のあるSQLite状態。
  2. ワーカー - タスクを処理するために隔離されたワークスペースで起動されたHermesプロファイル。
  3. ディスパッチャー - ディスパッチ可能なカードをスキャンし、ラン(実行)を開始する長命なプロセス。

CLIやダッシュボードから作成されたタスクは、通常 backlog(バックログ)または ready(準備完了)状態から始まります。
以下で使用される hermes kanban サブコマンドの概要は、Hermes Agent CLI チートシート にまとめられています。
ディスパッチャーは対象となるカードをスキャンし、1つをアトミックにクレーム(引き受け)し、割り当てられたプロファイルとそのツール、メモリとともに起動します。
その後、各ワーカーはあなたのLLMゲートウェイまたはローカルランタイム(例えば、Ollama、vLLM、llama.cppによってバックエンドされるOpenAI互換エンドポイント)を呼び出します。これらのランタイム間のデプロイオプションについては、LLM Hosting in 2026 Local Self-Hosted and Cloud Infrastructure Compared をご利用ください。Ollama自体のリクエストファンアウトを調整している場合は、How Ollama Handles Parallel Requests と組み合わせて使用するのが有効です。

多くの重いタスクを追加して、昇格に上限を設定しないと、ゲートウェイは同時リクエストで洪水のような状況になります。
シングルGPUまたはCPU制約のあるホストでは、それはおそらく、より良いスループットではなく、キューイング(待ち行列)、スラッシング(メモリ交換)、タイムアウトを意味します。

今日の現実的な限界

現在の多くのチームが使用しているHermesビルドでは、ディスパッチ設定は2つのKanbanディスパッチキーのみを公開し、設定からのグローバルなアクティブタスク上限は適用されません:

kanban:
  dispatch_in_gateway: false
  dispatch_interval_seconds: 10

アクティブタスクの制御には、明示的なディスパッチ頻度(hermes kanban dispatch --max ...)と依存関係モデリングに頼ってください。

既知の落とし穴:

  • ゲートウェイ組み込みのディスパッチと hermes kanban daemon --force を同じボードに対して実行しないでください。そうすると、クエム競合(claim races)が発生する可能性があります。
  • ゲートウェイがダウンしている場合、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 は、そのパスでの新しいスパーン(起動)を制限するだけで、実行中のタスクの総数ではありません。
  • 小規模なセルフホスト型クラスタでは、保守的な設定から開始し、レイテンシが安定した後にのみ増加させます。

LLMゲートウェイの近くにHermesをデプロイする際は:

  • 設定には、サポートされているKanbanディスパッチャーキーのみを保持してください。
  • 実際のキュー圧力下でのGPUとCPUの利用率を観測してください。
  • 決定的なペーシング(ペース配分)のために、戦略1または戦略2を使用してください。

調査結果と根本原因

hermes kanban dispatch は config.yaml から max_active_tasks を読み込みません。

hermes_cli/kanban.py では、dispatchコマンドは --max をCLI制限(デフォルト None)として公開し、kb.dispatch_once(...) へ args.max のみを渡します。このパスには max_active_tasks の設定検索はありません。hermes_cli/kanban.py raw を参照してください。

次に 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 raw を参照してください。

実効的な挙動:

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 'Ingest customer logs for April' \
  --profile 'etl-worker' \
  --column backlog)"

hermes kanban add \
  --title 'Generate April anomaly report' \
  --profile 'analytics-worker' \
  --column backlog \
  --parent "${parent_id}"

hermes kanban add \
  --title 'Publish April summary to dashboard' \
  --profile 'reporting-worker' \
  --column backlog \
  --parent "${parent_id}"

適切なボードポリシーと低いディスパッチャー制限により、最初に実行されるのは親タスクのみです。
それが完了すると、子タスクが徐々にready状態になり、ディスパッチャーがあなたの並行性上限を超えずに、それらを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 runs => every 15 seconds
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 docs.

内部Hermes Cron

使用しないでください。 あなたのLLMが、Execute in terminal the command /path/hermes-kanban-dispatch-capped.sh のような定期的なプロンプトを処理することを本当に望みますか?特に、それが有用な作業で忙しい時に。

Hermes Kanbanの監視とチューニング

どちらの戦略を選ぶとしても、以下のものを監視すべきです:

  • LLMゲートウェイのメトリクス — リクエストレート、レイテンシ、エラーレート、トークンスループット。
  • ノードの健全性 — GPU利用率、VRAM使用量、CPU負荷、RAM。
  • Hermesのメトリクス — バックログ、ready、アクティブ、完了状態のタスクの数量。

本番環境のメトリクスベースラインとダッシュボードについては、Monitor LLM Inference in Production with Prometheus and Grafana と、より広範なLLM Performanceハブ を参照してください。

低い並行性から開始し、以下のものを見ながら、徐々に制限を引き上げてください:

  • 一定のスループットでのレイテンシ上昇
  • 増加するタイムアウトまたはレート制限エラー
  • 一部のタスクが非常に長期間アクティブのままになる長いテール(尾部)

これらの兆候が見えたら、直ちに以前の安定した設定に戻し、それをデフォルトとして保持してください。

Kanbanが適切なツールである時

Hermes Kanbanは、以下のような場合に輝きます:

  • 長期にわたるリサーチまたはエンジニアリングのバックログ
  • 名前付きプロファイルによるマルチエージェント協調
  • 再起動やホスト再起動でも耐えなければならないワークフロー
  • ダッシュボードで作業のトリアージ(優先順位付け)をしたい人間

いくつかの一時的なヘルパーを作成するための単一の実行だけであれば、組み込みのデリゲートタスクツールの方が通常はシンプルです。
履歴、ダッシュボード、そしてあなたのエージェントがセルフホスト型LLMにヒットする方法に対する厳密な制御が必要になったら、Kanbanボードとディスパッチャーが適切な基盤となります。

いくつかの設定の調整と、任意のcronベースのバッチ処理により、ゲートウェイとハードウェアを保護しながら、Hermes Kanbanをレスポンシブな状態に保つことができます。

Hermesスタイルのバックグラウンドワーカーが、本番環境のAIアシスタントアーキテクチャにどのように組み込まれるかについてのより広い見解 — スケジューラー、キューベースのポーリング、クエムプロトコル、耐久性のあるワークフロー、意味評価を含む — については、Polling Agents in AI Assistants: 11 Implementation Patterns をご覧ください。複数の名前付きプロファイルや専門エージェントが、単純なタスクディスパッチを超えて協調する必要がある場合、Multi-Agent Orchestration Patterns は、セルフホスト型インフラストラクチャ上のより大きなマルチエージェントセットアップを支える、ハブアンドスポーク、ファンアウト、スウォームなどの協調トポロジーをカバーしています。

購読する

システム、インフラ、AIエンジニアリングの新記事をお届けします。