🐵

Claude CodeのSubAgents × SkillsでPR前にコード品質を守る

に公開

はじめに

こんにちは、データエンジニアの山口歩夢です。

Claude Codeにコードレビューしてもらうという使い方は便利ですが、少しのやり取りで多くのフィードバックをもらうのは大変かと思います。
業務で活用していましたが、複雑なディレクトリ構成の大量のコードを一度にレビューしようとすると、どうしても見落としがあったりして、一度に質の高いフィードバックをもらうのが難しいなと感じていました。

これらを解決するために、レビュー観点ごとの専門エージェントを並列実行し、親エージェントでサマリーをフィードバックするという工夫を行ってみたので、本記事で紹介しようと思います。
PRを作成する前にこれを使ってレビューをすることによって、PR前にコード品質をある程度守ることができるのではないかと考えています!

SubAgentsやSkillsについて

冒頭で話した課題を解決するのに、SubAgentsやSkillを活用したのですが、
本題に入る前に、まずそれらがどういった機能なのかを紹介します。

SubAgentsとは

ClaudeのSubAgentsについて、公式ドキュメントには以下のように書かれています。

サブエージェントは、特定の種類のタスクを処理する特化したAIアシスタントです。各サブエージェントは、カスタムシステムプロンプト、特定のツールアクセス、および独立した権限を持つ独自のコンテキストウィンドウで実行されます。Claudeがサブエージェントの説明に一致するタスクに遭遇すると、そのサブエージェントに委譲され、サブエージェントは独立して動作し、結果を返します。

https://code.claude.com/docs/ja/sub-agents

親エージェントから独立したコンテキストを持っていて、サブエージェントの説明に書かれたタスクに特化した処理を行い、親エージェントにサマリーを返すのが特徴だと思います。

なぜサブエージェントが便利なのか

Claudeはユーザーと会話をして、様々な処理をする上で「コンテキスト」として、
過去の会話履歴、ユーザーの指示、実行したコマンド、実行結果などを保持します。
コンテキストが長くなると重要な情報が埋もれやすく、結果として出力の精度に影響が出ることがあります。

サブエージェントは独立したコンテキスト内で、サブエージェントの説明(mdファイル)に書かれた内容に特化した処理を行い、必要な結果のサマリーを親エージェントへ返します。
そのため、最終的な出力に不要な中間情報を親エージェントのコンテキストへ持ち込まずに済み、結果的に精度の高い出力が得られやすくなります。
このようにコンテキストマネジメント的に使用できるのがサブエージェントです。

Skillsとは

公式ドキュメントには以下のように書かれています。

Skillsは、Claudeに領域固有の専門知識を提供する再利用可能なファイルシステムベースのリソースです。ワークフロー、コンテキスト、ベストプラクティスにより、汎用エージェントを専門家に変えます。プロンプト(1回限りのタスク用の会話レベルの指示)とは異なり、Skillsはオンデマンドで読み込まれ、複数の会話で同じガイダンスを繰り返し提供する必要がなくなります。

ユーザーとの会話文脈に応じて、Claude Codeが必要なSkillを動的に読み込み、SKILL.mdファイルに記述された内容をコンテキストとして実行します。
例えば、SKILL.mdに「ユーザーが『〇〇してください』と指示した場合は、〇〇を使って〇〇を行う」と定義しておくと、ユーザーが該当する指示をした際に、その指針に基づいた振る舞いが自動的に適用されます。

https://platform.claude.com/docs/ja/agents-and-tools/agent-skills/overview

それでは本題に入ります!
前述したように、Claude Codeを活用してレビューをしていると以下のような課題がありました。

課題:1つのエージェントに広い観点でレビューさせるとレビュー漏れが多く発生する

最初は、Claude Codeと普通にやり取りをしながらや、1つのサブエージェントにたくさんのコードをレビューをさせていました。
しかし、実際に使ってみると、どうしてもコードが多くなってくると、レビュー漏れが多いことに気づきました。

CLAUDE.mdにレビュー観点やコーディング規約を書いてはいたのですが、1つのエージェントが複数の観点(型ヒント、命名規則、コメント品質、デッドコードなど)を全てチェックしようとすることにより、重要な情報がどうしても漏れてしまい、各観点が浅いレビューになってしまっていたのかなと考えています。


1つのエージェントに広い範囲でレビューさせるとレビュー漏れが発生してしまう

解決策:SubAgents毎にレビュー観点を分離しSkillsで並列処理

これらの課題を解決するために、複数のレビュー観点ごとの専門サブエージェントを作成し、Skillsを使ってそれらを同時に呼び出し、親エージェントでレビュー結果を統合して出力するアプローチを試してみました。

