ankuro.dev
← ブログ一覧に戻る
【Claude Code × AWS #1】CloudFormationレビューAIを作った——3サブエージェント構成と6つのデプロイ教訓
2026-04-08#Claude Code#AWS#CloudFormation#マルチエージェント#Skills

【Claude Code × AWS #1】CloudFormationレビューAIを作った——3サブエージェント構成と6つのデプロイ教訓

この記事では以下がわかる。

  • 設計・生成・レビューの3サブエージェントが連携するCFnパイプラインの構成
  • 実際に5スタック構成のVPC環境をデプロイして踏んだ6つのエラー
  • エラーをSKILL.mdのルールとして書き込み、次回から防ぐ方法

スキル機能の基本的な仕組み(SKILL.mdの作り方・育て方)は前の記事で解説している。


作ったもの

/cfn-pipeline verification/test/ と打つだけで、ディレクトリ内のMarkdown要件ファイルを読み取り、CloudFormationテンプレートを順番に生成するスキル。

対象ファイル: 5件
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ファイル [1/5]: verification/test/01_VPC_Subnet.md
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[1/3] 設計エージェント 実行中...
✓ [1/3] 設計エージェント 完了

## アーキテクチャ設計(確認)
...

この設計で進めてよいですか?

設計を承認すると、生成・lint・セキュリティスキャンが自動で走り、verification/test/cfn/01_VPC_Subnet.yaml に保存される。


3サブエージェントの役割分担

このスキルの中核は、オーケストレーターが3つのサブエージェントを順番に呼び出す構成。

オーケストレーター(SKILL.md本体)
  ↓
[1/3] 設計エージェント
  要件ヒアリング → 不明点の確認 → アーキテクチャ設計書を出力
  ↓(ユーザーが設計を承認)
[2/3] 生成エージェント
  CFnテンプレート生成 → cfn-lint → checkov
  ↓
[3/3] レビューエージェント
  要件・設計書との照合 → approved / impl_issue / design_issue を判定
  ↓(approved の場合)
ファイルに保存 → 最終lint

設計エージェント

要件ファイルを受け取り、曖昧な点がある場合は生成前にユーザーに確認を求める。「対象環境はdev/stg/prodのどれか」「マルチAZ構成が必要か」「命名規則は何か」などが揃っていない場合は設計を止めて質問する。

確認が完了したら設計書を出力する。

### 作成するリソース一覧

| リソースタイプ   | 論理ID        | 用途                      |
| ---------------- | ------------- | ------------------------- |
| AWS::EC2::VPC    | VPC           | メインVPC 10.0.0.0/16     |
| AWS::EC2::Subnet | SubnetPublicA | パブリックサブネット AZ-a |

...

### リソース間の依存関係

VPC → Subnet → RouteTable → Route

### パラメータ

| パラメータ名 | 型     | デフォルト値 |
| ------------ | ------ | ------------ |
| Env          | String | prod         |

設計書をユーザーに提示し、承認または修正指示を待ってから次のステップへ進む。

生成エージェント

設計書を受け取りYAMLテンプレートを生成する。生成後はcfn-lintでlintを実行し、エラーがあれば自動修正する。checkovでCRITICAL/HIGHのセキュリティ指摘を検出して修正まで行う。

レビューエージェント

生成されたテンプレートを「要件との照合」「設計書との照合」の2段階で検証し、結果をJSON形式で返す。

{
  "route": "approved",
  "summary": "要件・設計書との重大な不一致なし。lint 0件エラー。",
  "requirements_check": [{ "item": "マルチAZ構成", "status": "ok" }],
  "issues": []
}

routeimpl_issue なら生成エージェントに修正を依頼、design_issue なら設計エージェントに戻す。最大3回のループで解決を試みる。


実際に動かした:5スタック構成のVPC環境

以下の要件ファイルを verification/test/ に置いて実行した。

ファイル 内容
01_VPC_Subnet.md VPC・サブネット・IGW・NAT GW・FlowLogs
03_SecurityGroup.md SG×4(ALB/Web/AP/RDS)のSG間参照
04_ALB.md ALB + TargetGroup + HTTPSリスナー
05_EC2.md EC2×4 + IAMロール + InstanceProfile
06_RDS.md RDS MySQL + ParameterGroup + LogGroups

各ファイルで設計確認が入り、承認後に生成・レビューが走る。処理完了後は verification/test/cfn/ にYAMLが5本揃う。


