8月14日、jsdev.spaceが「A Better Vibe Coding Workflow for AI-Assisted Development」と題した記事を公開した。AIコーディングエージェントを使った開発を4段階のワークフローに分割することで、プロジェクト規模が大きくなっても破綻しにくい開発プロセスを構築する方法を詳しく紹介している。
開発中、エージェントがタスクを実行しながら静かにアーキテクチャを書き換えていた——こうした経験が積み重なって生まれたのが、この記事の提案する構造化ワークフローだ。
「Vibe Coding」とは、AIに自然言語で指示を出しながらコードを生成させる開発スタイルだ。小規模なプロジェクトでは機能するが、コンポーネントが増えて機能間の依存関係が複雑になると、AIが過去のチャット履歴で決めた設計を忘れて別の解決策を勝手に実装する、といった問題が起きやすい。根本にあるのはコンテキストウィンドウの制約だ。コンテキストウィンドウとはAIが一度に参照できるテキストの上限範囲のことで、会話が長くなるほど古い情報が「見えない」状態になる。トークン(AIがテキストを処理する際の最小単位。日本語では概ね1文字1〜2トークン)換算で数万トークンに達した会話履歴は、初期の設計判断を実質的に押し流してしまう。
この問題への対処として近年注目されているアプローチには、長期記憶をファイルに外部化するMemoryBankや、Anthropicが推奨するCLAUDE.mdによるプロジェクト横断のコンテキスト管理などがある。本記事のアプローチはこれらと方向性を共有しつつ、ステージ単位のドキュメント受け渡しという形で実装を具体化している点が特徴だ。
エージェントが静かに設計を変えたら止める
まず記事が最も強く警告しているのが、エージェントによる無断の設計変更だ。タスク実行中にエージェントが「現在の設計ではInventoryService.getItems()が必要だが、実装済みのサービスはsubscribe()しか持っていない」という問題に気づいたとする。このとき、エージェントが勝手にサービスアーキテクチャを書き換えるのは許容しない。代わりに次のような報告を出させる。
BLOCKED
Task: INV-04
Problem: 設計が要求するgetItems()が実装済みサービスに存在しない
Suggested options:
1. getItems()をサービスに追加する
2. UIの設計をsubscribeを使う形に変更する
アーキテクチャの変更は一切行っていない。
この判断を適切なステージに戻すことで、大量のコード生成後に発覚する設計の不整合を防ぐ。その場では遅く感じられるが、後工程の手直しを大幅に減らせる、というのが記事の見解だ。この「止めて報告する」という振る舞いを引き出すには、後述するConstraintsの明示が不可欠になる。
4段階に分割する
記事が提案するワークフローは次の構造だ。
Requirements(要件定義)
↓
Design(設計)
↓
Tasks(タスク分解)
↓
Implementation(実装)
各ステージがファイルを成果物として出力し、そのファイルが次のステージへの入力になる。AIエージェントは肥大化した会話履歴を参照するのではなく、具体的なドキュメントを読んで動く。これが根本的な発想の転換だ。
プロンプトの基本構造
記事では各ステージで使う共通のプロンプト構造を提示している。
## [Stage Name]
Goal: このステージで何を達成するか
Input: 読むべきファイルと情報
Output: 作成するもの、保存先
Steps: 何を、どの順番で行うか
Constraints: エージェントが勝手に変えてよいことの範囲
Completion criteria: いつ完了とみなすか
Fallback: どのタイミングで前のステージに戻るか
「認証システムを作れ」という指示では何もかもが解釈次第になる。ConstraintsとCompletion criteriaで境界を引くことが、指示を増やすよりも重要だと記事は指摘している。前述のBLOCKED報告も、Constraintsに「アーキテクチャの変更を禁止する」と明記することで初めて機能する。
タスク分解が最重要ステップ
記事が特に強調しているのがStage 3のタスク分解だ。
doc/tasks/auth.md、doc/tasks/inventory.md のようにモジュールごとにファイルを分け、全タスクを参照できるdoc/tasks/progress.mdを1つ用意する。
良いタスクの例として記事が挙げているのが以下だ。
## AUTH-02: Session Validation
Priority: P0
Depends on: AUTH-01
Goal: サーバーサイドのセッション検証を実装する
Files:
src/auth/session.ts
src/auth/types.ts
tests/auth/session.test.ts
Requirements:
- セッショントークンを受け取る
- 有効な場合は認証済みユーザーを返す
- 期限切れの場合は未認証を返す
- 内部プロバイダーエラーを露出しない
Tests:
- 有効なセッション / 期限切れ / トークン欠如 / 無効なトークン
Completion:
モジュールテストが通り、無関係なモジュールを変更していない
このドキュメントがあれば、新しいエージェントセッションが過去の長い会話履歴を読まなくても何をすべきかを把握できる。「コンテキストは削減するほど良い」というのが記事の主張だ。
タスク分解を丁寧に行う効果は、コンテキスト圧縮にとどまらない。依存関係(Depends on)を明示することで実行順序が自明になり、Completionに「無関係なモジュールを変更していない」を含めることで、エージェントの作業範囲が自動的に制限される。記事が「最重要ステップ」と位置づける理由はここにある。大量のトークンを持つ会話履歴(古い要件、ボツになったアイデア、デバッグの記録を含む)より、的確なタスクドキュメントの方が精度の高い結果を生む、と記事は明言している。
エージェントの役割分担
実装ステージでは、メインエージェントがコーディネーターとして機能し、サブエージェントに個別タスクを委譲するモデルを提案している。
Main Agent
|
+----+----+
| | |
Auth Game UI
Agent Agent Agent
| | |
Tests Tests Tests
|
Integration Check
|
progress.md
サブエージェントに渡すコンテキストはシンプルで良い。「関連する要件 + 関連する設計セクション + タスク仕様 + 必要なソースファイル」だけだ。各サブエージェントが参照するのは自分のタスクに必要な情報のみであり、プロジェクト全体の文脈を持たせる必要がない。これがコンテキストウィンドウの効率的な活用につながる。
各ステージで新しいセッションを始める
記事ではもう一つ実践的なアドバイスとして、ステージの区切りでセッションをリセットすることを推奨している。新しい会話は前の議論すべてを必要としない。前の議論が生んだ成果物(requirement.mdなど)だけを読めばよい。
セッションをまたいでも一貫性が保たれるのは、意思決定がすべてドキュメントに落とされているからだ。逆に言えば、ドキュメント化されていない判断はリセットとともに失われる。ステージリセットはその損失を許容できる単位に区切る役割も果たしている。
詳細はA Better Vibe Coding Workflow for AI-Assisted Developmentを参照していただきたい。