はじめに
こんにちは。CADDi Quoteのサーバーサイドの開発を担当しています、majimacchoです。私たちのチームでは全員がAIエージェントを活用して実装しPR作成まで行なっています。
私自身を含め、全く自分でコードを書かなくなったメンバーもいます。AIエージェントを使ってから個人のアウトプットは大きく増えましたが、その分AIのマネジメント(お世話)の負荷が高まっていました。
今回紹介するUsecase Design Docと呼ばれるドキュメントと関連する施策を通して、このAIのお世話の負荷を軽減しました。またそれに付随して1日にマージできるPRの数は2倍になっています。
この記事では、AIエージェントを利用した開発で増大するAIのお世話の負荷をどう軽減したかを、具体的な開発プロセスと合わせてお伝えします。
何が辛かったのか
私は大きく以下の3つのことが辛いと感じていました。
- 毎回詳細なプロンプトを書くのが辛い
- AIエージェントのタスク完了まで面倒を見るのが辛い
- これらを並列で実行しているのが辛い
毎回詳細なプロンプトを書くのが辛い
AIが実装を行う際に「OOを実装して」のような曖昧な指示では期待通りのコードを作成してくれません。1つのPRを作成するのに、かなり多くの説明をしなければいけないことに負担を感じていました。AIしか読まない詳細な文書を書くことに虚無感すら覚えていました。様々なツールやスキルによって、ある程度個々の負担は軽減できますが、それでもAIのための指示を、その都度、正確にしなければいけませんでした。
AIエージェントのタスク完了まで面倒を見るのが辛い
最近のAIエージェントは十分賢くなったので、全ての挙動を見張る必要はなくなりました。 しかし、特にClaude Codeを利用している場合は、プランを確認したり、ツールの利用を許可したりするところで、まだ人間の操作を必要としています。 PR作成後もそのまま受け入れられる品質の時は良いですが、修正が必要な場合、何度もやり取りが発生したり、場合によってはセッションをクリアする必要があります。
これらを並列で実行しているのが辛い
上記の問題は、直列で作業している時には大きくなかったのですが、並列で仕事をするようになってから顕著になってきました。
特に、1人で同時に5つ以上のタスクをAIエージェントと実装するようになってからは、認知負荷が顕著に上がってしまいました。
AIコーディング以前は並列で作業することが間違っているという考え方が主流だったと思います。しかし、AIエージェントを待っている間に別のエージェントを動かさないと機会損失しているような感覚があり、ほとんどの時間に、AIを並列稼働させています。
ローカルでGit Worktreeを管理する必要も出てきたり、開発サーバーのポートが競合することもあります。手動でmainブランチをマージするのを忘れて、何度もコンフリクトを起こしました。
コンテキストスイッチも大きくなり一時期は並列数を3つまでに制限することもありました。
解決方針
上述の課題を以下の方針で解決しました。
- 詳細な設計ドキュメントの作り込み
- 細かい実装指示・計画・実行をAIエージェントに委譲
詳細な設計ドキュメントの作り込み
今回重要だったことは、細かい指示を出さなくても、AIエージェントが質の高いアウトプットを出せることです。 試行錯誤する中で、Usecase Design Docという形でより細かい設計内容をまとめることで、AIエージェントのアウトプットの質が高められることがわかりました。
Usecase Design Doc
以前はユースケースレベルの設計はPRのDescriptionやホワイトボードツールに散在しており、各開発者の暗黙知に依存していました。これを明文化することで、AIにとっての実装のエントリーポイントになると同時に、レビュー時の照合基準としても機能しています。
このドキュメントには、ユースケースシナリオに閉じた設計を記載します。具体的には以下の内容を含んでいます。
- サマリー(アクター・操作対象・操作内容の定義)
- 関連テーブルのCRUD表
- シーケンス図(トランザクション境界を含む)
- 主要なドメインエンティティのインターフェース(型定義・ファクトリメソッド)
- 関連するAPIインターフェース(API仕様書から抜粋)
- 既存コードへの変更箇所(レイヤーごと)
- 実装状況チェックリスト(集約単位・レイヤー単位)
以下は架空のユースケースを例にしたUsecase Design Docのサンプルです。実際のプロダクトのものではありませんが、記述の粒度やフォーマットは実際に使用しているものと同等です。ただし、サンプル内のユースケース・設計・コーディング規約は実際のものとは異なります。
# EX-a1: ユーザーはお気に入り商品をブックマークする ## サマリー - ログインユーザーが商品に対して、ブックマーク(お気に入り登録)を行う ## 関連のテーブル | テーブル | 操作 | 操作内容 | | :--- | :---: | :--- | | Product | R | ブックマーク対象の商品が存在することを確認する | | Bookmark | CR | ブックマークの存在確認(R)、新規作成(C) | | BookmarkCount | U | 商品のブックマーク数を +1 更新する | ## シーケンス図 ```mermaid sequenceDiagram autonumber actor User as ログインユーザー participant API as Product API<br/>[REST] participant DB as App DB<br/>[PostgreSQL] User->>API: POST /products/{productId}/bookmarks API->>DB: 商品の存在確認 alt 商品が存在しない API-->>User: 404 Not Found else 商品が存在する API->>DB: 既存ブックマークの確認 alt 既にブックマーク済み API-->>User: 409 Conflict else 未ブックマーク rect rgba(100, 150, 255, 0.15) Note over API,DB: トランザクション API->>DB: Bookmarkを保存 API->>DB: BookmarkCountを+1更新 end API-->>User: 201 Created end end ``` ## 主要なドメインエンティティのインターフェース > 実際のドキュメントではここにエンティティの型定義とファクトリメソッドを記載します。 > 例: `type Bookmark = Readonly<{ id: BookmarkId; userId: UserId; productId: ProductId; ... }>` > 例: `const Bookmark = { create: (...) => Bookmark, ... }` ## APIインターフェース > 実際のドキュメントではここにAPIのパスパラメータ・リクエストボディ・レスポンスの定義をテーブル形式で記載します。 > 例: パスパラメータ `productId: string`、レスポンス `201 Created / 404 Not Found / 409 Conflict` ## 既存コードの変更 > 実際のドキュメントではここにドメイン・ユースケース・インフラストラクチャ・プレゼンテーション等のレイヤーごとに、変更対象のファイルパスと変更内容をテーブル形式で記載します。 ## 実装状況 - [ ] 同期処理 - [ ] Bookmark 集約 - [ ] ドメインの実装 - [ ] ユースケースの実装 - [ ] プレゼンテーションの実装
細かい実装指示・計画・実行をAIエージェントに委譲
今までの開発ではAIエージェントに実装させる中でも、以下のようなタスクのために、AIエージェントとローカル環境に注意を向けなければいけませんでした。
- 最初のプロンプトの入力
- コンテキストがいっぱいになった時のセッションマネジメント
- Toolの利用の許可
今回は、これらに注意を払わずに、設計とPRレビューに集中するプロセスを構築しました。
Usecase Design Docの内容を元にユースケースシナリオごとに実装タスクを計画します。
タスクの分割方針
ユースケース全てを1つのPRで実装するには大きすぎるため、基本的には以下の軸で分割します。
- レイヤー単位(Presentation / Domain / Application)
- DDDの集約単位
- 同期・非同期の処理単位
この分割の基準は先ほどのUsecase Design Docのテンプレートに含まれています。 各PRは200〜300行の変更に収まることを目安にしています。この分割により、PR1件あたりの情報量が制限されます。さらに、レビュアーが把握すべき知識の範囲もレイヤーや集約の境界内に限定されます。
AIエージェントへの実装委譲
タスク分割が完了したら、以下の流れでAIエージェントに実装を委譲します。
- Usecase Design Docの実装状況の欄のうち、未実装の項目の一番上を実施タスクとする
- Devin Searchで関連コード・ドキュメントを収集: タスクを指定して、Usecase Design Docと関連する既存コードをDevinに読み込ませる
- DevinでPR作成まで実行: タスク定義に基づいてDevinが実装し、PRを作成する
- CIのDevin Reviewで自動レビュー: 作成されたPRに対してCI上でDevinによる自動レビューが走る
設計ドキュメントが十分に詳細化されていれば、この一連の流れに人間が介入する必要はありません。お昼前にタスクを投入し、出来上がったPRを午後にレビューするという非同期な作業サイクルが成立します。
AIのお世話からの解放 - 得られた成果
従来のような並列でAIのタスクとセッションを管理しなければいけないような環境から脱却し、心には平穏が訪れました。 心理的、認知的に楽になっただけではなく、業務上も以下の成果が得られました。
開発速度の向上
従来のAIを活用した開発と比較して 1日にマージされるPRの数が2倍になっています。
これはAIエージェントが人間を待たずに作業ができるようになったことと、アウトプットの質が上がって手戻りが減ったことによるものです。
また、今までAIエージェントへのプロンプトやセッション管理を通じた直接的なマネジメントから、AIエージェントの環境整備を行なって、セッション横断で効果のある施作に時間が割けている事もその要因の1つです。
さらに、並列数の上限も特になくなり、その日のPRレビューに割ける時間から逆算して実装タスクの数を決めるようになりました。
PRレビュー自体の認知負荷の軽減
詳細な設計ドキュメントがPRレビュー時にあることで、PRの内容をすぐに理解できるようになりました。今まではなんとなく頭にあった情報を思い出してレビューしていました。今は詳細な設計ドキュメントと照らし合わせながらレビューしているのでレビュー時のコンテキストスイッチによる負荷も小さくなっていると感じています。
現在直面している課題
設計書の細かい誤りの増幅
今回、主要なインターフェースの設計もAIに書かせていましたが、軽微な間違いを含んだまま実装フェーズに進み、そのままPR作成まで行われるケースがありました。一見些細なインターフェースの誤りでも、実装を通じて増幅され、結果として大きなズレにつながります。開発者が実装に伴走していれば、PR作成前の段階で気づけていたはずですが、今回のプロセスではPR作成後に初めて問題が表面化しました。設計ドキュメント自体のレビュー精度を高めるか、実装の途中段階でフィードバックを得る仕組みを整えることが今後の課題です。
設計とPRレビューのボトルネック化
よく言われていることではありますが、実装速度が上がったことで、その前後の設計とPRレビューの速度が開発スピード全体を決めるようになりました。
特に設計は、AIに手放しで任せるのは難しい領域が大きく、まだまだ時間がかかってしまうところです。
PRレビューについてはハーネスエンジニアリング*1によって不要になるという論調もありますが、本番環境で、お客様が利用しているサービスにPRレビューなしでマージするには課題が多いのも現状です。
まとめ
AIエージェントに指示を出す前の段階で実装内容が自明になることで、AIエージェントの管理工数を削減し、開発者の認知負荷を軽減することができました。 この取り組みを通して確認できたことは、実装時にAIエージェントに指示内容を考えるよりも、設計時点で詳細な実装までイメージできるようなドキュメントを作成した方が効率が良いことです。 この設計ドキュメントを、どれだけ正確に無駄なく作れるかということが開発速度と品質を左右します。
AIエージェント自体をどれだけうまく活用するかということも現時点では重要ですが、それらはツール側の成熟によって自然と解決していきます。一方で設計はまだまだ人間が考えるべきところが多く残されていると思います。
もしチームで試すなら、最小限の構成としてUsecase Design Docの整備から始めることをおすすめします。ユースケースごとにサマリー・シーケンス図・実装状況チェックリストをまとめたドキュメントを1つ作り、それをコードベースの特徴に合わせて分割した上でAIエージェントに渡して実装させてみてください。設計の曖昧さがどこにあるかがすぐにわかり、改善サイクルが回り始めます。
このプロジェクトは、まだ進行中で試行錯誤しているところも多分にあります。プロジェクト完了後にふりかえり記事を出してその時に答え合わせをしようと思っています。