踏んだ6つのエラーとルール化

生成されたテンプレートを実際にデプロイすると6つのエラーが出た。エラーごとに原因を分析し、SKILL.mdの生成エージェントプロンプトにルールとして追記した。

1. 非ASCII文字がコメントに混入した

VPCテンプレートのコメントに (U+2500、罫線文字)が入り込み、SSH Remote環境で「text contents could not be decoded」エラーが発生した。エージェントが見やすさのために罫線文字を使ったのが原因。

# 追記したルール
## 文字コード・エンコーディングルール
- YAMLコメントの区切りは `# ---` や `# ===` など ASCII文字のみを使う
- `─`(U+2500)等の罫線文字・全角文字をコメントに使わない

2. RDSエンジンバージョンが廃止済みだった

EngineVersion: "8.0.35" を指定したところ、ap-northeast-1では提供終了済みのバージョンだとしてデプロイに失敗した。エージェントが学習時点の情報をそのまま使い、実際の提供状況を確認しなかったのが原因。

# 追記したルール
## バージョン指定の事前検証ルール
要件にバージョンが明示されているリソースは、テンプレート生成前にAWS CLIで確認する。

| リソース | 確認コマンド |
|---|---|
| RDS (MySQL) | aws rds describe-db-engine-versions --engine mysql --engine-version <ver> --region <region> |
| EC2 AMI | aws ec2 describe-images --image-ids <ami-id> --region <region> |
| EC2インスタンスタイプ | aws ec2 describe-instance-type-offerings ... |

3. gp3 + Iops の組み合わせが失敗した

StorageType: gp3Iops: 3000 を明示したところ、AllocatedStorageが100GBしかないためエラーになった。gp3のデフォルト(3000 IOPS)を明示指定する場合、AWSはAllocatedStorage 400GB以上を要求する。

# 追記したルール
## RDS固有のルール
- StorageType: gp3 の場合、Iops のデフォルト値(3000)はわざわざ明示しない
- カスタム値を指定する場合は AllocatedStorage が400以上であることを確認する

4. デプロイ順序を間違えた

ALBスタックのデプロイ順序を 01→03→04→05→06 と案内していたが、ALBはターゲットグループにEC2のインスタンスIDをパラメータで受け取るため、EC2(05)を先にデプロイする必要があった。!ImportValue を使うクロススタック参照だけを依存として判断し、パラメータ経由の依存を見落とした。

# 追記したルール
## 前提条件・依存関係のルール
- デプロイ順序は !ImportValue だけでなく、パラメータ経由の依存関係も考慮する
  例: ALBがEC2のインスタンスIDをパラメータで必要とする → EC2を先にデプロイ

5. IAM capabilities を指定し忘れた

EC2スタックに AWS::IAM::Role が含まれていたが、デプロイ時に --capabilities CAPABILITY_NAMED_IAM を指定し忘れてエラーになった。

# 追記したルール
## IAM capabilities のルール
IAMリソースが含まれる場合は、テンプレート冒頭のコメントに明記する。
# デプロイ時の注意:
#   IAMリソースを含むため --capabilities CAPABILITY_NAMED_IAM が必要

6. DBパスワードが平文パラメータだった

RDSの MasterUserPasswordNoEcho: true のパラメータで受け取っていたが、CloudFormationのイベント履歴に平文が残るリスクがある。

# 追記したルール
## パスワード・シークレットのルール
NoEcho パラメータでパスワードを渡す場合、Secrets Manager の動的参照を推奨する旨をコメントに明記する。
# セキュリティ推奨:
#   MasterUserPassword は Secrets Manager の動的参照を推奨
#   例: '{{resolve:secretsmanager:MySecret:SecretString:password}}'

エラー→ルール化のサイクル

今回のポイントは、エラーを踏むたびにSKILL.mdにルールを追記していったこと。

デプロイしてエラーが出る
  ↓
原因を分析する
  ↓
SKILL.mdの生成エージェントプロンプトにルールを追加する
  ↓
次回から同じエラーは生成前に防がれる

一般的なコードであれば「コードを修正する」だけで終わる。AIが生成する場合は「生成AIへの指示を修正する」という一段メタなレイヤーでの修正になる。このサイクルを回すことで、スキルが自分たちのチームのベストプラクティスを埋め込んだCFnジェネレーターになっていく。


スキルの作り方——SKILL.mdの構造と育て方