その結果、非常に詳細なフィードバックが出力されるようになり、レビュー漏れも大幅に減少しました。

SubAgents毎にレビュー観点を分離して並列処理し、親エージェントが結果をまとめる
SubAgents毎にレビュー観点を分離して並列処理し、親エージェントが結果をまとめる

実装アーキテクチャの全体像

前述したとおり複数のレビュー観点ごとの専門サブエージェントを作成し、Skillsを使ってそれらを同時に呼び出し、親エージェントでレビュー結果を統合して出力する仕組みを作りました。
各SubAgentsやSKILL.mdの詳細な内容は割愛しますが、どんな内容を設定したのか概要を紹介します。

まずは、イメージしやすいよう、まずディレクトリ構成を紹介させていただきます。
以下のようにagentsディレクトリに各サブエージェントを配置し、skillsディレクトリにSKILLS.mdファイルを配置するだけになります。

プロジェクトルート/
  └── .claude/
      ├── agents/
      │   └── review-agents/              # レビュー専門エージェント群
      │       ├── README.md               # エージェント一覧
      │       ├── SubAgent1.md            # フレームワーク規約チェック
      │       ├── SubAgent2.md            # プライベート変数命名
      │       ├── SubAgent3.md            # コメント品質分析
      │       ├── SubAgent4.md            # 関数設計評価
      │       ├── SubAgent5.md            # 命名の具体性チェック
      │       ├── SubAgent6.md            # アーキテクチャ配置検証
      │       └── SubAgent7.md            # デッドコード検出
      └── skills/
          └── code-review-skills/
              └── SKILL.md            # SubAgentsの並列実行と調査結果を統合するよう記載

以上がディレクトリ構成になります。
そして、作成したこれらのSubAgentsとSKILL.mdは、以下のようなイメージになります。

1. レビュー観点毎に専門のSubAgentsを用意

まず、コードレビューの観点を書き出し、それぞれに専門特化したサブエージェントを作成しました。
各サブエージェントは1種類の観点を担当するように設計し、その観点に集中できるようにしました。

実際に用意したレビュー観点毎のSubAgentsを紹介します。
今回は以下のような、よくレビューをする時に発生する内容ごとにサブエージェントを用意しました。新しいレビュー観点を思いついたら、都度追加していこうと思っています!

# 区分 役割
1 フレームワーク規約チェック 型ヒント・docstring・テストコードの有無をチェック
2 プライベート変数命名 プライベートメンバーの _ プレフィックス規約をチェック
3 コメント品質分析 不要・過剰・不正確なコメントを検出
4 関数設計評価 複雑度・引数数・ネストの深さなどを多角的に評価
5 命名の具体性チェック df/row/col1 などの汎用的な変数名を検出
6 アーキテクチャ配置検証 ファイル配置の妥当性と重複実装をチェック
7 デッドコード検出 未使用import・関数・変数を信頼度別に検出

2. 複数のSubAgents同時実行するSKILL.mdを作成

次に、レビュー観点毎のサブエージェントを統括するSkillsを実装しました。
以下の流れをオーケストレーションするイメージでSKILL.mdを作成しました。

  1. ユーザーから親エージェントがレビュー依頼を受け取る
  2. Skillsがレビュー観点毎のSubAgentsを並列起動
  3. 各SubAgentsが処理結果を親エージェントに返す
  4. 親エージェントが結果を統合して、レビュー結果レポートを生成

各サブエージェントはそれぞれが専任のレビュー観点に集中して情報収集が可能かつ、独立したコンテキストで実行されるため、高い精度でアウトプットを出してくれます。
そして、最終的に親エージェントはこれらの結果を統合し、異なる観点からの指摘を1つの統一されたレポートとして開発者にフィードバックします。

SKILL.mdに書いた2つの重要なポイント

続いて、SKILL.mdに書いた指示を紹介します。
主に2点あり、「サブエージェントを並列実行する」「SubAgentsの調査結果のサマリーを出力する」というところを書きました。

まず以下のように、「1つのメッセージで7つ全てのサブエージェントを同時に起動すること」 を明記しました。
これにより、書くサブエージェントが親エージェントに同時に調査結果を返してくれます。

1つのメッセージで以下を並列実行:
├─ SubAgent1(フレームワーク規約チェック)
├─ SubAgent2(プライベート変数命名)
├─ SubAgent3(コメント品質分析)
├─ SubAgent4(関数設計評価)
├─ SubAgent5(命名の具体性チェック)
├─ SubAgent6(アーキテクチャ配置検証)
└─ SubAgent7(デッドコード検出)

