kage 影 · 設計レポート · 2026-06-24

Quest ライフサイクル

cron の”決まった時間に決まったタスク”を超えて、流動的・セレンディピティがある組織的な AI 探索を 24 時間 自律稼働させるための第2のライフサイクル。マインドマップ状のタスクグラフ、POC 撤退/育成、そして暴走防止の予算。

event-driven · 1 cron tick → 1 node team roles · scout / poc / strategist graph · nodes + edges runaway guard · max_agent_runs OS-native · no daemon

01背景と課題

現在の kage は cron ベースのみ。1タスク=1プロンプトを決まった時刻に起動し、Memory で線形に状態を保つ。人間のリアルな仕事――"ぼんやりした方向"から 0 で現状を調べ、PoC を回し、ROI で撤退/拡大を繰り返す――とは質が違う。

cron ライフサイクル

・固定スケジュール/線形 checklist

・1エージェント・1プロンプト

・"小さく決まったことを回す"用途

quest ライフサイクル new

・方向性だけ与えて継続探索

・ロール毎のチーム即時編成

・グラフ探索 + 撤退/育成のループ

02全体アーキテクチャ

OS ネイティブ (既存) quest (今回追加) 共通の executor / runs

cron と quest は同じ kage cron run 1分 tick に乗り、新しく常駐プロセスは立たない。quest のノード実行は既存の executor.execute_task を再利用するため、run 履歴 / log / metadata が cron と同一。

034つのロール = 総合力チーム (v2)

owner 👑 (NEW)

唯一のグラフ編集者。証拠が揃わない限り動かない。promote / abort / spawn / finish

scout 🧭

現状リサーチ。仮説を提案のみ。直接子 spawn はしない。proposed 留め

poc 🧪

最小検証。verdict は提案。owner 判断待ち。proposed 留め

strategist ♟

ROI 提案。判断は owner。proposed 留め

v2 では ロールは Quest 作成時に宣言。デフォルト (team モード) scout,poc,strategist,owner。各ロールは provider + プロンプト雛形を持ち、実行時に具体化。--solo でv1動作(scout/pocが直接spawn)に戻る。--provider claude 等でチーム単位の AI 指定も可。

04マインドマップ = タスクグラフ

直線的なチェックリストではなく、親から子へ枝分かれし、死んだ枝は aborted、有望な枝は grew_to で延伸。SQLite の 3 テーブルで永続化。

探索済/成長中 (explored/growing) 撤退 (aborted · dead PoC) 実行中 (running) 保留 (pending)

ノードのライフサイクル

# pending → run → {explored | growing | aborted}
pending  → running → explored   # 結論のみ・分岐なし
pending  → running → growing    # promising → 子 poc を展開
pending  → running → aborted   # dead → strategist を spawn

051 分 tick の中身

アクティブな quest ごとに 最大1ノード を dispatch。実行は同期待ちで execute_task に乗せ、完了後に verdict JSON を parse して子ノード/エッジを生成。agent_runs を +1。

AI との出力契約 (Output contract)

```json
{ "verdict": "promising (有望)" | "dead (撤退)",
  "evidence": "<要約>",
  "new_directions": ["<次に試す仮説>", ...] }
```

06暴走防止 — 終了条件

条件既定状態
max_agent_runs50超過で terminated今回実装
max_wall_minutes—開始からの経過時間上限将来 (列は用意済み)
max_token_budget—概算 token / 呼び出し回数将来
人間ゲート—深度/転換時に connector 経由で承認将来
kage quest stop <id>—手動停止 (tick は skip)今回
kage quest abort-node <id>—単一ノード強制 abort今回

07データモデル

quests

id, project_path, name, direction,
status (active|done|terminated|stopped),
max_agent_runs, agent_runs,
roles_json, provider, created_at, updated_at

quest_nodes

id, quest_id, parent_id, role,
hypothesis,
status (pending|running|explored|
       aborted|growing),
verdict, evidence, run_id,
created_at, updated_at

quest_edges

id, quest_id, from_node, to_node,
relation (spawned|aborted_to|grew_to), created_at

08CLI

kage quest new <name> --direction "..." \
            [--roles scout,poc,strategist] [--max-agent-runs 50] \
            [--provider claude] [--project <path>]
kage quest list        # id / 名前 / 状態 / runs / ノード数
kage quest show <id>   # ノード + エッジ表で表示
kage quest stop <id>
kage quest resume <id>
kage quest abort-node <node_id>

quest 実行は既存の kage runs / kage logs にもそのまま載る。task 名は quest:<quest_id>:<node_id>。

09ざっくり使ってみる

kage quest new ocr-hunt \
  --direction "日本語請求書PDF向けの無料OCRで最大精度を探す" \
  --max-agent-runs 80 --provider claude
# あとは寝る。1分ごとに scout→poc→... が回り、
# 朝には死んだ枝が abort され、有望枝が grow した状態で記録される。
kage quest list
kage quest show <id>     # グラフ+検証結果を一覧
kage runs                 # quest の各ノードもここに並ぶ

