0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform×Claude Code ⑤(全6回) |カスタムサブエージェント自作|AIにコードレビューさせたら意外な発見

0
Last updated at Posted at 2026-02-24

📁GitHubにコード公開tf_claudecode02

シリーズ記事一覧

📑 目次

  1. この記事について
  2. この記事のゴール
  3. 前提知識:カスタムサブエージェントとは
  4. 前提条件
  5. Step 1:2つのレビュアーを設計する
  6. Step 2:並列でレビューを実行する
  7. Step 3:結果を比較する
  8. 考察:なぜ Skills が後退したのか
  9. 体験して分かったこと
  10. まとめ

1. この記事について

1-1. シリーズの位置づけ

本記事は「Terraform × Claude Code」シリーズの第5回です。

記事 サブタイトル 状態
01 Skills比較|4つの公開スキルを調べて分かった最適な組み合わせ ✅実施済み
02 サブエージェント活用|並列調査で01記事の数値を裏付け検証してみた ✅実施済み
03 Skillsインストール&実践|コード生成の品質がどう変わるか検証してみた ✅実施済み
04 CLAUDE.mdカスタムルール|チーム独自のルールをAIに教えてみた ✅実施済み
05 カスタムサブエージェント自作|AIにコードレビューさせたら意外な発見(本記事) 📝本記事
06 カスタムエージェント&Agent Teams|AI開発チームを編成してみた 📄未

1-2. なぜこの記事を書いたか?

04記事で CLAUDE.md にチームルール(A〜E)を書き、
コード生成に反映されることを確認しました。
結果は「5つのルール全て反映、ほぼ完璧」でした。

しかし、04記事の最後にこう書きました。

「守られた」ことの確認を 人間が毎回やるのは大変 です。

この問題を解決するために、
カスタムサブエージェントを自作して、レビューを自動化 します。

さらに、もう1つ気になることがありました。
04記事では CLAUDE.md のルールだけを確認しましたが、
Skills のベストプラクティスはどうなっているのか は未確認です。
03記事で確認された
for_each 優先やバージョン制約の ~> は、
今回も維持されているのでしょうか?

本記事では、2つのサブエージェントを自作して、この疑問に答えます。

1-3. 05記事の方針

項目 方針
サブエージェント 自作して使う(本記事の主役)
レビュー対象 04記事で生成されたコード(iac_04/ 配下)
検証観点 ①CLAUDE.md ルール準拠
②Skills ベストプラクティス

02記事ではサブエージェントを「調査」に使いました。
本記事ではサブエージェントを 「レビュー」 に使います。
同じ道具を、
目的を変えて使うことで、サブエージェントの汎用性を示します。

1-4. 対象読者

  • 02記事でサブエージェントの基本を学んだ方
  • コードレビューを自動化したい方
  • CLAUDE.md と Skills の関係を深く理解したい方

2. この記事のゴール

# ゴール
カスタムサブエージェントの設計・実行ができる
CLAUDE.md ルールと Skills ベストプラクティスの違いを理解できる
CLAUDE.md + Skills 併用時の注意点が分かる

3. 前提知識:カスタムサブエージェントとは

3-1. サブエージェントの復習(02記事より)

02記事で学んだ内容を簡単に振り返ります。

用語 説明
サブエージェント メインの Claude セッションから Task ツールで起動する別プロセス
並列実行 複数のサブエージェントを同時に実行し、それぞれ独立して作業させる
コンテキスト分離 サブエージェント同士は互いの作業を知らない。
結果のみメインに返る

3-2. 02記事との違い

02記事 05記事(本記事)
用途 調査(GitHub リポジトリの情報を並列取得) レビュー(生成済みコードの品質チェック)
入力 URL やキーワード Terraform コードファイル
出力 調査結果のテキスト チェック項目ごとの判定(✅/⚠️/❌)
プロンプトの特徴 「〇〇を調べて」 「〇〇のルールに照らしてチェックして」

サブエージェントの「仕組み」は同じですが、
プロンプトの書き方で役割が変わる のがポイントです。

