👌

Devin で70個の API を OpenAPI Specification で定義し、 1週間で API First な開発へと移行した

に公開

ホットなAIエージェントであるDevinを使って、フロントがバックエンドのコードをある程度見ながら実装する従来型の開発から、OpenAPI Specification(以下OAS)をベースにした API First の開発体制に移行しました。

長年課題とは認識していたものの、限られた開発リソースの中ではなかなか着手できずにいました。

しかし、Devinに効果的なプロンプトを与え、複数Devinを並行で稼働させることで、1週間ほどで実現することができました。

そこで今回は

- API Firstに切り替えたことによる開発の変化
- それを実現させたDevinでの移行プロンプト
- Devinを使う上でのTips

をご紹介していきます。

本記事で扱わないこと

本記事では下記の点については扱わないこととします。

- OAS プロジェクトの具体的な構造
- sdk を生成して Schema 駆動にする話

oasの色が強く、本記事が取り上げる「Devinによる開発スタイルの移行」というスコープからは外れているためになります。

そのため、上記の観点は別の機会で取り上げます。

開発チームが抱えていた課題

API First への移行を決断した背景には、大きく分けて「稼働スタイルの非同期性に起因する開発効率の低下」と「技術的な一貫性・保守性の欠如」、「将来的な採用のハードル」という3つの課題がありました。

稼働スタイルの課題

私たちのチームは、フリーランスを中心とした非同期型の開発体制を採っています。

そのため、フロントエンド実装のタイミングでバックエンドが不在、という状況が珍しくありません。結果として、APIの実装待ちや仕様確認のためのコミュニケーションがボトルネックとなり、開発のスループットが大きく損なわれていました。

また、仕様に関するやりとりが都度発生するため、実装の並列性が低く、特定のメンバーの稼働状況に開発速度が強く依存する状態となっていました。

技術的な一貫性・保守性の欠如

2つ目は技術的な一貫性・保守性の欠如です。

まず、チーム内のメンバー交代が頻繁に起こることで、エラーハンドリングの粒度や、フロントでは使用されないレスポンスフィールドの扱いなどに、実装者ごとの個性が入り込みやすい状況でした。

レビューでその点を見逃してしまうと、結果として統一されていない仕様が点在していくことになります。

加えて、明確なスキーマ定義が存在しないことによる、オプショナルチェーンの多発も課題としてありました。

型の不確かさがコード全体に不安定さを与えており、request/response の構造や責務が曖昧なケースでは、フロントエンド側での実装判断が属人的になりやすく、保守性や品質に課題が残りました。

将来的な採用ハードル

また、数年前と比べて、少なくとも私の周りでは Rails のリーディングスキルを持つフロントエンドエンジニアが減少している印象を持っています。

あるいは新しく生まれてこない、という言い方が正しいかもしれません。

近いうちに「Railsが読めること」が必須な環境だと、採用ハードルが高くなっていく、というのは可能性の1つとしてあり得ます。

そのため、バックエンドの内部実装に依存しない形で仕様を把握・合意できる環境の整備は急務だと判断しました。

API First に切り替えた結果

API First への移行によって、想定していた以上に多くの副次的なメリットが生まれました。

特に、開発スピード・実装品質・人員構成の柔軟性といった観点で顕著な改善が得られています。

実装の独立性と並列度の向上

OASを基点に仕様を先行定義することで、フロントエンドとバックエンドの関心を完全に分離できるようになりました。

従来は「バックエンド実装を見ながら組み立てる」スタイルでしたが、今では OAS をもとにフロントが mock server を立ち上げて開発を進められるため、APIの「実装待ち」という状態がほぼゼロになっています。

結果として、開発の並列度が飛躍的に向上しました。

複数のエンジニアが独立して開発を進められるようになったことで、スループットの安定化に大きく寄与しています。

実装の均質化とレビュアビリティの向上

私たちが定義したOASプロジェクトでは構造上、レスポンスやリクエストの構造を最小単位として定義した component 群を $ref することで共通化していきます。

その結果、実装者ごとの独自定義や“我流”が自然と排除される仕組みになっています。

そしてリソース単位、あるいはマイクロサービスの境界として適切なドメイン単位で、一貫性のある API 仕様が保たれやすくなり、コードレビュー時にも「定義に基づいているか?」を機械的に確認できるようになりました。

実装フェーズよりも、OAS を構成する段階で設計的な違和感に気づけるため、仕様段階での修正が効率的に行えるのも大きな利点です。

人員の流動性に対する耐性強化

フロントエンド開発において、バックエンドの内部実装を直接読み解く必要がなくなったことも大きな成果のひとつです。

Rails に不慣れなメンバーが参画しても、OAS を見れば必要な request/response の仕様が読み取れるため、最小限のオンボーディングで開発に参加できます。

もちろん、完全に依存を断つことは難しく、つなぎ込みや仕様補足のためにコードを読む必要は残りますが、「コードを読めなくても合意形成ができる」状態があることで、リスクが分散されました。