15v3.2 設計: Team と工程 (planner→executer→accepter)

ユーザー指摘: scout/poc は「ロール」よりTeamという上位概念で持て。Team 内で planner → executer → accepter (受け入れテスター) の工程を回し、accepter が ng なら工程へ差し戻し。accept されたら初めて owner へ返せ。

階層構造

Team は1ノード、各工程は子ノード。Teamは編成単位、工程は社内 pipeline。owner は Team に dispatch し、Team は accept されたとき初めて owner に verdict を返す。

工程ごとの役割

工程 (stage)役割出力
plannerhypothesis を具体タスクに分解・計画implements_plan
executer計画に沿って実行・証拠生成evidence
accepter受け入れテスト (looper 互換 judge){verdict:"accept\|reject", revision_target:"planner\|executer"}

差し戻しループ

planner ─▶ executer ─▶ accepter
   ↑                         │
   └── # reject (revision_target=planner)
        ↑
        └── executer だけ差し戻し (revision_target=executer) も可

accept ─▶ Team 完了 verdict ─▶ owner へ
reject は max_revisions で暴走防止
cap 超過 ─▶ Team team_blocked ─▶ owner に fail verdict → 再判断

accepter は looper の judge と同じ。reviewer は notes のみ。reviewer-only は clean 宣言できない (looper gate rule 互換)。

Team ごとの accept 基準

Teamaccepter が使う検証型revision_target 判断
scoutjudge (検索カバレッジ + 仮説未解明)planner (計画ミス) / executer (実行ミス)
pocprogrammatic (exit_zero/指標しきい値) + judgeplanner (コスト設計ミス) / executer (実装ミス)
strategistjudge (ROI rubric)planner (評価軸ミス) / executer (集約ミス)

verdict flow

Team (pending) ← owner.dispatch (stages_into)
planner (proposed→running→explored) ─makes_plan→ executer
executer (proposed→running→explored) ─executes→ accepter
accepter (running) ─ judge
  ├─ accept ─▶ Team (explored) ─▶ owner へ verdict 返却
  └─ reject ─▶ revision_target (revising) ─▶ planner/executer 差し戻し
                max_revisions 超過 → team_blocked → owner に fail

schema 予約

quest_nodes.team_kind: scout|poc|strategist|custom
quest_nodes.stage: plan|exec|accept|revising
quest_nodes.revision_count, max_revisions
quest_edges.relation: stages_into, makes_plan, executes,
                       rejects_to, accepts_to

4モード階層 (互換性)

デメリット (追加分)

14v3.1 設計: looper から学んだ role 設計

参考: ksimback/looper · @0xCodez loop engineering · @shannholmberg looper

looper は「設計 → 実行」の2層 + council (reviewer/judge) + programmatic検証 で「same model grading its own homework」を排除する。kage v2 の owner 単独はまさにその blind spot で、v3 は区別を取り込む。

reviewer vs judge (council_member を置き換え)

Role出力verdict_source用途
reviewer{"notes":[...], "dissent":"..."}❌ なれないブレスト / 視点追加
judge{"verdict":"pass|revise", "blocking_issues":[...], "confidence":0.82}⭕ なれるgate を block する判定
owner (chair)actions[] (merge 後)—議長として merge のみ

--council "reviewer:2,judge:1" 形式で構成。reviewer-only gate は fixed_passes のみ。clean 宣言は禁止。

3つの検証 type (looper 互換)

programmatic: # 無料・deterministic
  check: ["pytest", "tests/test_quest.py"], expect: exit_zero
judge: # rubric + 構造化 verdict
  rubric: "少なくとも2つの独立 evidence が同方向"
human: # kage connector 経由で consent
  prompt: "Discord で 📌 で同意"

明示 gate (scout/poc/synthesis)

scout_gate

scout evidence 蓄積後、poc前にreviewer/judgeがquality check

poc_gate

各poc完了後、成長/撤退判定前にjudgeがverdict

synthesis_gate

戦略総括前にreviewer/judgeがROI視点

loop_control 拡張 (暴走防止)

max_iterations: 50          # = max_agent_runs 後方互換
budget:
  tokens: 2_000_000
  wall_clock_min: 1440       # 24h (既存 max_wall_minutes 列に統合)
no_progress:
  max_stalled_iterations: 3
  signals: ["同じ issue が繰り返し", "evidence 3ラウンド不変"]
  action: stop
human_checkpoints: [scout_gate]   # connector 経由

v2 の max_agent_runs だけでは「動いている間に実質進んでいない」堂々巡りを検知できない。no_progress が looper 由来でその穴を埋める。

cross-model council (privacy)

host(owner):  claude     # kage quest.provider
reviewer-A:   gemini     # 別 family 推奨 (blind spot)
judge-B:      codex      # gate 判定
# privacy.egress: 別 vendor CLI 送信を明示 + consent + redact glob

council_members は quest 単位の provider とは個別に provider を持てる。