3-3. カスタムサブエージェントの設計パターン

レビュー用サブエージェントを設計するときの基本パターンです。

1. 役割を定義する(あなたは〇〇レビュアーです)
2. チェック対象を指定する(以下のファイルを読んでください)
3. チェック観点を列挙する(以下のルールに照らして...)
4. 出力形式を指定する(判定: ✅/⚠️/❌、根拠: ...)

4. 前提条件

4-1. 環境

項目 内容
OS Windows 11 + WSL2(Ubuntu)※筆者環境
ツール Claude Code(最新版)
プラン Claude Max
レビュー対象 04記事で生成された iac_04/ 配下のコード

4-2. レビュー対象ファイル

04記事で Skills + CLAUDE.md の状態で生成されたコードです。

iac_04/
├── provider.tf
├── variables.tf
├── locals.tf
├── main.tf
├── outputs.tf
└── modules/vpc/
    ├── main.tf
    ├── variables.tf
    └── outputs.tf

5. Step 1:2つのレビュアーを設計する

5-1. 目的

レビューの観点を2つに分け、それぞれ専用のサブエージェントを設計します。

# レビュアー名 役割 チェック内容
1 ルール準拠チェッカー CLAUDE.md の
ルールA〜Eを守っているか
タグ・命名・バケットポリシー・日本語description・fmt/validate
2 ベストプラクティス監査 Skills の
パターンが適用されているか
for_each vs count・シングルトン命名・変数バリデーション・ファイル構成

なぜ2つに分けるのか?

  • 関心の分離:
    CLAUDE.md のルールと Skills のベストプラクティスは出所が違う。
    混ぜると「どちらの問題か」が分かりにくくなる。
  • 並列実行:
    2つを同時に走らせて結果を比較できる。(02記事で学んだパターン)

5-2. レビュアー1:ルール準拠チェッカーのプロンプト

あなたは Terraform コードレビュアーです。
以下のルール A〜E に対して、生成されたコードが準拠しているかチェックしてください。

## チェック対象ファイル
すべて ~/iac_04/ 配下にあります。
以下のファイルを読んでください:
- variables.tf
- locals.tf
- provider.tf
- main.tf
- outputs.tf
- modules/vpc/main.tf
- modules/vpc/variables.tf
- modules/vpc/outputs.tf

## チェックするルール

### A. 必須タグ
全てのリソースに以下の3つのタグが付与されているか?
- Project(var.project)
- Owner(var.owner)
- CostCenter(var.cost_center)
locals でマージする方式が使われているか?

### B. リソース命名規則
リソースの Name タグが {project}-{env}-{リソース種別} の形式になっているか?

### C. S3 バケットポリシー
S3 バケットにバケットポリシーが付与され、
指定 IAM ロール(var.allowed_role_arn)のみアクセス許可になっているか?

### D. セキュリティグループの description
セキュリティグループおよび各ルールの description が日本語で記述されているか?

### E. コード品質チェック
terraform fmt と terraform validate が実行可能な状態か?

## 出力形式
各ルールについて以下の形式で報告してください:
- 判定: ✅ 準拠 / ⚠️ 一部不備 / ❌ 未準拠
- 根拠: 具体的なファイル名と行番号を示す
- 改善提案: 不備がある場合のみ

最後に総合スコア(5点満点)を付けてください。

5-3. レビュアー2:ベストプラクティス監査のプロンプト

あなたは Terraform ベストプラクティス監査官です。
antonbabenko/terraform-skill の推奨パターンに照らして、
生成されたコードを監査してください。

## チェック対象ファイル
(レビュアー1と同じファイルリスト)

## チェック観点

### 1. for_each vs count
- リソースの繰り返しに for_each が使われているか?
- count が使われている場合、index ベースの参照による
  削除・再作成リスクがあるか?

### 2. シングルトン命名規則
- 同種リソースが1つしかない場合、リソース名が "this" になっているか?

### 3. 変数バリデーション
- 入力変数に validation ブロックが付いているか?

### 4. ファイル構成
- versions.tf / variables.tf / main.tf / outputs.tf の
  4ファイル分割がされているか?

