Yyatmita

【第5回】自作しない、着替えさせる——公式エージェントをスキルでラップする

Claude Code 公式プラグインのサブエージェントを、自作スキルでラップして自分のドメイン専用ツールに化けさせる発想。サブエージェントのネスト禁止に当たって辿り着いた設計パターン

Claude Codeサブエージェント検証#claude-code#subagent#plugin#workflow
← 前の記事: 【第4回】エージェントを構築する——スキル委任・agent-creator・article-writer の実践

前回(第4回)で「スキル→自作エージェント委任」のパターンを扱った。そのあと自分用の小さなオーケストレーション・スキルを作っていて、自然な発展形に行き着いた。

自作しない。公式エージェントをスキルで着替えさせる。

これは想定していた設計ではなく、ある制約に当たった結果として辿り着いたパターンだ。今回はその経緯と、なぜこの形が筋いいのかを書く。

当初の発想:専用エージェントを作る

Anthropic 公式マーケットプレイスに feature-dev というプラグインがあって、code-explorer / code-architect / code-reviewer という 3 つのサブエージェントを持っている。これらは汎用設計で、特定のプロジェクト文脈を知らない。

私がやりたかったのは、自分の開発フロー専用に「自プロジェクトの文脈を組み込んでから公式エージェントを呼ぶ」アダプタ的なエージェントを作ることだった。図にするとこう。

Main Claude
  │
  └─ my-architect (自作アダプタ)
        │
        └─ feature-dev:code-architect (公式) × 3 並列

自作の my-architect がプロジェクト固有の文脈(プロジェクト仕様、issue、過去の決定)を組み立てて、公式の code-architect に「この文脈で 3 つの違う focus(最小変更/クリーン/バランス)で設計案を返せ」と渡す。返ってきた 3 案を自作アダプタが整形して Main に返す。

綺麗なアダプタ層だと思った。公式は触らず、間に自作レイヤを挟むだけ。

壁:サブエージェントはネストできない

実装してみたら動かない。自作エージェント側から feature-dev:code-architect を Task ツール経由で起動しようとしても、何も起こらない。

公式ドキュメントを引いてもらった結果がこれだった。

Subagents cannot spawn other subagents, so Agent(agent_type) has no effect in subagent definitions.

Claude Code 公式ドキュメント

サブエージェントから別のサブエージェントを起動することは 仕様レベルで禁止 されている。ユーザー定義でも組み込みエージェントでも同じ。tools: Task を frontmatter で許可しても実行時にブロックされる。設定でも変えられない。理由は無限ループ防止。

つまり「アダプタ・サブエージェント」という発想そのものが成立しない。layer を 1 つ増やすという普通のソフトウェア工学の発想が、ここでは効かなかった。

転換:スキルを薄いプロトコル層にする

ネスト禁止に当たって最初に考えたのは「自作エージェントの中に、公式エージェント相当のロジックも全部書いてしまう」だった。これは要するに公式に依存せず単独完結する道。動くけれど、公式の改善が乗らないし、自作分の保守責任を持つことになる。

そこで思考をもう一段引いた。

サブエージェントから別のサブエージェントは呼べない。でも、スキルからサブエージェントは呼べる。スキルはサブエージェントではない。スキルは Main Claude の指示書(プロンプトの拡張)であって、独立した context を持たない。だからスキル本体が Task ツールを使って公式エージェントを起動するのは、Main からの直接起動と同じ扱いになる。これはネスト禁止に抵触しない。

当初想定(不可)          現実解
─────────────            ─────────────
Main                     Main
  └─ 自作アダプタ          └─ スキル(プロトコル層)
       └─ 公式 ×3              └─ 公式 ×3 を直接起動
       (ネスト 2 段で禁止)     (1 段なので OK)

スキルが「何を、どんな形式で返してほしいか」を起動プロンプトに書き込む。公式エージェントは context が独立しているので、スキルが渡したプロンプトに完全に従って動く。

OUTPUT REQUIREMENT で着替えさせる

ここが今回の中心アイディアだ。公式エージェントは汎用設計なので、デフォルトでは自分のドメイン形式では返さない。だが起動プロンプトの末尾に OUTPUT REQUIREMENT セクション を入れて「必ずこのフォーマットで返せ」と強制すると、出力の形を自分のドメインに揃えられる。

例えば私が使ったのはこういうテンプレート(抜粋・一般化)。

[CONTEXT]
<プロジェクト固有の文脈をここに展開>

[FOCUS]
<3 並列のうちこの 1 件はどんな観点で設計するか>

[TASK]
issue #N: <タイトル> の実装方針を上記 FOCUS で設計せよ。

[OUTPUT REQUIREMENT]
通常の architecture blueprint に加えて、必ず以下のセクションを末尾に含めよ。
セクション名と項目名は厳密に守ること(後段の自動整形が依存する)。

## My Adapter Output