フロントエンドの実装簡略化

明確な型定義とドキュメントが先行して存在することで、フロントエンド側のオプショナルチェーンなどの防御的な実装が大幅に削減できます。

API レスポンスの構造と意味合いを開発初期から共有できるようになったことで、エラーケースや例外パスに対する設計も事前に議論・合意できるようになり、全体の品質が底上げされています。

Devin で精度よく API First に移行させるプロンプト

Devin を活用して OAS を構築していくうえで、現時点で最も重要なのは「プロンプトの設計」です。

「現時点で」というのは近いうちにプロンプトの品質が問題にならなくなっていく、と予測しているからなのですが、少なくとも今はプロンプトの質が作業精度・作業スピード・ACU コストに直結します。

そのため構造化と制約条件の定義は手を抜けません。

以下は、実際に使用しているプロンプトのテンプレート例です。

@Devin  
下記の要件を満たす実装を行なってください。

## 操作対象リポジトリ  
your_project_oas  

## 実装内容  
PATCH /v2/users/:id  
に対する OpenAPI 実装  

## 参照箇所  
your_project_api リポジトリの

・app/controllers/v2/your_controller.rb  
・spec/requests/v2/your_controller_spec.rb  
・app/serializers/v2/your_serializer.rb  

を参照して。

## 注意事項  
・5分実行して進捗が出せなければ、相談してください  
・ローカルで確認できていれば、CIの完了を待たずにレビュー依頼してください  
・README のコーディング規約および、既存構造に準拠すること  
・認証(authenticate_user!)も考慮すること  
・Pull Request には pull_request_template.md のフォーマットを用いて、日本語で実装内容・結果・検証項目を記載すること  
・私とは日本語で会話すること  

このテンプレートは「迷わせない」ことに主眼を置いて設計しています。

Devin に自由裁量を与えすぎると、文脈を外したり無駄に探索範囲が広がる傾向があるため、「明示的な制約」と「確認すべき参照元の提示」が非常に効果的です。

少しブレイクダウンします。

実装スコープは狭く切る(1リソースあたり最大3エンドポイント)

人間でも同じではあるのですが、実装スコープを狭めることで精度の向上、フィードバック時の手戻り量を減らすことができます。

PATCH /v2/users/:id
GET /v2/users/:id
DELETE /v2/users/:id

現状だとこのあたりまでが限界でした。

これを超えると Devin の解釈力が急激に低下し、精度・スピード・安定性のすべてが劣化する傾向にありました。

プロンプトの戻り結果も膨大になりやすく、フィードバックのやりとり回数も増えるため、ACU コストも跳ね上がります。

参照ファイルは明示的に提示する

Devin は必要な情報が見つからない場合、リポジトリ全体をスキャンして情報を探しにいく挙動があります。

つまり明確なファイルを指定しないと、リポジトリが大きくなるほど探索時間とコストが肥大化します。

特に、下記の3ファイルは精度に直結するため、必ず指定します。

- Controller:エンドポイントの仕様・認証処理の有無
- Serializer:response body の構造
- Request Spec:正常系・異常系の仕様パターン

この3点が適切に書かれていれば、Devin はほぼ正確に OAS に変換可能です。

逆にテストが未整備な箇所は、response の仕様も曖昧になっているため、生成される OAS もボヤけたものになりがちです。

我々人間も複雑なロジックを読み解く前に、specをみて満たすべき業務要件を確認することがありますが、Devinも同じです。

実行時間に制限を設ける

堂々巡りや無限思考ループを防ぐために、「5分で進捗がなければ相談してください」といった時間制限を設けておきます。

Devinは人間と「並行作業」させることで、開発全体の生産量を増やせるのが強みです。

自分の作業に没頭して指示したのを忘れてしまうこともあるので、報連相をお願いします。

CI 完了を待たずに PR を出させる

プロジェクトによっては CI が数分以上かかるケースが多く、Devin が「待機状態」で ACU を消費し続けることがあります。

ローカルで Lint・Test を通しているなら、レビュー待ちに入らせてOKとします。

[おまけ] Devin に並列作業させる

Devin は複数の作業を並列で作業させることができます。

同じような構成のエンドポイントを複数持っている場合、ひとつずつ順に対応していくのではなく、プロンプトを少し変えて複数の Devin にスライド的に作業させるのがいいです。

コンフリクトを最小限に抑え、人間と並行して作業させていきます。

例えば DevinAにこのような指示を出します。

PATCH /v2/users/:id に対する OpenAPI 実装を行ってください。

## 対象リポジトリ
your_project_oas

## 参照リポジトリ
your_project_api

- app/controllers/v2/users_controller.rb
- app/serializers/v2/user_serializer.rb
- spec/requests/v2/users_controller_spec.rb

※ コーディング規約と PR テンプレートを遵守してください。

この Devin A が作業を進め、fix/users-patch-oas というようなブランチで PR を作成したら次に進みます。

Devin B にこう指示します。

PATCH /v2/teams/:id に対する OpenAPI 実装を行ってください。

