Hermes Kanban の境界 API と worker protocol を外部エージェントに教えるための記事
この記事はなにか
これは 人間向けの CLI 解説記事ではない。
Hermes Agent のタスクボード (Kanban) を、Claude Code / Codex / ローカル LLM bot などの外部エージェントに「正しくしゃべらせる」ための仕様メモとして書いている。
読者として想定しているのは、エージェントを Hermes のワーカーとして組み込みたいエンジニア — 具体的には、ブリッジスクリプトを書く人と、エージェントに渡すシステムプロンプトや SKILL.md を書く人。両者が一次資料として横に置ける形を目指している。
シリーズ位置としては、次回記事「サブスク Claude Code を Hermes のワーカーとして動かす工夫」の 前提記事 にあたる。Kanban の「境界 API」としての性質をここで先に固め、次の記事で具体的な運用設計に入る。
結論先出し
エージェントに教えるべき要点は 4 つに整理できる。
-
Kanban DB を直接書いてはいけない。
何の経路で触るにしても、必ず公式 surface 経由で。 -
誰が何の surface を使うかが分かれている。
Hermes 内の worker model はkanban_*tool call、外部 bridge / 人間 / cron はhermes kanbanCLI。同じ DB layer に到達するが、入口が違う。 -
状態モデルとライフサイクルを覚える。
エージェントは「自分が今どの状態にあり、何を呼べば次へ進むか」を理解している必要がある。 -
最小プロトコルだけ覚えさせる。
dispatcher 起動型と pull 型 external bridge で前段が違う以外、本体の流れは同じ。
読む → 動く →heartbeat→completeまたはblock。
以下、この 4 点を順に開く。
アクターと surface の整理
Kanban を触る主体は少なくとも 4 種類いて、それぞれ使う surface が違う。
| 主体 | 使う surface |
|---|---|
| 人間オペレータ |
hermes kanban ... CLI / /kanban ... slash command / dashboard |
| cron / script / 外部 bridge |
hermes kanban ... CLI |
| Hermes dispatcher-spawned worker (LLM 本体) |
kanban_show, kanban_complete, kanban_block, kanban_heartbeat などの tool call
|
| Orchestrator profile |
kanban_create, kanban_list, kanban_link, kanban_unblock を含む拡張 toolset |
ここを混ぜると事故る。特に注意すべきは、
-
Hermes 内の worker は CLI を shell out しない。
worker model はkanban_*toolset を呼ぶ。
CLI と toolset はどちらも同じ kanban_db layer に到達するので、状態遷移・イベントログ・依存タスクの自動昇格などの整合性が保たれる。 -
外部 bridge (Claude Code, Codex, ローカル LLM bot を Hermes に繋ぐ薄い層) は CLI を使う。
これは bridge 自体が「人間相当の外部スクリプト」だから。
つまり本稿で扱う「エージェントに教える」は、正確には 2 つのターゲットがある。
-
(a) 外部 bridge = CLI を叩くスクリプト + LLM。
bridge の責務としてlist/watch/claimが必要。 -
(b) Hermes 内 worker LLM =
kanban_*tool call で動く。
CLI は呼ばない。
両方に共通するのは、
Kanban DB を直接書かないこと、
状態モデルを理解していること、
最小プロトコルを守ること。
なぜ DB を直接書いてはいけないか
CLI でも kanban_* tool でも、どちらの surface も同じ kanban_db layer に乗っている。
この layer をスキップして SQLite を直接書くと、最低でも次の 3 つが壊れる。
-
claimの atomicity:
「readyで誰もlockしていないタスクだけを、自分の lock 付きで取る」という排他操作を 1 トランザクションで処理する。手書き SQL でこの保証を再現するのは面倒で、書き間違えると 2 つの worker が同じタスクを握る race が起きる。 -
イベントログの整合性:
状態遷移ごとに events テーブルに行を足すのが規約。
surface を通せば自動で書かれるが、生 SQL でtasks.statusだけ書き換えるとログが無音になり、tail/watchでの進捗追跡が不能になる。 - 依存タスクの自動昇格:
- 親タスクが
doneになったときに子をtodo → readyに上げる処理は、surface 経由でしか発火しない。link/unlinkで組んだ DAG が機能しなくなる。
要するに、公式 surface (CLI または kanban_* tools) が「セマンティクスを保証する API」 であり、SQLite ファイルそのものは内部実装の都合にすぎない。
1 枚絵
人間 / cron / script / 外部 bridge Hermes 内 worker model
│ │
▼ ▼
hermes kanban ... CLI kanban_* tool call
│ │
└────────────────┬────────────────────────┘
▼
kanban_db layer
(atomicity / events / dependency promotion)
│
▼
SQLite (board ごとに分離された DB / workspace / dispatcher scope)
入口は 2 つあるが、整合性を維持する層は 1 つ。
これが、Kanban を「ゲートウェイ間の境界に置ける」性質の正体になっている。
ボードは per-board に分離されている
旧来「単一の kanban.db にすべてのタスクが入る」とイメージされがちだが、
現行では SQLite DB / workspace / dispatcher scope がボード単位で分離されている。
default ボードは旧来の場所、追加ボードはそれぞれ独立した領域を持つ。
gateway-embedded dispatcher は tick ごとに各ボードを sweep する (ボードごとに別プロセスや別スレッドが立つわけではない)。
bridge / scripting 側で押さえておくべきこと:
- スクリプトでは必ず
--board <slug>を明示する (switchのグローバル current は別シェル間で事故る) - CLI の board 解決順序は
--board→HERMES_KANBAN_BOARD環境変数 → current file → default - ボードをまたいで状態を集計したい場面では、各ボードに対して個別にクエリする必要がある
ボードの切り方の目安:
-
プロジェクト単位:
qi-portal,support-chat -
ドメイン単位:
bidding-cases,hr-tickets -
ゲートウェイ間の境界:
cross-org-decisions,client-handoff -
一時ワークフロー:
2026q2-audit-prep
個人ノートを Kanban に書くのは設計ミス。
それは Vault と Memory の仕事で、Kanban に書いた瞬間に他ゲートウェイから可視になる。
状態モデル
タスクは次の状態を取る (v0.14.0 時点)。
triage ──specify/decompose──> todo ──deps done──> ready ──claim──> running ──complete──> done
↑ ↑ │
│ │ ├── block ────> blocked ──┐
│ │ │ │
│ │ └── schedule ─> scheduled ─┤
│ │ │
└────────────────────┴────────── unblock ─────────────────────────┘
ポイント:
- 本流は
triage → todo → ready → running → done。 -
blockedとscheduledは本流の中継点ではなく、ready/runningから脇に park される side state。 -
unblockは単一コマンドだが、戻り先は 2 系統に分岐する。
タスクの依存が 解決済みならreadyに、未解決ならtodoに 戻る (図中のunblock線は両方をまとめて描いている)。 -
archivedは表示制御。
各状態の意味を agent 視点で整理する。
| 状態 | agent から見た意味 |
|---|---|
triage |
まだ仕様化されていない。agent が触る対象ではない。specify または decompose で次状態に上がる。 |
todo |
仕様は決まったが依存未解決。まだ claim できない。
|
ready |
依存解決済み、claim 可能。 dispatcher が拾うか、外部 bridge が取りに来る。 |
running |
誰かが claim 中。他 agent は触らない。
|
done |
正常終了。summary (人間向け handoff) と metadata (機械向け handoff) が次工程の情報源。 |
blocked |
人間 / 他 bot の判断待ち。dispatcher は自動再開しない。 |
scheduled |
時間トリガー待ち。schedule で park、時刻到来 or unblock で本流に戻る。 |
エージェントが特に押さえるべきは,、
-
readyでなければclaimできない。
todoに対してclaimを試みても失敗する。 -
running中のclaimには TTL がある。
TTL 内にheartbeat/comment/complete/blockのどれかを送らないと、最終的に他 worker に取り直される。TTL の値も、heartbeat不在時のstale判定の閾値も、いずれも build / config に依存する。外部 bridge はclaim --ttl <seconds>で TTL を policy として明示し、それより十分短い間隔で heartbeat を打つ設計にする。 -
silent return は禁止。
worker がcomplete/blockを呼ばずに正常終了した場合、現行実装ではprotocol_violation扱いになり、auto-block/gave_upでタスクが閉じられる。
詰まった場合も進めた場合も、必ずblockかcompleteでタスクを閉じる。
最小プロトコル
エージェントが暗記するのはこれだけ。前段が違う以外は共通。
CLI と toolset の引数の差: CLI コマンドは外部から叩くので
<task_id>を必ず受け取る。一方、Hermes 内 worker のkanban_*toolset は task-scoped で、worker は自分が動かしているタスクを既知の対象として扱う。原則として task_id を渡さず、body / summary / note 等の中身だけを引数に取る。
共通プロトコル (Hermes 内 worker / 外部 bridge どちらも)
1. 読む
| surface | コマンド |
|---|---|
| CLI (外部 bridge / 人間 / script) |
hermes kanban show <task_id> / hermes kanban context <task_id>
|
| toolset (Hermes 内 worker) | kanban_show() |
CLI 側で show はタスク本体 + コメント + イベント履歴、context は「worker がこれから動くために必要な情報の塊」を 外部から確認する ための surface。
Hermes 内 worker では、kanban_show() の返り値に task body / comments / parent handoffs / prior attempts / worker_context がまとめて入る。
別途 kanban_context() を呼ぶ前提にしない — toolset 側に対応する tool は存在せず、
CLI の context は外部の人間 / bridge が worker の見え方を覗くための診断用と理解する。
2. 長時間ジョブで heartbeat
| surface | コマンド |
|---|---|
| CLI | hermes kanban heartbeat <task_id> --note "step 2 of 4" |
| toolset | kanban_heartbeat(note="step 2 of 4") |
長い作業では節目ごとに heartbeat を打つ。打たないと、heartbeat 不在の stale 判定を経て他 worker に取り直される (stale 判定の閾値は build / config に依存する。手元 build では kanban.dispatch_stale_timeout_seconds に対応する設定が確認できたが、設定名や既定値はバージョン間で変わり得るため、bridge はこれに依存しない設計が望ましい)。
bridge では claim --ttl 900 のように自分で TTL を明示し、TTL より十分短い間隔 (目安として数分ごと) で heartbeat を打つ policy が安全。公式 docs でも、長時間 operation では kanban_heartbeat(note="...") を定期的に打つ worker protocol として説明されている。
3. 観測事実を comment で残す
| surface | コマンド |
|---|---|
| CLI | hermes kanban comment <task_id> --author claude-code-bridge "本文" |
| toolset | kanban_comment(body="本文") |
ここに書くのは 観測事実・検証結果・未解決事項・handoff に必要な情報。
chain-of-thought 的な内部思考の逐語ログではなく、次の読者が再現・判断できる事実を書く。CLI の --author は呼び出し主体の識別子 (bridge 名など)。toolset 側は profile が自動的に author になる。
4. 正常終了
CLI:
hermes kanban complete <task_id> \
--summary "Implemented API endpoint and added integration test." \
--metadata '{"changed_files":["src/api/foo.ts","test/api/foo.test.ts"]}'
toolset: kanban_complete(summary="...", metadata={...})
-
summaryは人間向け handoff。実装の中身ではなく「次に必要な情報」を書く。 -
metadataは機械向け handoff。downstream の自動化スクリプトや子タスクが消費する free-form JSON。
5. 詰まったら block
CLI:
hermes kanban block <task_id> "cause: spec undecided
what happened: 仕様書のセクション 3.2 で A 案と B 案が併記されたまま。実装側が判断する根拠が無い。
options: A / B / C
recommendation: A (既存システムとの互換性で優位)
next action needed: human decision on which option to implement"
toolset: kanban_block(reason="cause: ...")
block の本文は必ず以下のテンプレに従う:
cause: <human decision needed | test failure | environment | auth missing | spec undecided>
what happened: <事実関係を 1 段落で>
options: <A, B, C — 具体的な選択肢>
recommendation: <どれを推すか、その理由>
next action needed: <解除する側がやるべき具体的アクション>
このテンプレが守られていれば、解除する側 (人間または別 bot) は一度のリードで全情報を受け取れる。「うまくいきませんでした」だけ書かれた block は最悪で、人間が往復で問い詰めることになる。
外部 bridge のみが前段で叩く
Hermes 内 dispatcher が spawn した worker は、起動時に自分のタスク ID が注入された状態 (HERMES_KANBAN_TASK 環境変数) で動き出すので、自分で claim しに行く必要はない。
一方、外部 bridge は自力でタスクを取りに行く必要がある。
0a. 自分宛のタスクを探す
hermes kanban list --board <slug> --assignee claude-code-bridge --status ready --json
# あるいは stream 監視:
hermes kanban watch --assignee claude-code-bridge --interval 5
# → stdout に JSON Lines 形式で event を吐き続ける。SIGINT で抜ける。
0b. claim
hermes kanban claim <task_id> --ttl 900
# 成功すると workspace path が stdout に返る
TTL は本稿の bridge policy として 900 秒に明示している (build / config の既定値に依存しない)。claim 成功後はそこに cd してから、上の共通プロトコル (1〜5) に入る。
破ってはいけないルール
スタイル選好ではなく、破ると state が壊れるか、ボード全体が機能不全になる:
-
Kanban DB ファイルに生 SQL で UPDATE/INSERT/DELETE しない。 公式 surface (CLI または
kanban_*tools) 以外で書き込まない。 -
詰まったときも進めたときも、必ず
blockまたはcompleteでタスクを閉じる。 silent return は現行実装ではprotocol_violationとしてauto-blockされる。 -
CLI が non-zero exit した時の扱いは、claim 前と claim 後で分ける。
-
claim 前 (
list/watch/claimの失敗): race・一時的な board 状態変化・通信問題で起こり得る。bridge は短い backoff の後、rescan して別タスクを取りに行くか、同じタスクを後で再試行する。block は打たない (claim 前なので block する相手がいない)。 -
claim 後 (
show/context/heartbeat/comment/completeなどの失敗): 短い再確認の後、解決不能ならblockで人間に渡す。 -
complete/block自体が失敗 した場合は、Kanban 上で状況を伝えられないので、別チャネル (Slack / Discord / メール / ログ aggregator) にアラートを出す。bridge 側でこの fallback channel を持っておく。
-
claim 前 (
- 認証情報 / 秘密鍵 / 別ゲートウェイの vault 内容を body / comment / metadata に書かない。 surface は redact しない。
-
cron / スクリプトから
createするときは必ず--idempotency-keyを付ける。 transient な失敗で重複タスクが生まれる。決定的な要素から生成するのがコツ — 例:--idempotency-key "$(echo -n "${board}:${title}:$(date +%Y-%m-%d)" | sha256sum | cut -c1-16)"のように、「ボード + 役割 + 実行日」程度のキーから ID を作る。 - claim TTL 内に必ず何か送る (heartbeat / comment / complete / block のどれか)。
実装 worker / 外部 bridge が「触ってはいけない」CLI コマンド
以下は人間オペレータのためのコマンドで、通常の実装 worker や外部 bridge には教えない方がよい (orchestrator profile の役割は別。第 3 節「アクターと surface の整理」を参照):
-
init,boards create/rm/rename— ボードのライフサイクル管理 -
dispatch(手動 tick),daemon— dispatcher 操作 (※daemonは将来 deprecate 予定。移行先は公式 docs を参照) -
gc,diagnostics— 運用メンテ -
archive— 完了済みの整理 -
assign,reassign,reclaim— 担当変更 / 救出系
理由はシンプルで、エージェントが状況判断でこれらを叩くと ボード全体の整合性を agent 都合で壊す リスクがある。詰まったら block で人間に渡す、というモデルを守らせるほうが結果的に安全に回る。
v0.14.0 で追加された新機能
Hermes v0.14.0 (build 2026.5.16) で以下が追加された。
-
新ステータス
scheduled:
時間トリガー待ちの side state (前述の状態モデル参照)。 -
schedule <id>コマンド:
タスクをscheduledに park する。time-delay / follow-up work 用。 -
decomposeコマンド:
triage column のタスクを子タスク graph に fan out する。kanban.auto_decompose: trueのとき dispatcher tick ごとに自動実行されるオプションもある。
本稿の立場としては、これらは 当面エージェントには教えない。
-
scheduleはオペレーション層 (いつ実行するか) の意思決定で、agent が自律判断で park すべき対象ではない。 -
decomposeは粒度設計責任を agent に持たせることになる。仕様と運用上の振る舞いが安定するまでは、分解は人間オペレータ or 上位 orchestrator の責務にしておく方が安全。
手元の build では
swarmというコマンドも観測されているが、現時点の公式 docs では未確認のため本稿のスコープ外とする。
参考: DB スキーマと read-only アクセス (人間向け)
この節は 人間のオペレータ・bridge スクリプトの実装者向け。エージェントには教えない。実装の中を知っておくと「なぜ surface 経由が必須なのか」が腑に落ちるが、エージェントに DB の存在を意識させると surface を迂回する誘惑が生まれる。
テーブル構成
v0.14.0 時点で、各ボードの SQLite には 6 つのテーブルが入っている。
| テーブル | 用途 |
|---|---|
tasks |
タスク本体 (30 カラム) |
task_links |
親子依存 (parent_id, child_id) |
task_comments |
コメント |
task_events |
状態遷移イベントログ |
task_runs |
実行履歴 (1 claim = 1 row) |
kanban_notify_subs |
通知 subscriber 管理 (v0.14.0 で追加) |
tasks テーブルの主要カラム
論理的にグルーピングするとこうなる。
-- 識別 / 基本属性
id, title, body, assignee, status, priority
-- ライフサイクル
created_by, created_at, started_at, completed_at
-- workspace
workspace_kind (scratch | worktree | dir), workspace_path
-- claim 状態 (排他制御)
claim_lock, claim_expires, worker_pid, last_heartbeat_at
-- namespace と冪等性
tenant, idempotency_key
-- 結果と handoff
result
-- 再試行制御 (circuit breaker)
consecutive_failures, last_failure_error, max_retries, max_runtime_seconds
-- run 紐付け
current_run_id -- → task_runs.id
-- workflow (forward-compat)
workflow_template_id, current_step_key
-- skill 自動ロード
skills -- JSON 配列
-- v0.14.0 で追加 ↓
session_id -- bot session との紐付け (どのチャットから作られたか)
branch_name -- git branch 別作業 (worktree 系の追跡性改善)
model_override -- per-task で使う LLM を切り替え可能
status カラムが取り得る値は triage | todo | scheduled | ready | running | blocked | done | archived の 8 種。前述の状態モデルと一対一に対応している。
tenant(マルチテナント運用),workflow_template_id/current_step_key(workflow テンプレート系) は本稿のスコープ外。実運用での使い分けは別記事で扱う予定。
task_runs テーブルの主要カラム
tasks 1 行に対して、claim されるたびに task_runs に 1 行が積まれる (再 claim や TTL 切れの reclaim も含めて履歴が残る)。
| カラム | 用途 |
|---|---|
id |
run の識別子 (tasks.current_run_id から参照される) |
task_id |
どのタスクの run か |
started_at, ended_at
|
run の開始 / 終了時刻 |
worker_pid, worker_profile
|
この run を回した worker の識別 |
outcome |
終了種別 (下記の enum を参照) |
error |
エラーメッセージ (失敗時) |
outcome で観測される代表的な値
| 値 | 意味 |
|---|---|
completed |
正常に complete した |
failed |
実行中にエラーで終了 |
reclaimed |
TTL 切れで他 worker に取り直された |
timed_out |
max_runtime_seconds を超過 |
gave_up |
worker が complete / block を呼ばずに終了 (= protocol_violation)。前述の auto-block の原因 |
(完全な enum は手元の task_runs の制約定義を参照。バージョンで増減し得るので、コード側で switch するなら未知値を unknown でフォールバックする方が安全。)
kanban_notify_subs (v0.14.0 新規)
| カラム | 用途 |
|---|---|
task_id |
通知対象のタスク |
platform |
通知先 (discord, teams など) |
chat_id, thread_id, user_id
|
通知先の identifier |
notifier_profile |
通知を行う Hermes profile |
created_at |
subscribe した時刻 |
last_event_id |
最後に通知済みの event id (重複通知防止) |
「特定タスクの進捗を Discord / Teams 等に通知する subscriber」を管理する。人間が「このタスクが終わったら教えて」を設定する用途。
ボードごとに DB は別、スキーマは同一
各ボードは独立した SQLite ファイルを持つが、スキーマは全ボードで同一。.schema の出力を比較しても diff は出ない。
読み取り専用で覗くショートカット
bridge スクリプトの分析用途では、CLI の --json 出力で足りないケースに限って、読み取り専用で SQL を直接当てるのは OK。書き込みは禁止 (後述)。
# 対話で開くときは -readonly フラグ
sqlite3 -readonly <board-db-path>
# 1 行クエリは URI mode で read-only を強制
# running task の生存確認 (heartbeat が古い worker を炙り出す)
sqlite3 "file:<board-db-path>?mode=ro" \
"SELECT id, title, assignee, last_heartbeat_at
FROM tasks WHERE status='running';"
# 直近の失敗履歴
sqlite3 "file:<board-db-path>?mode=ro" \
"SELECT task_id, outcome, error FROM task_runs
WHERE outcome NOT IN ('completed', 'reclaimed')
ORDER BY started_at DESC LIMIT 20;"
なぜ書き込みは禁止か (スキーマで再確認)
スキーマを見ると、たとえば status の遷移ひとつとっても、整合性のために連動して更新すべきカラムが多いのが分かる。
-
tasks.statusだけ書き換えるとtask_eventsに痕跡が残らず、tail/watch/ dashboard の表示と不整合になる - claim を生 SQL で取ろうとすると、
claim_lock/claim_expires/started_at/worker_pid/current_run_idを atomic に書く必要があり、かつtask_runsに新 row を足す必要がある (これを 1 トランザクションで書けないと race る) - 完了の生 SQL は
consecutive_failuresのリセットや dependency promotion の発火を逃す
公式 surface (CLI / kanban_* tools) はこれら全部を 1 操作の裏側で面倒見ている。読み取りオンリーの分析用途に限ってだけ、生 SQL を許す、というのが現実的な落とし所になる。
「実装こそ約束」原則の Kanban 版
ここで一段引いて、なぜ Kanban が「お願いだから SQL 書かないで」ではなく、
「書いても整合性が壊れる構造」 になっているかを言語化しておく。
エージェントを業務に組み込む時の原則は、「規律を文書ではなく実装で強制する」だ。エージェントは説明書を律儀に読むとは限らないし、システムプロンプトに「SQL を書くな」と書いても、状況によっては書く。だから書けない構造にする。
- 公式 surface (CLI または
kanban_*tools) が atomicity / event logging / dependency promotion を一括で面倒見る - 公式 surface を経由しない書き込みは整合性を壊す
- → エージェントは「公式 surface を叩く」以外に選択肢がない
この性質によって、Kanban は ゲートウェイの内側ではなく、ゲートウェイ間の境界に置ける。複数の Hermes プロファイル (たとえば全社用と入札専用) が同じボードを共有しても、それぞれが自分の vault / memory で動きながら、タスクという最小限の単位だけを安全に受け渡せる。
これが次の記事「サブスク Claude Code を Hermes のワーカーとして動かす工夫」の前提になる。Claude Code を Hermes のボードに参加させるとは、
Claude Code を境界 API の話者にする
ということだ。
まとめ
— SKILL.md / システムプロンプトに貼れる cheat sheet
# Hermes Kanban - Agent Protocol Cheat Sheet
- Kanban は durable task board。DB を直接書いてはいけない。
- 人間 / script / 外部 bridge は `hermes kanban` CLI を使う。
- Hermes 内 worker model は `kanban_*` tool call を使う (task-scoped、原則 task_id を渡さない)。
- 両方とも同じ kanban_db layer に到達するので整合性が保たれる。
- 状態モデル: triage → todo → ready → running → done。
blocked と scheduled は ready/running から脇に park される side state。
- ready でなければ claim できない。
- scheduled / blocked のタスクは通常 worker の領域ではない。
解除は人間 or orchestrator の責務。
- 最小プロトコル: read → work → heartbeat → complete or block。
- CLI で読む: show <task_id> + context <task_id>
- tools で読む: kanban_show() ※ context 相当はこの返り値に含まれる
- heartbeat: heartbeat <task_id> / kanban_heartbeat(note="...")
- comment: 観測事実・検証結果・handoff に必要な事実を書く (内部思考は書かない)
comment <task_id> --author ... / kanban_comment(body="...")
- complete: summary = 人間向け、metadata = 機械向け
complete <task_id> --summary ... --metadata ...
kanban_complete(summary="...", metadata={...})
- block: cause/what/options/recommendation/next-action テンプレ必須
block <task_id> "..." / kanban_block(reason="...")
- 外部 bridge は前段で list/watch → claim が必要。
- Hermes 内 worker は HERMES_KANBAN_TASK が注入されるので自分で claim しない。
- silent return 禁止。必ず complete または block で閉じる。
- CLI non-zero exit は claim 前 / claim 後で扱いを分ける。
- claim 前 (list/watch/claim): backoff + rescan。block は打たない。
- claim 後 (show/heartbeat/comment/...): 短く再確認し、解決不能なら block。
- complete/block 自体が失敗: Kanban 外の fallback channel に alert。
- secrets / vault 内容 / token / raw PII を body/comment/metadata に書かない。
- cron/script から create するときは --idempotency-key 必須。
- board は per-board に分離。script では --board を明示。
次回予告
次の記事では、本稿の仕様を踏まえて サブスクの Claude Code を Hermes Kanban の外部 worker として実際に動かすときの運用設計 を扱う。
具体的には、
- bridge スクリプトの設計 (list/watch ループ、claim の取り方、TTL の扱い、workspace のマウント)
- skill / システムプロンプトに何を書いて何を書かないか
- Claude Code に「block を打つ」という習慣を仕込む工夫
- サブスク (= 1 ライセンス) の Claude Code を複数タスクに並行で当てるかどうかの判断
を書く予定。
本稿は Hermes Agent v0.14.0 (build 2026.5.16) 時点の挙動に基づく。新コマンド
schedule/decomposeおよび手元 build で観測されるswarmの詳細仕様 (特にdecomposeの auto-decompose 挙動と orchestrator 経由での使い方) は別記事で改めて整理する予定。
本記事は、筆者が所属するクイックイタレート株式会社で社内エージェント環境を構築した際の整理メモをもとにしています。
関連する公開事例は 事例紹介 をご覧ください。
LLM(Local/フロンティアモデル) × エージェントツール × 社内システム連携の
設計・構築・運用のご相談も承っております。