### 5. output の形式
- for_each を使ったリソースの output は Map 形式か?
- 全 output に description が付いているか?

### 6. セキュリティグループのリソース型
- 旧式の ingress/egress ブロックではなく、
  aws_vpc_security_group_ingress_rule が使われているか?

### 7. terraform ブロック
- required_version でバージョンが固定されているか?
- バージョン制約の書き方は ~> か >= か?

## 出力形式
各観点について以下の形式で報告してください:
- 判定: ✅ ベストプラクティス準拠 / ⚠️ 一部乖離 / ❌ 非準拠
- 現状: 具体的なファイル名と行番号
- 推奨: ベストプラクティスではどうすべきか
- 影響度: 高/中/低

最後に総合評価を付けてください。

5-4. プロンプト設計のポイント

ポイント 理由
チェック対象ファイルを明示 サブエージェントは文脈を共有しないため、ファイルパスを完全に指定する
チェック観点を番号付きで列挙 曖昧な「レビューして」ではなく、具体的な観点を与える
出力形式を指定 結果を比較しやすくするため、判定・根拠・改善提案の形式を統一
スコアリングを要求 定量的な比較を可能にする

6. Step 2:並列でレビューを実行する

6-1. 目的

2つのレビュアーを 並列で 実行します。
02記事で学んだ「Task ツールの並列実行」の実践です。

6-2. 実行方法

Claude Code の Task ツールで、2つのサブエージェントを同時に起動します。

2つのサブエージェントは
互いの作業を知らず、独立して ファイルを読み、チェックし、結果を返します。

6-3. 実行結果

2つのサブエージェントがそれぞれ約1分で完了しました。


7. Step 3:結果を比較する

7-1. レビュアー1:ルール準拠チェック — 4.5 / 5.0

ルール 判定 根拠
A. 必須タグ ✅ 準拠 locals.tfcommon_tags 定義。
全リソースで merge(local.common_tags, {...})
VPCモジュールには common_tags 変数で受け渡し
B. 命名規則 ✅ 準拠 全リソースの Name タグが {project}-{env}-{種別} 形式。
例に挙げていないIGW・NAT・サブネットにも自動拡張
C. S3バケットポリシー ⚠️ 一部不備 aws_s3_bucket_policy.logsvar.allowed_role_arn を許可。
ただし 明示的な Deny がない
D. SG description 日本語 ✅ 準拠 SG本体・SSH・Egress の3つ全て日本語
E. コード品質チェック ✅ 準拠 terraform fmt / terraform validate ともに成功

ルールC の不備の詳細

レビュアー1が指摘した唯一の不備は、S3 バケットポリシーの構造です。

現状(Allow のみ):

Statement = [
  {
    Sid    = "AllowAccessFromSpecifiedRole"
    Effect = "Allow"
    Principal = {
      AWS = var.allowed_role_arn
    }
    Action   = ["s3:GetObject", "s3:PutObject", "s3:ListBucket"]
    Resource = [aws_s3_bucket.logs.arn, "${aws_s3_bucket.logs.arn}/*"]
  }
]

問題点:
Allow だけでは、
他の IAM ポリシーで許可されたプリンシパルもアクセスできてしまう。

レビュアーの改善提案:

# 指定ロール以外を明示的に拒否する Deny ステートメントを追加

{
  Sid       = "DenyAccessFromOtherPrincipals"
  Effect    = "Deny"
  Principal = "*"
  Action    = "s3:*"
  Resource  = [
    aws_s3_bucket.logs.arn,
    "${aws_s3_bucket.logs.arn}/*"
  ]
  Condition = {
    StringNotEquals = {
      "aws:PrincipalArn" = var.allowed_role_arn
    }
  }
}

[!NOTE]
これは CLAUDE.md のルールCに「のみアクセスを許可する」と書いたにもかかわらず、
コード生成では Allow のみで Deny が欠落したケースです。
「のみ」という曖昧な表現では、
明示的な Deny まで生成されないことが分かりました。

