🧭

1年半かけて育ててきたAI開発フロー

に公開1件

はじめに

去年からClaude Codeを実務に取り入れて、いろいろと試してきました。

以前、サブエージェントで「思考をレビューする」開発フローを組んだ話を書きましたが、あれから数か月経ち、形がかなり変わりました。
https://zenn.dev/sprix_it/articles/9d7519eb249681

前提として、私の考えとしては、
AI駆動開発の手法に良し悪しや正解はなく、人それぞれ・好みによるものだと思っています。
自身が使い慣れた手法をベースに、自分のやりたいフローを想いのままに強化し、
他の人がやっている良さそうな手法や、新しく見つけた機能を肉付けしていく。
それが良いと思っています。
私のフローもそうやって育ててきました。

この記事では、今の私のフローがどういう仕組みで動いていて、なぜそうしたのかを書きます。

前回のようにエージェント定義の全文は載せません。
私の開発スタイルと業務形態に合わせて作ったものなので、そのまま配布しても万人の需要にはマッチしないと思うからです。
仕組みと考え方を共有するので、参考にできそうな部分があれば、必要なところだけご自身の環境に合わせて取り込んでみてください。
(あとできたらいいねもください、もらえたら執筆意欲が湧くので。)

前回から何が変わったか

前述の記事で紹介したフローは、仕様を作ったら人間がレビューし、実装したらまた人間がレビューする、という形でした。

AIが勘違いしたまま大量に実装するのを防ぐために、途中で「思考」を見せてもらう。
この仕組みはかなりうまく機能していました。

ただ、開発スピードはそこまで上がりませんでした。

仕様を確認し、コードを確認し、レビュー指摘への対応を決め、続きを指示する。
この間、人間はちょこちょこ呼び戻されます。
とはいえ会議や別の作業もあるので、つきっきりで画面を見ているわけにもいきません。

実装そのものはAIのおかげで速くなっているはずなのに、AIが私の確認待ちで止まっている時間の方が長かったのです。

そのため私は、
人間の介入負荷をもっと減らせないかな。
と思うようになりました。

人間が関わる場所を極力減らし、AIだけで回せるように組み直したのが今の形です。

私の環境と、目指したもの

普段は、

  • 新規プロジェクトを企画から開発までやる
  • 複雑なドメイン知識が必要な既存プロジェクトも触る
  • 私が関わるプロジェクトでは、仕様ドキュメントを長く保守する運用はあまりしていない
  • 開発スピードも求められる

という環境で開発しています。

そんな中で目指したのが、

人間と仕様を合意したら、本当に人間の判断が必要になるまでAIだけで進められる状態

です。

今は、人間が判断する場所を基本的に「仕様を決める時」と「最後に出す時」の2箇所にしています。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 仕様ループ(人間と並走)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 人間が要件や構成を伝える
   ↓
 要件分析        ← 足りない情報はAIが人間に質問
   ↓
 仕様設計
   ↓
 仕様ドキュメント
   ↓
 AIによるレビュー
   ↓
 仕様サマリを人間が確認・承認          ★人間の判断
   ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 実装ループ(AIだけで進む)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 テスト設計
   ↓
 タスク分割
   ↓
 実装 → テスト → レビュー → 修正
   ↓
 動作確認
   ↓
 完了報告
   ↓
 人間が確認(後回し事項の処理・PRの許可) ★人間の判断
   ↓
 PullRequest 作成

レビューやテストを減らしたわけではありません。むしろAIに自走させる分、AI側の確認工程は増えています。

変えたのは、

人間がその都度判断していたことを、AIが判断できるルールに置き換えたこと

です。

AIの指揮系統

先述の各工程は、要件分析・仕様設計・仕様ドキュメント作成・テスト設計・タスク分割・実装・レビュー・動作確認と、
役割ごとに分けたClaude Codeのサブエージェントが担当しています。

それらを呼び出しているのが、メインチャットのClaude Code本体です。
この記事ではメインエージェントと呼びます。

サブエージェントは、渡された仕事をして完了報告を返すだけです。
自分で次の工程を呼んだり、実装ループでは人間に確認したりはしません。
報告を受け取って、次に何を呼ぶか、指摘をどう扱うか、止まるかどうかを決めるのは、すべてメインエージェントです。

工程ごとにサブエージェントへ分けているのは、メインチャットのコンテキストを汚染したくないからです。

要件分析の質疑や既存コードの調査ログまで残したまま実装に入ると、関係のない情報まで判断材料になってしまいます。
実際、余計な文脈に引っ張られてほしくない場面が結構あります。

サブエージェントは会話の履歴を引き継がず、独立したコンテキストウィンドウで動くので、各工程で必要なことだけに集中させられます。
メインエージェント側にも判断に必要な情報だけを残せるので、今はこの形にしています。

余談:モデルの使い分け

モデルも全部同じにはしていません。

要件分析や仕様設計、レビュー結果の判断など、間違えた時に下流への影響が大きいところほど強いモデルを使い、転記や機械的な作業は軽いモデルへ寄せています。
コードを書く量が多いところに強いモデルを使うというより、判断の重いところに使うイメージです。

