Hermes Agent を読み解く — Kanban 永続タスクボード
連載「Hermes Agent を読み解く」第7回。
連載「Hermes Agent を読み解く」全10回
- 第1回 全体像と読み方
- 第2回 コアの会話ループ
- 第3回 状態管理とコンパクション
- 第4回 記憶アーキテクチャと人格
- 第5回 ツールシステム
- 第6回 マルチエージェント並列
- 第7回 Kanban 永続タスクボード(本記事)
- 第8回 接続層とインタフェース総覧
- [第9回 拡張運用]
- [第10回 セキュリティと安全運用]
はじめに — 揮発する fan-out の限界
前回の delegate_task は強力だが、3 つの弱点がある。同期(親が子を待つ)、揮発(プロセスが落ちれば消える)、人間不在(途中で人に聞けない)。長期にわたる、人間とエージェントが入り混じる、落ちても再開できる協調——これには別の仕組みが要る。それが Kanban 永続タスクボードだ。約 14,000 行(正確には 14,032 行)の大きなサブシステムで、Hermes の中でも独立性が高い。
1. todo / delegate_task との違い
todo |
delegate_task |
Kanban | |
|---|---|---|---|
| 永続性 | セッション内 | 揮発 | 永続(SQLite) |
| 協調 | 単独 | 親 → 子 同期 | ピア協調 |
| 人間介入 | なし | なし | あり(blocked) |
| クラッシュ耐性 | なし | なし | あり(リトライ) |
todo(第5回)はセッション内の備忘、delegate_task(第6回)は同期的な fan-out。Kanban はそのどちらとも違い、落ちても残り、人間も介入でき、複数のワーカーがピアとして協調するボードだ。
2. SQLite データモデルとステータス機械
ボードは SQLite に永続化される。主なテーブルは tasks / task_links(親子依存)/ task_comments(ハンドオフ + swarm blackboard)/ task_events(監査ログ)/ task_runs(試行履歴)/ task_attachments / kanban_notify_subs(gateway 通知購読)。
タスクは状態機械を持つ。VALID_STATUSES は triage / todo / scheduled / ready / running / blocked / review / done / archived。dispatch される本流は todo → ready → running → done で、blocked / scheduled / review が分岐として乗る。
blocked が人間介入の入口だ。ワーカーが判断できない局面で kanban_block を呼ぶと、reason がボードに掲示され、人間(または orchestrator)が kanban_unblock するまで待つ。unblock 後は親依存がすでに終わっていれば ready、まだなら todo に戻る。
3. CAS による claim(ロック無し並行制御)
複数ワーカーが同じボードを突くとき、同じタスクを二重に掴む事故を防ぐ必要がある。Hermes はロックではなく CAS(compare-and-swap) で解く。
-
WAL +
BEGIN IMMEDIATEでトランザクションを開始 - タスクの現在状態を読み、期待値と一致する場合のみ claim を書き込む(compare-and-swap)
- 競合した側は失敗を検知してリトライ
これにより明示的ロックなしで「早い者勝ち」の安全な claim が成立する。タイムアウト系の値は次の 3 つ(kanban_db.py:111,121)。
- claim TTL: 15 分 — claim の有効期限
- heartbeat stale 閾値: 1 時間 — ハートビートが 1 時間途絶すると wedged(行き詰まり)と判定
- crash grace: 30 秒 — クラッシュ検知の猶予
ここは骨子段階で誤りがあった箇所だ。「heartbeat 1 時間」は間隔ではなく stale 閾値——つまり「1 時間ハートビートが来なければ死んだとみなす」しきい値であって、1 時間ごとに鼓動を打つ意味ではない。claim TTL の 15 分とは別物なので書き分けている。
4. decompose → specify → swarm
大きなタスクは 3 段で展開される。
- decompose — 補助 LLM がタスクをサブタスクのグラフに分解
- specify — 各サブタスクの仕様を詰める
- swarm — ワーカー群で並列実行
swarm の構成は root → workers → verifier → synthesizer。root が束ね、workers が手を動かし、verifier が検証し、synthesizer が統合する。ワーカー間の情報共有には blackboard(共有黒板。コード上は [swarm:blackboard] として確認)パターンを使う——各ワーカーが中間結果を黒板に書き、他のワーカーがそれを読む。
delegate_task の「要約だけ親に返す」閉じた fan-out と違い、swarm は黒板を介してワーカー同士が横に情報を流せる。協調の密度が一段高い。
5. dispatcher と worker 起動
ボードに積まれたタスクは、誰が拾って走らせるのか。dispatcher が担う。
- Gateway 内で定期的に tick(巡回)し、ready なタスクを探す
- 見つけると
hermes -p <profile>でワーカーをサブプロセス起動する - ワーカーには
HERMES_KANBAN_TASK/HERMES_KANBAN_BOARD/HERMES_KANBAN_DB/HERMES_KANBAN_WORKSPACES_ROOTなどが環境変数で注入される - ワーカーは
HERMES_KANBAN_TASKの有無で Kanban ツール群(第5回の 9 ツール)を有効化する
タスク指定が CLI フラグ(--tasks <id> のような形)で渡されるのか、環境変数だけなのかは、手元コードでは環境変数経由(HERMES_KANBAN_TASK)が確実に確認できた範囲。ここでは env 注入として記述する。
第5回で「HERMES_KANBAN_TASK 設定時のみ Kanban ツールが有効」と書いたのは、この起動経路と対応している。dispatcher が env を注入してワーカーを立てる → ワーカーは env を見て Kanban モードに入る、という流れだ。
次回は視点を外に向ける。これら全機能を「どの面から触れるか」——Gateway を中心とした接続層とインタフェース総覧。
対応マップ章: §16 / 行番号は hermes update でずれうる
クイックイタレート株式会社
IoT / 電力監視 / AI / 衛星・無線通信 / システムインテグレーション/
ローカル LLM・エージェント基盤に関するお問い合わせはお気軽にどうぞ。