作成日: 2026-03-31
ステータス: Draft
関連文書:
本書は、butler2 における Butler を「複数の内部実務ユニットを束ねる執事長」として再定義した上位アーキテクチャを示す。
ここでの主題は、Maid を単一 provider ではなく、
用途別に異なる属性を持つ内部 worker 群 として扱う構成である。
ここでいう v1 は、旧 ButlerLayer の 01_アーキテクチャ定義書.md を中心とした従来整理を指す。
本書はそれを全面置換するものではなく、Maid と worker routing に関する上位補完文書 として位置づける。
従来は、Butler の下で特定の provider や特定モデルを直接切り替える発想が強かった。
しかしこの形では、provider 差・model 差・役割差がコード内に漏れやすい。
v2 では以下のように見直す。
Maid 抽象v1(ButlerLayer/butler/)約20モジュール
agent_backend.py / agent_executor.py / execution_backend.py
langgraph_backend.py / mcp_executor.py / mcp_gh_copilot.py
orchestrator.py / qwen_gate.py / reload_utils.py
skills_registry.py / sop_resolver.py / guidance.py
windmill_backend.py / wsl_compat.py ...
v2(butler2/butler/)責務が明確なモジュールのみ
cli.py / env.py / implement.py / maids/
mcp_facade.py / models.py / registry.py
result.py / router.py / runtime.py
mcp_executor.py / mcp_gh_copilot.py として断片的に存在mcp_facade.py として独立した薄い接続層を設け、Brain→Butler の MCP 経路を正式化
execute_task 巨大ツールを廃止)failed + evidence を Brain に返し、Brain が次経路を判断する設計maid_registry.yml と intent_maid_routes.yml で YAML 管理
intent → maid_id のテーブルルーティングqwen_gate.py)など model 固有ロジックありdocs/reference/、docs/capabilities/ 等に分散docs/マスタードキュメント.md を中心に再構成
黒執事アーキテクチャ_v2.md(本書、上位設計書)docs/capabilities/maid/仕様書_v3.md(Maid 詳細仕様)Butler利用ガイド.md(Brain 向け利用ガイド)Brain
└─[MCP]──→ Butler Layer
├─ Contract / Policy / Approval
├─ API / CLI / MCP Facade
├─ Routing
├─ Recorder / Evidence
├─ Git / Wiki / Trilium / Gitea capabilities
└─ Maid Orchestration
├─ Maid Registry
├─ Prompt Builder
├─ Launcher
├─ Supervisor
├─ Verifier
└─ Worker Instances
├─ Goose(OpenRouter, implement)
├─ Goose(OpenRouter, docs)
├─ Goose(Ollama, implement)
└─ Script(formatter)
現行実装では、Butler 本体はまず Python ライブラリとして成立させ、
その上に接続方式ごとの薄い facade を載せる。
execute_task() を中心とする routing / supervision / verification 本体この分離により、Butler の本質である task 実行ロジックを
MCP や CLI と切り離してテスト・再利用できるようにする。
Maid は Butler の内部 worker 抽象である。
Maid は「AI そのもの」ではなく、Butler が委任できる実務実行ユニットの総称である。
maid_idkindprovidermodelrolelaunch_configverification_profileenabledButler は intent ごとに適切な Maid を選択する。
選択はコード分岐ではなくテーブルまたは設定で行う。
ただし初期段階では「委譲すべき task かどうか」の判断を routing の前段に置き、
小タスクまで無条件に Goose へ流さない。
intent -> maid_id
ルーティングは intent_maid_routes.yml で定義し、先に一致したルートが優先される。
task の性質に応じて worker を分岐させる条件を conditions_json に記述できる。
intent とルーティング先の例:
implement → goose_*_implement(常に Goose。探索・推論が必要な実装)apply_edits → file_edit_worker(LLM不要。Brain が差分を計算済みの場合)将来的には以下を条件に加えてよい。
このテーブル化により、Butler は
これは ButlerLayer における責務分離を大きく改善する。
Goose は以下の点で有力である。
つまり Goose は、手足付き Maid の実体候補として現在最も現実的である。
現時点の Goose は完全自走ではなく、補助ありの部分成功である。
したがって Butler は Goose を放置せず、supervisor として介入を自動化する。
ただし現時点の知見は限定的であり、supervision が多様な失敗パターンに十分対応できるかは未検証である。
Brain -> Butler -> Goose -> Butler(supervisor) -> Brain
人間がやっていた以下の補助は Butler に移す。
この方針は有効候補だが、まだ 1 タスク系の試験結果に強く依存している。
したがって Goose supervision mode は、多様な task で失敗分類と再依頼文の妥当性を検証しながら育てる前提とする。
複数モデルを Butler 自身が直接呼ぶのではなく、複数 Goose を別 worker として持つ。
例:
| maid_id | kind | provider | model | role |
|---|---|---|---|---|
goose_openrouter_qwen3coder30b |
goose | openrouter | qwen/qwen3-coder-30b-a3b-instruct |
general_reasoning |
goose_openrouter_grok41fast |
goose | openrouter | x-ai/grok-4.1-fast |
general_reasoning |
goose_ollama_qwen3_8b |
goose | ollama | qwen3:8b |
general_reasoning |
script_formatter |
script | local_script | n/a | formatting |
現時点の session_log summarize 評価候補は次の 3 つに絞る。
goose_openrouter_qwen3coder30bgoose_openrouter_grok41fastgoose_ollama_qwen3_8bgoose_ollama_qwen35_9b は過去の試験で不安定だったため、現時点の候補から外す。
implement intent については、現時点の既定 worker を
goose_openrouter_grok41fast_implement とする。
理由:
研究枠としては、次の 2 つを継続評価対象とする。
qwen/qwen3-coder-nextgoogle/gemini-3.1-flash-lite-previewqwen/qwen3-coder-30b-a3b-instruct次は、現時点では implement 候補から外す。
deepseek/deepseek-v3.2初期既定値として、supervisor の再試行上限は 3 回 とする。
ここでいう 3 回は 初回実行 1 回 + 再依頼 2 回 を意味する。
3 回で成功しない場合、Butler は failed を返し、Brain に evidence を添えて終了する。
failed 返却後の次経路は自動で固定しない。
Brain は evidence を読んだ上で、Brain 直実行に切り替えるか、別 Maid / 別 capability / task 分割へ切り替えるかを判断する。
この判断を可能にするため、Butler は失敗理由だけでなく、何回試したか、どこで失敗したかを読み取れる evidence を返す必要がある。
MCP facade を経由する場合も、この責務分離は維持する。
implement のような長時間 task では、MCP 側は core の内部監視を置き換えず、
少なくとも「開始した」「dispatch した」「終了した」を progress として Brain に返す薄い中継層として振る舞う。
Maid 実体は「完全自走できるか」だけでは採用を決めない。
次を総合評価する。
maid_registry / intent_maid_routes を YAML で実装する黒執事アーキテクチャ v2 における核心は、
Butler の下に単一の Maid provider を置くのではなく、複数属性を持つ Maid 群を置き、Butler がそれらを route・監督・検証する
ことである。
この構成により、
Maid 選択へ昇華できる3〜13 章では Butler が Maid を束ねる内部構造を定義した。
本章では Butler と Brain がどう協調するかの 外向き品質保証原則 を定義する。
この原則は implement 固有の話ではない。
Butler が提供するすべての capability(intent)に適用される設計基準 である。
Brain(Claude Code、Goose、その他)がルールを「覚えている」ことに依存してはならない。
settings.json フックは Claude Code にしか効かない強制したいルールはすべて Butler サーバー側に実装する。
すべての capability は以下 4 軸を備えていること。
| 軸 | タイミング | 目的 | 実装場所 |
|---|---|---|---|
| 軸1: 事前情報提供 | 実行前 | Brain が正しいコントラクトを書けるようにする | MCP リソース |
| 軸2: 入力検証 | 実行時(前) | 不正・不完全なコントラクトを拒否する | preflight pipeline |
| 軸3: 次アクション明示 | 実行時(後) | Brain が次に何をすべきか迷わないようにする | post-process pipeline |
| 軸4: 状態整合性チェック | 実行時(前) | 前の操作の取りこぼしを検知して警告する | state_check pipeline |
Brain が execute_task を呼ぶ前に、正しいコントラクトの形を知れる仕組み。
butler://usage-guide — 全 intent 共通の最小構造例(実装済み)butler://skill/{intent} — intent ごとの payload スキーマ・例(未実装)get_contract_template ツール — intent 指定で穴埋めテンプレートを返す(未実装)コントラクトの不備を早期に・まとめて返す。
ok レスポンスに「次にやるべきこと」を含める。
"next_required_action": {
"intent": "git_push",
"reason": "implement completed, changes are committed on butler/task-{id} branch"
}
Brain はレスポンスを読むだけで次の手が分かる。ルールを覚えなくていい。
設計変更(2026-04-15): 旧設計では implement 完了後の変更は未コミット状態で返し、Brain が
git_commitを next_required_action として発行していた。新設計では ImplementMaid が Goose 終了後に自らコミットして返すため、Brain が git_commit を別途発行する必要はない。詳細は ImplementMaid 仕様書 を参照。
前の操作が正しく完了しているかを、次の操作の前に検証する。
先に git_commit で変更をコミットしてください を追加すべき)enforce_delegation.sh にルートがない intent が登録されている場合に警告)4軸は 各 capability が自前で実装するのではなく、Butler core が全 capability を包む共通層として実装する。
理由:
execute_task(task)
├─ [軸4] state_check(task) ← 全 intent 共通・実行前
├─ [軸2] preflight_validate(task) ← intent 別・実行前
├─ maid.execute(task) ← capability 本体(変更なし)
└─ [軸3] post_process(task, result) ← intent 別・実行後
butler://skill/{intent} ← [軸1] MCP リソース・intent 別
Python での実装形:
@dataclass
class CapabilityLifecycle:
# 軸2: 入力検証(None を返せば通過)
preflight: Callable[[TaskContract], ResultContract | None] | None = None
# 軸3: 次アクション注入
post_process: Callable[[TaskContract, ResultContract], ResultContract] | None = None
LIFECYCLE_REGISTRY: dict[str, CapabilityLifecycle] = {
"implement": CapabilityLifecycle(
preflight=preflight_validate,
post_process=inject_git_push_next_action, # ImplementMaid がコミット済みのため git_push を促す
),
"git_commit": CapabilityLifecycle(
preflight=preflight_git_commit,
),
# ...
}
capability 側(MaidExecutor Protocol)は変更しない。
新しい capability を追加したとき、LIFECYCLE_REGISTRY に登録しなければ軸2〜3 が効かないため、
レビューで気づける(テストや起動時検証で強制することも可能)。
軸4(state_check)と軸1(MCP リソース)は capability 横断なので別途実装する。
Brain はタスクの性質に応じて異なる intent を使い分ける。
| タスクの性質 | intent | worker |
|---|---|---|
| 推論・探索が必要な実装 | implement |
goose_*_implement(Goose) |
| 決定論的変更(文字列置換・定数追加等) | apply_edits |
file_edit_worker |
apply_edits の payload スキーマ:
{
"edits": [
{"file": "path/to/file.py", "old_string": "...", "new_string": "..."}
]
}
Brain は run_apply_edits MCP ツールを呼ぶことで apply_edits intent を発行できる。
implement intent は条件なしで常に Goose にルーティングされる。
| 軸 | 全 intent 共通部 | implement | git_commit | gitea | session_log |
|---|---|---|---|---|---|
| 軸1: 事前情報 | usage-guide ✅ | 例あり ✅ | 例あり ✅ | - | - |
| 軸2: 入力検証 | - | 一括返却 ✅ | - | 1件ずつ ⚠️ | - |
| 軸3: 次アクション | - | - | - | - | - |
| 軸4: 状態整合性 | 未コミット拒否 ✅ | ヒントなし ⚠️ | - | - | - |
- 未実装詳細は Issue #24 を参照。
docs/マスタードキュメント.mddocs/capabilities/maid/仕様書_v3.mddocs/reference/01_アーキテクチャ定義書.md(経緯参照)goose_test リポジトリ Issue #1 に記録された実験メモ(経緯参照)