メインエージェントが判断を担い、手を動かすサブエージェントは軽いモデルで回す。
トークンの消費を抑えつつ、品質は上流とメインエージェントで担保する、という考え方です。

仕様ドキュメント:AIが判断するための材料

人間が途中で判断しないなら、代わりにAIが判断する材料が要ります。
それが仕様ドキュメントです。

ただし、仕様を長期的なsource of truthとして保守するタイプの仕様駆動開発(SDD)とは違い、長く保守はしません。
1タスクの間だけ、後続のサブエージェントが全員同じ基準で判断するためのものとして使っています。

要件ごとに「この入力なら、この結果」という受入条件を書き、テスト設計も実装も動作確認も、その受入条件を基準にします。
分からないことがあっても「たぶんこうだろう」で補完はさせず、仕様に戻します。
仕様ドキュメントがあり、受入条件がはっきりしていれば、AIはそこからテストケースを起こしやすくなります。

余談:以前、仕様ドキュメントなしでAIにテストコードを書かせたら、仕様をほとんど検証していないテストが出てきました。
(貴重なトークンを使ってゴミを生産してしまったわけです。)
当時はAIが読める材料が実コードしかなく、「何が満たされれば合格か」がどこにもなかったからだと思います。
この手法を始めてからは、(モデルの賢さが上がったのもあると思いますが)かなり改善しました。

そのため、仕様を作る段階は一番手をかけています。
既存プロジェクト改修の場合は、設計判断を実コードで裏取りし、変更がどこに影響するか確認させる。
上流でAIが勘違いすると、その後をどれだけ丁寧に進めても全部ズレてしまうためです。

レビューについて

思想としては、
レビュアーを完璧にするのではなく、レビュー結果をどう扱うかを決めておく
という感じです。

実装が終わるたびに、メインエージェントが品質レビューとセキュリティレビューのサブエージェント2体を並行で呼び出します。
2体は指摘結果をメインエージェントに返すだけで、自分では直しませんし、人間にも聞きません。

レビュー指摘をそのまま全部直すわけではありません。
メインエージェントがレビュー結果を受け取って統合し、どう扱うかを決定します。

サブエージェントが返すレビュー結果には、

  • どの仕様に反しているのか
  • どのルールに反しているのか
  • 実コード上、どこで問題が起きるのか

といった根拠を含めさせています。

そのうえで、メインエージェントは受け取った指摘を、

  • 根拠があり、直してよいものは修正
  • 軽微なものは記録して後回し
  • 根拠のないものは提案扱い
  • 仕様変更が必要なら止める

という、先に決めたルールで振り分けます。
(重要度の高い指摘だけは、振り分ける前にメインエージェントが実コードを読み、指摘どおりの経路で本当に問題が起きるのかを確かめるフローを挟んでいます。)

「AIにやらせないこと」を決める

自走させるうえで大事なのが、範囲外を触らせないことです。

AIは、

ここも直した方が良さそう

というものを見つけ、範囲外へ変更を広げることがあります。
それを許してしまうと、変更範囲がどんどん広がっていきます。

そのため、範囲外のリファクタやバグ修正は禁止。
気付いたものは記録だけ、というルールを決めました。

記録したものは、最後にまとめて処理します。

  • 今直す
  • 別で起票する
  • ルールに反映する
  • 捨てる

記録するだけだと二度と見ないので、処理まででワンセットです。

止まる条件を決める

実装ループに入った後は、基本的に人間へ質問しません。
その代わり、止まる条件を明確に決めておく必要があります。

たとえば私の場合は、

  • 仕様自体に問題がある
  • 同じ問題を何度直しても解消しない
  • 仕様にない依存追加が必要になった
  • 仕様から判断できないことが出てきた
  • 危険な操作をしようとする

といった場合に止めるようにしています。

意識しているのは、「難しそうなら止まる」のような主観的な条件にしないことです。
主観にすると、同じような変更でも止まったり止まらなかったりするし、モデルによって判断がぶれやすく、再現性がないためです。
「何回失敗したら止まる」「この種類の変更が必要なら止まる」のように、なるべく機械的に判定できる形を指定しています。
(ファイル削除やDBの破壊的操作などの危険な操作は、AIの判断基準とは別にClaude Codeのhookでも止めています。)

まとめ

このフローを作っていく中で、一番大事だったのは、

AIをもっと賢くするというより、人間の判断基準をAIが使える形にしていくことでした。

どこまで触っていいのか、何をもって正しいとするのか、どんな時に止まるのか。
人間ならその場で判断できることも、AIに任せようとすると、ちゃんとルールにして渡す必要があります。

そのために、今まで自分がなんとなく判断していたことを、AIでも判断できる形まで言葉にすることが、一番効きました。

おわりに

冒頭にも書いたとおり、手法に良し悪しはなく、人によると思います。

皆さんも自分の思い描く最強のフローを信じ、試行錯誤しながら強化していってください!
なんてったって自分の使う開発環境なんですから!

今回紹介した私のフローの中でも、
もし参考にできそうな部分があれば、ぜひご自身の環境に取り込んでいただけると嬉しいです!

最後まで読んでいただき、ありがとうございました!

株式会社スプリックス IT戦略部・SPRIX Enginieering Lab

Discussion