そして、これらのサブエージェントから返された個別の結果を、親エージェントが1つのレポートに統合するよう指示しました。
観点ごとにレビュー結果を出力してくださいという指示もSKILL.mdに指示を書いて、わかりやすく出力してくれるようにしました。

以上が実際に用意したSubAgentsやSkillsになります。
最後に、レビュー結果がどのように出力されるのかという点も紹介しようと思います。

統合レビュー結果の実例

実際に7つのサブエージェントを並列実行し、親エージェントが統合したレビュー結果の例を示します。
以下の形式で「コード修正の優先度」「レビュー観点毎のフィードバック」「サマリー」のようなものをアウトプットしてくれるように作成しました。
出力形式はSKILL.mdに指示を記載しました。

# コードレビュー結果レポート

レビュー対象: src/data_processor.py, src/utils.py

---

## 📋 検出サマリー

| 観点 | 指摘数 | 重要度 |
|------|--------|--------|
| フレームワーク規約 | 5件 | 🔴 高 |
| プライベート変数命名 | 3件 | 🟡 中 |
| コメント品質 | 2件 | 🟡 中 |
| 関数設計 | 2件 | 🔴 高 |
| 命名の具体性 | 4件 | 🟡 中 |
| アーキテクチャ配置 | 1件 | 🔴 高 |
| デッドコード | 3件 | 🟢 低 |

**合計: 20件の指摘を検出**

---

## 🔴 優先度: 高

### [フレームワーク規約] 型ヒントとdocstringの不足
**ファイル**: `src/data_processor.py:45-67`

```python
# 現状
def process_data(file_path, options):
  return result

# 修正案
def process_data(file_path: str, options: dict) -> pd.DataFrame:
  """データを処理する

  Args:
      file_path: 処理対象ファイルのパス
      options: 処理オプション辞書

  Returns:
      処理済みのDataFrame
  """
  return result
```

---

### [関数設計] 引数の過多と複雑度
**ファイル**: `src/calculator.py:56`

関数 `calculate()` は7個の引数を持ち、推奨値(5個)を超えています。
また、ネストが4段階あり循環的複雑度が高い状態です。

**推奨**: 引数をデータクラスにまとめ、早期リターンで簡素化

---

### [アーキテクチャ配置] 共通機能の重複実装
**ファイル**:
- `apps/sales_report/utils.py:12`
- `apps/inventory_report/utils.py:34`

`format_date()` 関数が2箇所に重複実装されています。

**推奨**: `common/date_utils.py` に統合し、DRY原則に従う

---

## 🟡 優先度: 中

### [プライベート変数命名] _ プレフィックスの不足
**ファイル**: `src/processor.py:23, 45`

- 変数 `cache``_cache`
- メソッド `helper_method``_helper_method`

---

### [命名の具体性] 汎用的な変数名
**ファイル**: `src/report.py:23, 45, 67, 89`

- `df``sales_df` または `product_df`
- `col1`, `col2``title_col`, `button_col`
- `row``sale_record` または `product_row`

---

### [コメント品質] 不要・不正確なコメント
**ファイル**: `src/utils.py:12, 34`

- L12: `# iをインクリメント` ← 自明なため削除推奨
- L34: `# 降順でソート` ← 実際は昇順。コメント修正必要

---

## 🟢 優先度: 低

### [デッドコード] 未使用のimportと関数
**ファイル**: `src/processor.py:5, src/old_calc.py:45`

- `import pandas as pd` (未使用)
- 関数 `old_calculate()` (呼び出し元なし)

**推奨**: 削除してコードを整理

---

## 📊 総合評価

全7つの観点から20件の指摘を検出しました。

**即座の対応が必要な項目 (🔴)**: 8件
- 特に型ヒント・docstringの追加とアーキテクチャの整理を優先してください

**改善推奨項目 (🟡)**: 9件
- 命名規則の統一により可読性が大幅に向上します

**クリーンアップ推奨 (🟢)**: 3件
- デッドコードの削除で保守性が向上します
\`\`\`

以上になります。
各サブエージェントが独立してコードをレビューし、出力した結果を統合することで、開発者は異なる観点からの指摘を一度に把握できるようになります。
PR前にこのサブエージェントのレビューを通すことによって、レビュワーの負担を軽減できるのではないかと考えています。

まとめ

本記事では、Claude CodeのSubAgentsとSkillsを活用し、複数の専門エージェントを並列実行して統合フィードバックするコードレビュー機能を紹介しました。
この機能を導入したことで、命名規則、コードの配置、デッドコードなどの基礎的な品質チェックをサブエージェントが自動的に担ってくれるようになりました。

サブエージェントが基礎的なコード品質を担保してくれることにより、レビュアーがロジック部分のレビューに集中できるようになるのではないかと考えています!

DATUM STUDIO

Discussion