- touched_files: ファイルパスを bullet で列挙
- dod: 検証可能な完了条件 3-6 件
- out_of_scope: 触らない領域
- canary_dod: 早期暴走検知用の構造化検証可能な DoD を 1 つ
- ralph_loop_risk: Bash 自動ループで駆動した場合のリスク

[CONSTRAINTS]
- 実装はしない(Edit / Write は使わない)。設計提案のみ。

公式 code-architect は本来「decisive な 1 案の architecture blueprint を返す」ように書かれている。でも起動プロンプトに OUTPUT REQUIREMENT を上乗せすると、blueprint の 末尾に自分のドメイン形式のセクションが付いて返ってくる。スキル側はその末尾セクションだけ抽出すればよく、blueprint 本体は捨てて構わない。

これが「着替えさせる」ということだ。エージェント本体は触らず、起動プロンプトで形式だけ自分仕様に変える。

並列 3 起動の実験結果

実際に同じ context を渡して focus だけ変えた 3 並列起動を試した。code-architect を 3 つ並列で同時起動して、focus を「Minimal Changes」「Clean Architecture」「Pragmatic Balance」に振り分ける。

結果:

  • 3 つとも OUTPUT REQUIREMENT を厳密に守った## My Adapter Output セクションが揃って返ってきた。書式違反は 0 件
  • 3 案がきれいに直交した。Minimal は変更面積最小、Clean は templates 分離、Balanced はその中間。同じ context から異なる軸の判断が出た
  • canary DoD の選び方が 3 案で違った。Minimal は bash -n(構文チェック)、Clean は TOML パース、Balanced は install + ls。各案の暴走モードに応じた検証を独立に提案してきた
  • 起動ラグはほぼなし。並列の同時性が崩れない

これは並列で異なる観点を発散させて人間に選ばせる、という処理パターンとして成立する。1 つのエージェントに「3 案出して」と頼むと案同士が引きずられがちだが、独立 context の 3 並列だと観点の独立性が保たれる。

なぜこの形が筋いいか

整理するとこうなる。

1. 自作分の責任が最小化される

エージェント本体のロジック(コードベース解析、設計判断、blueprint 生成)は公式が持つ。自作スキルは「文脈を組み立てる」「OUTPUT REQUIREMENT を渡す」「3 並列を統合する」だけ。公式が改善されれば自動で乗る。

2. 着替えさせるだけで専用化できる

code-architect は本来汎用だが、OUTPUT REQUIREMENT で形式を強制すれば自分のドメイン専用ツールに化ける。エージェント本体を fork する必要がない。プロジェクトを変えるたびに OUTPUT REQUIREMENT だけ書き換えればいい。

3. プロトコル層と実行層が分離する

スキル = プロトコル層(呼び出し方と出力形式の契約)、公式エージェント = 実行層(実際の処理)。型システム的に言えば、スキルが interface を定義して、公式エージェントが implementation を提供する関係。後で別のエージェントに差し替えても、interface が同じなら動く。

4. ネスト禁止という制約と相性がいい

サブエージェントのネスト禁止は「アダプタ層を 1 段増やす」という素直な発想を封じる。だがスキルは subagent ではないので、スキルをアダプタ層として使えば制約に抵触せず同じことができる。仕様の制約に対して、層の選び方で逃げる設計。

第 4 回との接続

第 4 回では「スキル→自作エージェント委任」を扱った。当時の前提は「自作エージェントが処理本体を担う」だった。今回はその拡張として「自作エージェントの代わりに公式エージェントを呼ぶ」と「自作エージェントは書かず、スキルが直接呼ぶ」の 2 つを足した。

連載を通した結論を言い直すとこうなる。

  • スキル:いつ・どう呼ぶかの責務
  • エージェント:何をするかの責務(公式でも自作でもいい)
  • OUTPUT REQUIREMENT:エージェントの出力をスキルが読める形に揃える契約

この 3 つを分けて考えると、Claude Code のサブエージェント機能は「自作する道具」というより「借り物を着替えさせる道具」として使える。feature-dev のような公式プラグインが増えれば増えるほど、自作する代わりに着替えさせる選択肢が広がっていく。

まとめ

「サブエージェントは作るもの」と思いがちだが、公式に良いものがあるなら作らない方がいい。スキルでラップして OUTPUT REQUIREMENT で着替えさせるだけで、自分のドメイン専用ツールに化ける。エージェント本体は触らず、起動プロンプトで形式だけ強制する。

サブエージェントのネスト禁止という制約に当たって、最初は壁に見えた。でもスキルがプロトコル層として機能することに気づくと、制約に逆らわずに同じことができる。仕様の制約に対して、層の選び方で逃げる——これは Claude Code を使い込むほど効いてくる発想だと思う。

連載は今回で本当に区切り。第 4 回の「自作する話」と、今回の「自作しない話」を両方持っておくと、状況に応じて選べるようになる。