7-2. レビュアー2:ベストプラクティス監査 — 1 / 7 準拠

観点 判定 影響度 詳細
1. for_each vs count ❌ 非準拠 サブネット・NAT・ルートテーブルすべて count + index ベース
2. シングルトン命名 ⚠️ 一部乖離 VPCモジュール内は "this" だが、ルートは "logs" / "web"
3. 変数バリデーション ❌ 非準拠 validation ブロックが一切ない
4. ファイル構成 ⚠️ 一部乖離 versions.tf がない。
provider.tfterraform ブロックが同居
5. output の形式 ⚠️ 一部乖離 リスト形式(Map 形式ではない)。
description は全て付与
6. SG リソース型 ✅ 準拠 aws_vpc_security_group_ingress_rule / egress_rule を使用
7. terraform ブロック ⚠️ 一部乖離 >= 1.0.0 / >= 5.0.0~> ではなく >=

7-3. 2つの結果を並べる

ここで、2つのレビュアーの結果を並べてみます。

CLAUDE.md ルール準拠(レビュアー1) Skills ベストプラクティス(レビュアー2)
4.5 / 5.0(ほぼ完璧) 1 / 7 準拠(大半が後退)

CLAUDE.md のルールはほぼ完璧に守られた。
しかし、Skills のベストプラクティスは大半が後退していた。

これは04記事の時点では見えていなかった発見です。
04記事では
CLAUDE.md のルール(A〜E)だけを確認し、
「5つ全て反映、ほぼ完璧」と結論付けました。
しかし、
別の観点でチェックしたら別の結果が見える ことを、
サブエージェントによるレビューが明らかにしました。

7-4. 具体的にどこが後退したのか

03記事(Skills のみ)と04記事(Skills + CLAUDE.md)を比較します。

