HOME/ブログ/AIに気をつけてもらうのではなく、間違えられない構造をつくる
ai-driven-development-structural-guardrails-eyecatch
AI 駆動開発

AIに気をつけてもらうのではなく、間違えられない構造をつくる

avatar
Junki Tamae

AIコーディングエージェントを使った開発では、スピードが出る一方で「言った/言わない」の漏れや、確認漏れによる事故が起きやすくなります。あるプロダクト開発プロジェクトでは、この課題に対して口頭の注意喚起に頼るのではなく、開発速度・セキュリティ・品質の3つの軸で「仕組み」による解決を進めてきました。本記事では、実際に使っているスキル・フック・CI設定を、プロンプトの具体例とあわせて紹介します。


前提: なぜ仕組みで防ぐのか

AIエージェントに逐一「これをやっていいか」を確認させると、確認自体が積み重なって効率を落とします。かといって好きにやらせると、方針から外れた実装をしてから修正する手戻りが発生します。

このプロジェクトで採用したのは、実装前に必ず計画を提示させる defaultMode: "plan" の設定です。依頼を受けたら計画を提示し、承認を得てから実装に進むフローを強制します。最初の計画提示には時間がかかりますが、的外れな実装を作ってからやり直すよりも、トータルの手戻りは小さくなります。

Code

という依頼に対して、AIがいきなり実装を始めるのではなく、変更ファイル・手順・検証方法を含む計画を提示してから承認待ちに入るようにしています。

同時に、コミット・プッシュ・マージ・削除のような重大な操作以外は確認プロンプトをスキップする設定も入れています。計画承認というチェックポイントを1箇所に集約する代わりに、軽微な操作の確認は減らすという役割分担です。


開発速度: 「意図」だけ言えば「型」で動く

このプロジェクトでは、繰り返し発生する定型作業をスキル化し、AIが自然文の意図から適切なスキルを自動選択して実行する運用にしています。

代表例が create-pr スキルです。git push の後に必要な「PR本文の作成」「AIレビュー」「Slack下書き作成」の3タスクは、従来は逐次実行すると30分以上かかっていました。これを並列で走らせ、投稿だけを順次行うようにしたことで、待ち時間を短縮しています。

Code
/create-pr

このコマンド1つで、PR作成・AIレビュー・Slack下書きの3タスクが同時に走ります。

スキルをどれだけ増やしても、AIが毎回「MCPを直接叩くか、スキル経由にするか」を迷っていては意味がありません。そこで workflow.mdc にスキルファースト原則を宣言し、スキルが存在する場合はMCPの直接呼び出しよりもスキル経由を優先するルールにしています。ユーザーは「PR作成して」「議事録まとめて」といった意図だけを伝えれば、AIが /create-pr/manage-minutes を自動的に選ぶ形です。