## 操作ブランチ
- `fix/users-patch-oas` ブランチを `fetch` し、
- そのブランチから `fix/teams-patch-oas` ブランチを `checkout` してください。

## 対象ファイル
- app/controllers/v2/teams_controller.rb
- app/serializers/v2/team_serializer.rb
- spec/requests/v2/teams_controller_spec.rb

※ PR は `fix/users-patch-oas` に向けて作成してください。

同様に Devin C, Devin D … を動かす場合も、常に直前の Devin が出したブランチを fetch し、そこから作業ブランチを切るように指示します。

OpenAPI は構造や共通定義を $ref で共有するため、複数人が同時に base ブランチに PR を出すと、schema 定義や component 周りで高確率で競合します。

この「スライド方式」によって:

  • コンフリクトを回避しながら並列化
  • 各 Devin が スムーズに OAS に拡張
  • PR レビューも段階的に可能になり、粒度が揃いやすい

といった効果があります。

Devinで移行させる際の細かい Tips

Devin を用いて OpenAPI 化などのリファクタリングを進める際には、ちょっとした工夫や運用ルールが成果に直結します。ここでは、実際に複数人で Devin を運用しながら得られた、細かい Tips をまとめます。

README は丁寧すぎるくらいに整備する

まず重要なのは、プロジェクトの構成や方針を README に明記しておくことです。

Devin はコードの構造をある程度読み解いてくれますが、ディレクトリの意味やファイルの役割を独自に解釈してしまうことも少なくありません。

特に、OpenAPI 用のファイル群が複数存在していたり、生成対象のディレクトリが明確でない場合には、誤解を生みやすくなります。

そのため、README には各ディレクトリの立ち位置や命名ルール、生成対象のスコープ、PR の出し方などを丁寧に記述しておくことが重要です。

例えば components に関しては下記のように記載します。

ドメイン単位で「これ以上分割できない、最小単位」のかたまりを定義するディレクトリです。
各ドメイン(addresses, banking, contents など)ごとにディレクトリを分けて管理します。
ファイル名は単数系とします。

人間であれば空気を読めるようなところ」こそ、明文化しておくことで Devin の挙動を安定させられます。

disable ボックスにチェックを入れる

DevinがPRを出すと、このようなコメントがつきます。

もちろんプロジェクトルールによりますが、この「Disable automatic comment and CI monitoring」にチェックを入れるという選択肢は押さえておくといいかと思います。

DevinはデフォルトでPRに対するコメントに反応してしまう = せっかく sleep しても、人間が元気よく「LGTM!」などのコメントをしてしまうと、目覚めてしまいます。

自動で反応して欲しくない場合はチェック入れておくといいです。

フィードバックが多岐に渡る場合は Cursor で手直し

Devin にフィードバックを返す際、コメントが多くなるケースでは、逐一修正を依頼するよりも、自分で一括して手直しした方が効率的な場合があります。

特に、命名揺れやコードフォーマットの統一など、全体に影響する微調整が必要な場合には、Cursor や VSCode 上で修正してから Devin に戻す運用が便利です。

うまく指示が伝わらず、誤読して修正を行われてしまうと、さらなる手戻りと無駄なACU消費が発生するためです。

Devin はあくまで補助的なツールとして、「こまかい仕上げは人間のほうが早い」と割り切ることで、全体のスピードと品質を両立できます。

バックエンドのテストは必須

Devin は OpenAPI だけを扱うわけではなく、実際のコードベース(特にバックエンドの実装)を参照して動作を把握しています。

そのため、バックエンドにテストコード(RSpec など)が整備されていることが、正確なドキュメント生成で非常に重要です。

実際、テストがあるロジックとないロジックに対して oas 生成させると、明らかに精度に差が見られました。

特に nullable や例外に対して精度の差が出ます。

バックエンドにとっても oas にとっても、テストがあることは常にメリットになるので、複雑なロジックほど事前に整備しておくことを推奨します。

もちろん、以下のように「まとめ」セクションを追加できます:

まとめ

Devinを活用することで、API First開発への移行を短期間で実現できました。

OASを起点とした開発により、実装の並列化・仕様の均質化・人材の流動性への対応、といった多くの課題への解決の糸口とすることができました。

ただし、それには

- Devinは人間と並列で稼働させて、総生産量を上げる形で効果を発揮する
- Devinが迷わないように狭いスコープ、明瞭なプロンプトで指示する
- 生成リポジトリ(OAS)のディレクトリの責務を明確にし、READMEを整える
- 参照先(バックエンド)にテストが実装されていることで、型定義の精度が上がる
- あくまでも「サポートは必要」と割り切り、人間による手直しは行う

という点を認識する必要がありました。

やることが明確で、適切に定義された構造を用意してあげれば、このように「人間がリソース上やれなかった」作業に対して、パフォーマンスを発揮してくれます。

従来型の開発スタイルに課題を持ち、移行を検討している方にとって、このアプローチが参考になれば幸いです。

Discussion