項目 03記事(Skills のみ) 04記事(Skills + CLAUDE.md) 変化
サブネットのループ for_each(map) count(list) ❌ 後退
SSH ingress for_each で複数CIDR対応 count + [0] で先頭1つだけ ❌ 後退
リソース名 "this"(シングルトン) "logs", "web" 等(用途名) ⚠️ 変化
変数バリデーション CIDR の validation あり validation なし ❌ 後退
versions.tf あり(~> 1.9 なし(provider.tf>= 1.0.0 ❌ 後退
サブネット変数の型 map(string) list(string) ❌ 後退
output の形式 Map(AZ → ID) リスト ❌ 後退

7項目中6項目が後退 しています。


8. 考察:なぜ Skills が後退したのか?

8-1. 3つの仮説

# 仮説 説明
1 CLAUDE.md が
Skills より優先された
CLAUDE.md はプロジェクトに直接紐づくため、Claude の注意がCLAUDE.mdに集中した
2 統合プロジェクトの
文脈が影響した
03記事は個別リソースだったので "this" が自然だったが、統合プロジェクトでは複数リソースがあるため "this" が使えない → 他のパターンも連鎖的に変わった
3 ルールA〜Eへの注意力が
Skills を押し出した
5つのカスタムルールに注意を向けた結果、Skills のパターンへの注意リソースが減少した

8-2. 仮説の検証

仮説 支持する根拠 限界 評価
1. CLAUDE.md 優先 CLAUDE.md: 5つ中4つ完璧、Skills: 7つ中1つ準拠。注意配分の偏りを示唆 ◎ 有力
2. 統合プロジェクト "this" は統合時に区別がつかない → 合理的判断 for_eachvalidation の後退は説明不能 △ 部分的
3. 明示 > 暗黙 CLAUDE.md = 具体的指示、Skills = 暗黙注入(SKILL.md)。明示ルールが勝った ◎ 有力

8-3. 結論

3つの仮説はそれぞれ一部を説明しますが、最も有力なのは 仮説1 + 仮説3 の組み合わせ です。

CLAUDE.md は「プロジェクト固有の明示的なルール」であるため、
Skills の「汎用的な暗黙のルール」よりも優先される傾向がある。

これは「バグ」ではなく、設計上の自然な振る舞い と言えます。
プロジェクト固有のルールが優先されるのは、人間のチームでも同じです。
新メンバーに「業界のベストプラクティスより、まずうちのルールを覚えて」と言うのと似ています。

8-4. 実務への示唆

この発見から導かれる実務的な教訓です。

教訓 対策
CLAUDE.md に書いたルールは
高い確率で反映される
反映させたいルールは CLAUDE.md に明示的に書く
Skills のパターンは
CLAUDE.md と併用すると後退しうる
Skills のパターンも重要な場合は CLAUDE.md に重複記載する
「のみ」「必ず」などの曖昧な表現は
厳密に解釈されない場合がある
実装方法まで具体的に指示する(例:Deny ステートメントを追加する)

9. 体験して分かったこと

9-1. サブエージェントについて

  1. プロンプトの書き方で役割が変わる:
    02記事では「調査」、本記事では「レビュー」に使った。
    同じ Task ツールでも、プロンプト次第で別の仕事ができる
  2. 並列実行が効果的:
    2つのレビュアーを同時に走らせて、それぞれ約1分で完了。
    人間が全ファイルを2つの観点でチェックするより圧倒的に速い
  3. 「別の視点」を入れられるのが最大の価値:
    04記事ではCLAUDE.mdのルールだけを見て「完璧」と思っていた。
    しかしサブエージェントで「Skills のベストプラクティス」という別の視点を入れたら、見落としが発覚した

9-2. CLAUDE.md と Skills の関係について

  1. CLAUDE.md は「強い指示」:
    反映率が非常に高い。
    チーム独自のルールは CLAUDE.md に書くのが正解
  2. Skills は「弱い指示」になりうる:
    CLAUDE.md と併用すると後退する場合がある。
    Skills のパターンも重要なら CLAUDE.md に重複記載が必要
  3. 「完璧」は観点次第:
    1つの観点では完璧でも、別の観点からは問題がある。
    レビュー観点を複数持つことの重要性を実感した

9-3. 期待と違った点

  1. Skills が有効なのにパターンが後退したこと:
    Skills は有効のまま実験したので、
    Skills + CLAUDE.md の「両方の良いとこ取り」を期待していた。
    実際には CLAUDE.md が優勢で、Skills が後退するケースがあった。
  2. CLAUDE.md の「のみ」が厳密に解釈されなかったこと:
    ルールCで「指定 IAM ロールのみアクセス許可」と書いたが、
    生成されたのは Allow だけで Deny がなかった。
    自然言語の曖昧さは CLAUDE.md でも完全には解決しない。

10. まとめ

10-1. この記事で分かったこと

ゴール 結果
①カスタムサブエージェントの設計・実行 「役割定義 → チェック対象 → チェック観点 → 出力形式」の設計パターンで作成。
並列実行も成功
②CLAUDE.md ルール vs Skills ベストプラクティス CLAUDE.md: 4.5/5.0(ほぼ完璧)、Skills: 1/7(大半が後退)。
明示的ルールが暗黙ルールに勝つ
③併用時の注意点 Skills のパターンも重要な場合は CLAUDE.md に重複記載する。
「のみ」等の曖昧表現は避けて具体的に書く

10-2. シリーズを通して学んだこと

ここまでの5記事で、以下の知識が積み上がりました。

記事 学んだこと 積み上がった知識
01 Skills の比較と選び方 「何を使うか」
02 サブエージェントの基本 「道具の使い方」
03 Skills の効果検証 「汎用ルールの威力」
04 CLAUDE.md のカスタムルール 「チーム固有ルールの威力」
05 サブエージェントでレビュー + 意外な発見 「自動レビュー」+「2つの仕組みの関係」

10-3. 次のステップ

01〜05で 個人 としての Claude Code 活用を学びました。

  • Skills でコード品質を上げる
  • CLAUDE.md でチームルールを教える
  • サブエージェントでレビューを自動化する

次回の06記事では、
Agent Teams でインフラ設計チームを組みます。
複数のエージェントを
「チーム」として編成し、インフラ設計を分担させる方法を紹介します。


参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?