状態機械 (v3.1)

work(scout/poc) 完了
  ↓ owner (pending) — _should_dispatch_owner() gate
  ↓ design: gate spawn (scout_gate / poc_gate / ...)
gate (pending)
  ↓ spawn N× reviewer/judge (relation: council_of)
member (proposed→running→explored)
  ↓ verdict / notes
gate (running) — chair merge
  ↓ verdict_source "pass" → 次フェーズ work を pending 化
  ↓ verdict_source "revise" → 前フェーズ work を保持し revision spawn
gate (explored)
  ↓ run: owner が merged actions[] → tick 適用
owner (explored)

3モード階層 (互換性)

今回は intent + 本レポートに設計のみ。executor 並列化と connector consent 拡張後に着手。programmatic check / loop_control 拡張は非同期化なしでも実装可能。

13v3 設計: design + run 2-phase で owner SPOF 解消

v2 では owner 1出力が曲がればグラフ全体が曲がる SPOF だった。v3 は owner を design (協議) + run (実行) の2フェーズに分け、design phase で council を並列招集して再帰リスクを下げる。

design phase (協議)

owner は判断せず council_member N 体を並列 spawn

各 member が独立 LLM 呼出で plan を提案

owner (chair) が複数案を比較し merged plan を1つ統合

過半数一致で採用。分裂時は rationale 記録

run phase (実行)

merged plan を tick が機械的に適用

run phase では追加 LLM 呼出なし

→ owner LLM 1回分の依存を解消

bad plan を出すには N+1 体が同時に間違える必要

council_member ロール (新)

Role: council_member   権限: execute + 提案のみ (graf 編集不可)
入力: 全 evidence + proposed 一覧 (owner と同一)
出力: { "member_id":"A", "confidence":0.8, "actions":[...], "dissent":"..." }
既定3体 (--council-size N で変更可)

2-phase 状態機械

owner (pending)  ← _should_dispatch_owner() 待機
   ↓
owner (running)   ─ design phase ─▶ spawn N × council_member (並列, proposed)
   ↓                        owner は全 member 完了待ち (status: council_pending)
owner (running)   ─ chair: merge
   ↓
owner (explored)  ─ run phase 出力 → tick 適用 (機械的)

→ 新 status: council_pending / 新 relation: council_of (owner→member), council_reply (member→owner) / 新列: quest_nodes.phase (design|run) / --council-size 0 で v2 単独 owner に戻る

なぜ今回は設計だけか

11v2: Owner-gated team model

v1 では scout/poc が promising 判定のたびに 勝手に子ノードを spawn していた。LLM 1 個のミスが即グラフに漏れる構造で、「1エージェントはまだミスが多い」限界を捨てきれない。

v1: solo (勝手に進む)

scout が promising → 直接 poc を spawn

poc が dead → 直接 strategist を spawn

1エージェント = グラフの所有者

→ 簡単だがミスが直結

v2: team (owner だけ触れる)

owner だけがグラフ編集権を持つ (唯一)

scout/poc/strategist は proposed ノード(提案)のみ生成。即 spawn しない

owner は十分な証拠が溜まるまで動かない (_should_dispatch_owner gate)

owner 出力 = actions[]: promote / abort / spawn / finish

tick が action を権限チェック付きで適用。未知 ID は弾く

proposed ノードのライフ

# scout/poc/strategist が実行 → proposed を残す
SCOUT POC  ──execute──▶ proposed (by scout)
                          │
                          │ owner が promote で pending 化
                          ▼
                       pending ──▶ running ──▶ explored/growing/aborted
                                               │
                                               └▶ owner が次ラウンドで triage

→ proposed_by 列 & proposed_from エッジで誰の提案か追跡可能。owner は全 evidence を食べて総合判断。「1人で進めるのはダメ、チームで戦う」を機構として保証。

12v2: Web UI — kage ui /quests

kage ui に quest 専用ページを追加。PC・スマホ両方で LAN から確認できる。

kage ui --host 0.0.0.0 --port 8771
# スマホ: http://<raspiのIP>:8771/quests

追加 route

ページ機能:

10実装スコープ & 残課題

今回やったこと (v1+v2)

  • 設計 doc: docs/quest/.../intent.md (v1 + v2 section)
  • DB schema (3 テーブル + mode/proposed_by 列)
  • src/kage/quest.py: QuestMode, owner-gated spawn, action 適用
  • scheduler 末尾に quest_tick() 接続
  • kage quest サブコマンド (--solo 付き)
  • Web UI: /quests + /api/quests
  • テスト 9 件 / ruff pass / 162 tests green
  • README / README_JA / SKILL.md / HTML レポート更新

将来 (intent に設計済み)

  • wall-clock / token 予算の実装
  • connector 経由の人間承認ゲート
  • owner action の厳密 validation
  • proposed 自動間引き (今は上限で間接制御)
  • TUI でのグラフ表示 (現在は Web のみ)
  • kage doctor への quest 診断行
  • ロール プロンプトの quest 単位上書き