もう一つの柱が自動メモリシステムです。「前回も言ったのに」を無くすため、ユーザーからのフィードバックを memory/*.md に保存し、次のセッションで自動的に参照させています。たとえば「Slackはテキストの氏名ではなくSlack IDでメンションして」という指摘は、一度伝えればフィードバックとして永続化され、以降のセッションで自動的に反映されます。何をチームで共有し、何を個人設定に留めるかは、都度チームで相談しながら決めています。

バックエンドとフロントエンドの型の乖離を防ぐ gen:api も効果が大きい仕組みです。OpenAPI定義(docs/api/openapi.yaml)から pnpm gen:api を実行するとTypeScriptの型が生成され、フロントエンドの型を手書きする必要がなくなります。スキーマを唯一の真実とすることで、バックエンドとフロントエンドの間の情報共有も最適化されます。

このほか、開発速度に貢献している仕組みは次の通りです。

No.仕組み概要
02manage-minutes議事録の取得・解析・Issue反映・Slack周知を自動化
05タスク種別ルールのオンデマンドロードフロント/バックエンド/インフラのルールを作業対象に応じて自動ロード
07PostToolUseフックpush後にPR作成をリマインドし、作成漏れを防ぐ
09MCP統合(GitHub・Backlog・Figma)ブラウザを行き来せず、AIがデータを直接取得
10docs:catalog既存の atoms コンポーネントを一覧化し、重複実装を防ぐ
11fetch-minutes + analyze-minutes議事録の自動取得と、既存Issueとの差分検出
12確認スキップの記憶git addgh pr edit など軽微な操作は確認なしで進める設定を記憶

セキュリティ: 事故を「起きない」構造にする

AIエージェントは、意図せず危険なコマンドを実行してしまう可能性があります。このプロジェクトでは、フックによる挙動レベルの制御と、ルールファイルによる宣言的な制御を二重に組み合わせています。

もっとも重要な仕組みが data-transfer-guard.py です。PreToolUseフックとして動作し、rclone / scp / rsync / aws s3 といったデータ持ち出し系のBashコマンドを実行前に捕捉します。

Code
S3

という指示に対して、実行前に data-transfer-guard.py が発火し、対象コマンドを検出したうえで承認を要求する仕組みです。settings.json 側でもコマンドを deny(削除を伴う操作は即拒否)と ask(コピー系は承認待ち)に分類しており、フックと設定ファイルの両方で多層的に防御しています。

アクセス権限は shared / local / user-global の3層に分けたパーミッションモデルを採用し、チーム共有のデフォルトは読み取り専用にしています。書き込みが必要な操作は意識的に個別付与する形で、事故発生時の影響範囲を最小化する狙いです。加えて ~/.aws~/.ssh.venvnode_modules といった認証情報や依存パッケージを含むディレクトリは settings.jsonpermissions.deny でデフォルト読み取り拒否にしています。

これらのフックや設定でカバーしきれない部分は、security.mdc にAIへの強制ルールとして宣言しています。ハードコードされたシークレットの禁止、最小権限のIAM、パーティションプルーニングといった方針を明文化し、実装がこの方針に反する場合はAI自身が実装を止め、Secrets Manager経由の代替案を提案するようにしています。

CI側では pip-audit を組み込み、依存ライブラリの脆弱性をPR作成時に自動検知してPRコメントに要約を出す運用にしています。レビュアーが別ツールを開く必要がなく、チェック自体にほとんど時間もかかりません。

Project v2 のような bulk API を使った一括更新では、既存データを全消ししてしまうリスクがあります。この対策として、既存IDを付けて投入したうえで、まず1件で dry-run 的に検証してから承認を経て全件展開する、という段階的な運用にしています。

このほかのセキュリティ関連の仕組みは次の通りです。

No.仕組み概要
06シークレットの会話貼付防止トークンは ! コマンド経由でローカル取得し、チャット履歴に残さない
07settings.local.json の gitignore個人のMCPトークンや拡張許可が誤ってコミットされない設計
09GitHub書き込み直前の再確認「計画の承認」と「書き込みの承認」を区別し、gh issue edit 等の実行直前に再確認
10branch-source-guard.ymlmain へのマージ元を develop / staging に限定
12ai-review のセキュリティチェックリスト全PRのAIレビューにハードコードシークレット・権限過多などの検出項目を必須化

品質: 仕様書とテストをCIで強制する

AIレビューは便利ですが、レビュー内容を人間が確認しないまま承認する「ノールックPR」が起きると意味がありません。このプロジェクトでは、仕様書とテストの存在自体をCIで強制するアプローチを取っています。

spec-guard.sh は、pages や Lambda を変更した際に対応する仕様書の更新をCIで強制する仕組みです。仕様書を更新せずにPRを出すと、CIが spec-guard: 対応する仕様書が未更新です として失敗します。同様に test-guard.sh は、新規のソースファイルに対応するテストファイルの存在を強制し、AIが生成したコードであってもテストなしでは通過できないようにしています。

AIレビューについては、指摘事項に Must(必ず直す) / Should(直すべき) / Nice(できれば) の3段階の優先度を付けています。すべての指摘を「全部直せ」と扱うのではなく、急いでいるときは Nice を保留するといった判断がしやすくなり、レビューが人にもAIにも扱いやすい形になりました。レビュー観点も UI / API / Data / Infra の4軸と組み合わせたマトリクスにして、レビュー品質が担当者による差になりにくいようにしています。

仕様やコーディング規約が複数のドキュメントに分散すると、内容が食い違ったり陳腐化したりします。このプロジェクトでは engineering-standards.md を規約の単一正本とし、命名規則などの規約はここに集約したうえで、Lambda個別のMDファイルなどからはこのファイルを参照する構成にしています。カバレッジについては API側で90%、Web側でも80〜85%の閾値をCIで強制していますが、外部モックの作成コストを踏まえ、100%を必須にはしていません。

API とフロントエンドの型の乖離は gen:api で防いでいますが、実装とOpenAPI定義そのものの乖離は openapi-check というCIで検出しています。Lambdaハンドラのレスポンスにフィールドを追加してもスキーマ側を更新し忘れると、openapi-check: 実装とOpenAPIが不一致 としてCIが失敗する仕組みです。

UI変更の影響範囲を人が都度確認するのは負荷が高いため、Playwrightによる E2E テストではゴールデンパスとなる主要フローに絞って自動検証しています。すべてのパスを網羅しようとすると実行時間が長くなり、本質的でない検証にコストがかかってしまうため、範囲を絞る判断をしています。

このほかの品質関連の仕組みは次の通りです。

No.仕組み概要
05仕様書の必須章を宣言page-specs.mdc / lambda-specs.mdc が Overview・Routes・Tests など必須章を宣言し、漏れをAIが自己チェック
06.mdc ルールのバージョン管理AIへの指示をコード同様にPRで差分レビュー
08PRテンプレのAIレビュー欄必須化AIレビューコメントの投稿漏れをテンプレート構造で防止
10docs/testing/ のテストマトリクス外部I/Fの破壊的変更がどのテストに影響するかを記録し、AIが影響範囲を判定
11build-pr-quality-comment.shカバレッジ・監査サマリーをPR上部にsticky表示
12architecture.mdcatoms/features/layouts の3層でレイヤー責務を制約し、atomsへの直接スタイル上書きを禁止
13_common.mdLambda仕様書の共通セクションをDRY化
14ai-review --pre-prPR作成前にローカルdiffをレビューし、指摘を反映してからPRを作成

運用で意識したこと

すべてを画一的なルールで縛ろうとすると、かえって窮屈になります。たとえば思考の深さ(モデルの reasoning effort)やウェブ検索の可否といった個人の好みが関わる設定は、チーム全体で縛らず個人ごとの settings.local.json での上書きを許容しています。何をチームルールにして、何を個人設定に委ねるかは、定例などの場で相談しながら決めていく必要があります。

AIレビューについても、GitHubにPRを出してからレビューを待つと、レビューを受けて修正し、また待つというタイムラグが発生します。このプロジェクトでは ai-review をローカルで完結させ、セキュリティチェックリストを含めて指摘を直してからプッシュする流れにすることで、このタイムラグを減らしています。

スキル自体の数は、増えすぎるとかえって扱いにくくなるため、チームで共有したいものだけをリポジトリに置き、個人的に使うだけのものはホームディレクトリ側で管理するという運用にしています。


まとめ

ここで紹介した仕組みは、次の3つのパターンに集約できます。

  1. スキル/コマンド化: 「意図」だけ言えば「型」で動くようにする
  2. フック/CIによる構造的強制: 人の記憶に頼らず、仕組みで事故を防ぐ
  3. 仕様書・メモリによる単一の真実: 情報の乖離と再説明をゼロにする

AIに「気をつけてもらう」のではなく、間違えられない構造をつくる。この考え方は、AIコーディングエージェントを本格的に開発フローへ組み込むほど重要になっていくはずです。

社内では、これらの仕組みを継続的に見直しながら改善を進めています。AI駆動開発の体制構築についてご関心があれば、お気軽にKDDIアイレットへご相談ください。