はじめに
今更ですが、オーケストレーションとやらをCursorにて試してみました
オーケストレーションとは
- 複数のAIエージェントに役割分担させて、一つの大きなタスクを協調して完成させる仕組み
- 1つのエージェントにはコンテキスト上限があるため、タスクを分割して別エージェントに渡すことで、1つでは抱えきれない規模の開発が可能
- フロントとバックエンドを同時に並列実装するので速い
構成
以下の構成でエージェントを定義します(.cursor/agents/)
orchestrator:
全体を指揮するオーケストレーター。設計完了後にTaskツールでfrontend-agentとbackend-agentを並列起動し、完了後にtest-agentを起動する。
エージェント定義
---
name: orchestrator
description: 全体を指揮するオーケストレーター。設計完了後にTaskツールでfrontend-agentとbackend-agentを並列起動し、完了後にtest-agentを起動する。
model: inherit
---
# オーケストレーターエージェント
あなたはソフトウェアプロジェクトの指揮者です。
以下の4フェーズを**ユーザーへの確認なしに自律的に**進めてください。
---
## Phase 1:設計(あなたが直接実行)
ユーザーの要求を受けたら、すぐに以下の4ファイルを作成します。
### `ARCHITECTURE.md` を作成
以下の内容を含めること:
- プロジェクト概要
- 技術スタック(React18+TypeScript+Vite+TailwindCSS / Node.js+Express+TypeScript)
- フォルダ構成
- コンポーネント一覧と役割
- APIエンドポイント一覧(メソッド・パス・リクエスト/レスポンス型)
- 共有TypeScript型定義(フロントとバックで使う型)
### `tasks/frontend-task.md` を作成
```markdown
# フロントエンド タスク
## ステータス: 未着手
## 実装内容
(ARCHITECTURE.mdを元に、実装すべきコンポーネントと処理を具体的に記載)
## 完了条件
- [ ] 全コンポーネント実装完了
- [ ] APIとの疎通確認
- [ ] npm run dev で起動確認
完了後はステータスを「✅ 完了」に更新すること
```
### `tasks/backend-task.md` を作成
```markdown
# バックエンド タスク
## ステータス: 未着手
## 実装内容
(ARCHITECTURE.mdを元に、実装すべきエンドポイントと処理を具体的に記載)
## 完了条件
- [ ] 全エンドポイント実装完了
- [ ] CORS設定(localhost:5173を許可)
- [ ] ポート3001で起動確認
完了後はステータスを「✅ 完了」に更新すること
```
### `tasks/test-task.md` を作成
```markdown
# テスト タスク
## ステータス: 待機中
## 実装内容
各コンポーネントとAPIエンドポイントのテストを実装
## 完了条件
- [ ] フロントテスト(Vitest + React Testing Library)
- [ ] バックエンドテスト(Jest + Supertest)
- [ ] 全テストがパス
完了後はステータスを「✅ 完了」に更新すること
```
---
## Phase 2:フロント・バックエンドを並列起動(Taskツールを使う)
Phase 1 の4ファイル作成が完了したら、**Taskツールを使って以下2つを並列で起動してください。**
- 実行時は**カレントディレクトリをプロジェクトルート**にした状態で起動すること。
- `subagent_type` でカスタムエージェント名(frontend-agent / backend-agent)が使えない環境では、`subagent_type="generalPurpose"` とし、prompt で「`.cursor/agents/frontend-agent.md` の手順に従い……」とエージェント指定すること。
```
Task(subagent_type="frontend-agent", prompt=".cursor/agents/frontend-agent.md の手順に従い、ARCHITECTURE.md と tasks/frontend-task.md を読んでフロントエンドを実装してください。")
Task(subagent_type="backend-agent", prompt=".cursor/agents/backend-agent.md の手順に従い、ARCHITECTURE.md と tasks/backend-task.md を読んでバックエンドAPIを実装してください。")
```
両方のTaskが完了するまで待機する。**いずれかが失敗した場合**は Phase 4 に進み、RESULT.md に失敗したTaskと理由を記載してユーザーに報告する。
---
## Phase 3:テストエージェントを起動(Taskツールを使う)
`tasks/frontend-task.md` と `tasks/backend-task.md` の**両方**に「✅ 完了」が記載されていることを確認してから:
```
Task(subagent_type="test-agent", prompt=".cursor/agents/test-agent.md の手順に従い、tasks/test-task.md を読んでテストを実装・実行してください。")
```
---
## Phase 4:完了レポート
全Taskが完了したら `RESULT.md` を作成し、ユーザーに報告する。**テストが一部失敗した場合**は「テスト結果」に失敗したテスト一覧を記載する。
```markdown
# 開発完了レポート
## 実装サマリー
- フロントエンド: (コンポーネント一覧)
- バックエンド: (エンドポイント一覧)
- テスト: (件数と結果。失敗がある場合は失敗したテスト一覧を記載)
## 起動方法
### フロントエンド
npm install && npm run dev # → http://localhost:5173
### バックエンド
cd server && npm install && npm run dev # → http://localhost:3001
```
ユーザーへ:「✅ 全エージェントの作業が完了しました。RESULT.md を確認してください。」(Phase 2 で失敗があった場合は「フロント/バックエンドの一部が失敗しました。RESULT.md を確認してください。」と報告する。)
frontend-agent:
React専門エージェント。orchestratorのTaskツール経由で起動され、フロントエンドを実装する。
エージェント定義
---
name: frontend-agent
description: React専門エージェント。orchestratorのTaskツール経由で起動され、フロントエンドを実装する。
model: inherit
---
# フロントエンドエージェント
あなたはReact専門のフロントエンドエージェントです。
Taskツール経由で起動されたら、以下の手順で自律的に実装を進めてください。
## 実行手順
### Step 1:タスク確認
1. `ARCHITECTURE.md` を読む(全体設計・コンポーネント仕様・API仕様を把握)
2. `tasks/frontend-task.md` を読む(実装内容を確認)
### Step 2:プロジェクト初期化
```bash
npm create vite@latest . -- --template react-ts --force
npm install
npm install axios
npm install -D tailwindcss @tailwindcss/vite
```
- **Tailwind CSS(Vite)**: `vite.config.ts` に `import tailwind from '@tailwindcss/vite'` を追加し、`plugins` に `tailwind` を含める。エントリCSS(例: `src/index.css`)の先頭に `@import "tailwindcss";` を追加する。
- **test-agent 用**: `package.json` の `scripts` に `"test": "vitest"` を追加する(後続の test-agent が `npm run test` で実行するため)。
### Step 3:実装
ARCHITECTURE.mdの仕様に従い実装:
- `src/types/` — 型定義
- `src/api/` — axios によるAPI通信関数
- `src/components/` — Reactコンポーネント
- `src/App.tsx` — ルートコンポーネント
### Step 4:動作確認
```bash
npm run build
```
ビルドが通ることを確認。
### Step 5:完了報告
`tasks/frontend-task.md` のステータスを「✅ 完了」に更新する。
## 技術ルール
- バックエンドAPIのベースURL: `http://localhost:3001`
- Tailwind CSSでシンプルにスタイリング
- エラー処理を適切に実装する
backend-agent:
Node.js/Express専門エージェント。orchestratorのTaskツール経由で起動され、バックエンドAPIを実装する。
エージェント定義
---
name: backend-agent
description: Node.js/Express専門エージェント。orchestratorのTaskツール経由で起動され、バックエンドAPIを実装する。
model: inherit
---
# バックエンドエージェント
あなたはNode.js/Express専門のバックエンドエージェントです。
Taskツール経由で起動されたら、以下の手順で自律的に実装を進めてください。
## 実行手順
### Step 1:タスク確認
1. `ARCHITECTURE.md` を読む(全体設計・APIエンドポイント仕様・データモデルを把握)
2. `tasks/backend-task.md` を読む(実装内容を確認)
### Step 2:プロジェクト初期化
```bash
mkdir -p server && cd server
npm init -y
npm install express cors dotenv
npm install -D typescript ts-node @types/express @types/cors @types/node nodemon
npx tsc --init
```
`package.json` の scripts に追加:
```json
{
"dev": "nodemon --exec ts-node src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "jest --verbose"
}
```
(test-agent が `npm run test` でバックエンドテストを実行するため `test` スクリプトが必要。Jest 本体は test-agent が後でインストールするので、ここでは script だけ定義する。)
### Step 3:実装
ARCHITECTURE.mdの仕様に従い実装:
- `server/src/types/` — データモデルの型定義
- `server/src/data/` — インメモリデータストア
- `server/src/routes/` — ルートハンドラー
- `server/src/index.ts` — Expressサーバー本体
### Step 4:動作確認
```bash
cd server && npm run build
```
ビルドが通ることを確認。
### Step 5:完了報告
`tasks/backend-task.md` のステータスを「✅ 完了」に更新する。
## 技術ルール
- ポート: `3001`
- CORS: `http://localhost:5173` を許可
- データストア: インメモリ配列(DBなし)
- 適切なHTTPステータスコードを返す(200/201/400/404/500)
test-agent:
テスト専門エージェント。orchestratorのTaskツール経由でフロント・バックエンド完了後に起動され、テストを実装・実行する。
エージェント定義
---
name: test-agent
description: テスト専門エージェント。orchestratorのTaskツール経由でフロント・バックエンド完了後に起動され、テストを実装・実行する。
model: inherit
---
# テストエージェント
あなたはQA専門のテストエージェントです。
Taskツール経由で起動されたら、以下の手順で自律的にテストを実装してください。
## 実行手順
### Step 1:タスク確認
1. `ARCHITECTURE.md` を読む
2. `tasks/test-task.md` を読む
3. `src/` のフロント実装を確認
4. `server/src/` のバックエンド実装を確認
### Step 2:フロントエンドテスト
ルートの `package.json` に `"test": "vitest"` が無ければ `scripts` に追加する。
```bash
npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom
```
`src/__tests__/` に各コンポーネントのテストを作成。
### Step 3:バックエンドテスト
`server/package.json` に `"test"` スクリプトが無ければ `"test": "jest --verbose"` を追加する。
```bash
cd server && npm install -D jest supertest @types/jest @types/supertest ts-jest
```
`server/src/__tests__/` に各エンドポイントのテストを作成。
### Step 4:テスト実行&結果を記録
```bash
npm run test -- --reporter=verbose 2>&1 | tee tasks/frontend-test-result.txt
cd server && npm run test -- --verbose 2>&1 | tee ../tasks/backend-test-result.txt
```
### Step 5:完了報告
`tasks/test-task.md` のステータスを「✅ 完了」に更新し、テスト結果のサマリーを記載する。**一部テストが失敗した場合**は、失敗したテスト一覧を test-task.md または RESULT.md に記載し、オーケストレーターが Phase 4 でユーザーに伝えられるようにする。
## テストルール
- 各コンポーネントに最低1つのレンダリングテスト
- 各APIエンドポイントに最低1つのリクエストテスト(正常系・異常系)
成果物(ソースは割愛します)
ARCHITECTURE.md
# Todoアプリ アーキテクチャ設計
## プロジェクト概要
Todoの追加・完了トグル・削除の3機能を持つシンプルなTodoアプリ。フロントエンドはReact(Vite + TypeScript + TailwindCSS)、バックエンドはExpress(TypeScript)、データはインメモリで保持する。
---
## 技術スタック
| 層 | 技術 |
|----|------|
| フロントエンド | React 18, TypeScript, Vite, TailwindCSS, axios |
| バックエンド | Node.js, Express, TypeScript |
| データ | インメモリ配列(永続化なし) |
---
## フォルダ構成
```
todo-app/
├── ARCHITECTURE.md
├── tasks/
│ ├── frontend-task.md
│ ├── backend-task.md
│ └── test-task.md
├── src/ # フロントエンド(Viteで生成)
│ ├── types/ # 型定義
│ ├── api/ # API通信
│ ├── components/ # Reactコンポーネント
│ ├── App.tsx
│ ├── main.tsx
│ └── index.css
├── server/ # バックエンド
│ ├── src/
│ │ ├── types/ # 型定義
│ │ ├── data/ # インメモリストア
│ │ ├── routes/ # ルートハンドラー
│ │ └── index.ts
│ ├── package.json
│ └── tsconfig.json
└── package.json # フロント用
```
---
## 共有型定義(フロント・バック共通)
フロントは `src/types/todo.ts`、バックは `server/src/types/todo.ts` に同じ型を定義する。
```ts
// Todo 1件の型
export interface Todo {
id: string;
title: string;
completed: boolean;
}
// POST /todos のリクエストボディ
export interface CreateTodoRequest {
title: string;
}
// PATCH /todos/:id のリクエストボディ(部分更新)
export interface UpdateTodoRequest {
title?: string;
completed?: boolean;
}
```
---
## APIエンドポイント一覧
| メソッド | パス | 説明 | リクエスト | レスポンス |
|----------|------|------|------------|------------|
| GET | /todos | 一覧取得 | なし | `Todo[]` (200) |
| POST | /todos | 1件追加 | `CreateTodoRequest` (JSON) | `Todo` (201) |
| PATCH | /todos/:id | 更新(完了トグル等) | `UpdateTodoRequest` (JSON) | `Todo` (200) |
| DELETE | /todos/:id | 1件削除 | なし | 204 No Content |
- 存在しないIDで PATCH/DELETE した場合: **404**
- title が空・不正な POST: **400**
- サーバーエラー: **500**
---
## フロントエンド コンポーネント一覧
| コンポーネント | 役割 |
|----------------|------|
| `App` | ルート。Todo一覧の取得・状態管理、子コンポーネントの配置。 |
| `TodoForm` | 入力欄と「追加」ボタン。Enterまたはボタンで POST /todos を呼ぶ。 |
| `TodoList` | Todo一覧を表示。各項目は TodoItem で表示。 |
| `TodoItem` | 1件表示。チェックボックス(完了トグル → PATCH)、削除ボタン(DELETE)、タイトル表示。 |
- **APIベースURL**: `http://localhost:3001`
- 一覧はマウント時および追加/更新/削除後に GET /todos で再取得するか、ローカル状態を更新する。
---
## データフロー
1. **追加**: TodoForm で title 入力 → POST /todos → 成功時は一覧に反映(再GETまたはレスポンスで追加)。
2. **完了トグル**: TodoItem のチェック → PATCH /todos/:id `{ completed: !completed }` → 成功時は表示を更新。
3. **削除**: TodoItem の削除ボタン → DELETE /todos/:id → 成功時は一覧から除外。
---
## バックエンド 実装方針
- **ポート**: 3001
- **CORS**: `origin: http://localhost:5173` を許可
- **ストア**: メモリ上の `Todo[]`。ID は UUID または `Date.now().toString(36)` 等で一意に生成
- **ルート**: `server/src/routes/todos.ts` に GET/POST/PATCH/DELETE を実装し、`server/src/index.ts` で `app.use('/todos', todosRouter)` のようにマウント
frontend-task.md
# フロントエンド タスク
## ステータス: ✅ 完了
## 実装内容
ARCHITECTURE.md に基づき、以下を実装する。
### 1. プロジェクト初期化
- `npm create vite@latest . -- --template react-ts --force` で Vite + React + TypeScript プロジェクト作成
- axios, tailwindcss (@tailwindcss/vite) をインストール
- vite.config.ts に Tailwind プラグインを追加、index.css に `@import "tailwindcss";`
- package.json の scripts に `"test": "vitest"` を追加
### 2. 型定義
- `src/types/todo.ts`: `Todo`, `CreateTodoRequest`, `UpdateTodoRequest` を ARCHITECTURE.md の通り定義
### 3. API 通信
- `src/api/todos.ts`: ベースURL `http://localhost:3001` で以下を実装
- `getTodos(): Promise<Todo[]>` … GET /todos
- `createTodo(title: string): Promise<Todo>` … POST /todos
- `updateTodo(id: string, data: UpdateTodoRequest): Promise<Todo>` … PATCH /todos/:id
- `deleteTodo(id: string): Promise<void>` … DELETE /todos/:id
### 4. コンポーネント
- **App.tsx**: Todo一覧の state 管理、GET /todos で初期取得、TodoForm と TodoList を配置
- **TodoForm**: 入力欄と「追加」ボタン。送信で createTodo を呼び、成功時に一覧を更新(再取得または親から渡した setState)
- **TodoList**: todos 配列を受け取り、各要素を TodoItem で表示
- **TodoItem**: チェックボックス(完了トグルで updateTodo の PATCH)、削除ボタン(deleteTodo の DELETE)、タイトル表示。必要なコールバックは props で受け取る
### 5. スタイル
- TailwindCSS で見た目を整える(リスト、ボタン、入力欄など)。シンプルでよい。
### 6. エラー処理
- API 呼び出しでエラーになった場合は alert または画面上にメッセージ表示など、適切に処理する。
## 完了条件
- [x] 全コンポーネント実装完了
- [x] APIとの疎通確認(バックエンド起動時に追加・完了トグル・削除が動作すること)
- [x] `npm run dev` で起動確認
- [x] `npm run build` が通ること
完了後はステータスを「✅ 完了」に更新すること。
backend-task.md
# バックエンド タスク
## ステータス: ✅ 完了
## 実装内容
ARCHITECTURE.md に基づき、以下を実装する。
### 1. プロジェクト初期化
- `server/` ディレクトリを作成し、その中で `npm init -y`
- express, cors, dotenv をインストール
- typescript, ts-node, @types/express, @types/cors, @types/node, nodemon を devDependencies でインストール
- `npx tsc --init` で tsconfig.json 生成
- package.json の scripts に `dev`, `build`, `start`, `test` を追加(test は `jest --verbose`)
### 2. 型定義
- `server/src/types/todo.ts`: `Todo`, `CreateTodoRequest`, `UpdateTodoRequest` を ARCHITECTURE.md の通り定義
### 3. インメモリデータストア
- `server/src/data/store.ts`: Todo の配列を保持する変数と、ID 生成用のヘルパー(例: uuid または `crypto.randomUUID()` / 簡易的に `Date.now().toString(36)` など)を用意。GET/POST/PATCH/DELETE で参照・更新する。
### 4. ルート
- `server/src/routes/todos.ts`: Express の Router で以下を実装
- **GET /todos**: 全件返却、200, body は `Todo[]`
- **POST /todos**: body に `title` 必須。空や不正なら 400。成功時は 201 で作成した `Todo` を返す
- **PATCH /todos/:id**: body で `title` / `completed` を部分更新。id が存在しなければ 404。成功時は 200 で更新後の `Todo` を返す
- **DELETE /todos/:id**: 該当 id を削除。存在しなければ 404。成功時は 204 No Content
### 5. サーバー本体
- `server/src/index.ts`:
- Express アプリを作成
- CORS で `origin: http://localhost:5173` を許可
- `express.json()` で JSON パース
- `/todos` で todos ルートをマウント
- ポート 3001 でリッスン
### 6. エラー・ステータス
- 存在しない ID: 404
- 不正なリクエスト(例: title なし): 400
- サーバーエラー: 500
## 完了条件
- [x] 全エンドポイント実装完了(GET /todos, POST /todos, PATCH /todos/:id, DELETE /todos/:id)
- [x] CORS で localhost:5173 を許可していること
- [x] ポート 3001 で起動確認
- [x] `cd server && npm run build` が通ること
完了後はステータスを「✅ 完了」に更新すること。
test-task.md
# テスト タスク
## ステータス: ✅ 完了
## 実装内容
フロントエンド・バックエンドの実装が完了した後に、以下のテストを実装・実行する。
### フロントエンド(Vitest + React Testing Library)
- ルートの package.json に `"test": "vitest"` が無ければ追加
- `npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom` を実行
- `src/__tests__/` に以下を配置
- App または TodoList / TodoItem / TodoForm のいずれかに対するレンダリングテスト(最低1コンポーネント以上)
- ユーザー操作(入力・クリック)とAPIのモックを使ったテストがあればよい
### バックエンド(Jest + Supertest)
- server/package.json に `"test": "jest --verbose"` が無ければ追加
- `cd server && npm install -D jest supertest @types/jest @types/supertest ts-jest` を実行
- `server/src/__tests__/` に API テストを配置
- GET /todos: 正常系(200、配列が返る)
- POST /todos: 正常系(201、Todoが返る)、異常系(title なしで 400)
- PATCH /todos/:id: 正常系(200、完了トグル)、異常系(存在しない id で 404)
- DELETE /todos/:id: 正常系(204)、異常系(存在しない id で 404)
### 実行・記録
- `npm run test -- --reporter=verbose` をフロントで実行し、結果を tasks/frontend-test-result.txt に保存(任意)
- `cd server && npm run test -- --verbose` を実行し、結果を tasks/backend-test-result.txt に保存(任意)
## 完了条件
- [x] フロントエンドテスト(Vitest + React Testing Library)の実装とパス
- [x] バックエンドテスト(Jest + Supertest)の実装とパス
- [x] 全テストがパスすること(一部失敗した場合は test-task.md または RESULT.md に失敗一覧を記載)
## テスト結果サマリー(実施日: 2025-03-15)
- **フロントエンド**: 4 ファイル・11 テスト すべてパス(結果: `tasks/frontend-test-result.txt`)
- **バックエンド**: 1 ファイル・8 テスト すべてパス(結果: `tasks/backend-test-result.txt`)
- 失敗したテストはなし
RESULT.md
# 開発完了レポート
## 実装サマリー
### フロントエンド
- **技術**: React 18, TypeScript, Vite, TailwindCSS, axios
- **コンポーネント**
- `App.tsx` … ルート。Todo一覧の state 管理、GET /todos で初期取得、エラー表示
- `TodoForm` … 入力欄と「追加」ボタン。Enter/送信で POST /todos、バリデーション・エラー表示
- `TodoList` … todos 一覧表示、0件時メッセージ
- `TodoItem` … チェックボックス(完了トグル PATCH)、削除ボタン(DELETE)、タイトル表示
- **API クライアント**: `src/api/todos.ts`(getTodos, createTodo, updateTodo, deleteTodo)
- **型**: `src/types/todo.ts`(Todo, CreateTodoRequest, UpdateTodoRequest)
### バックエンド
- **技術**: Node.js, Express, TypeScript
- **エンドポイント**
- `GET /todos` … 一覧取得、200 + Todo[]
- `POST /todos` … 1件追加、201 + Todo(title 必須、空なら 400)
- `PATCH /todos/:id` … 更新(完了トグル等)、200 + Todo(存在しない id は 404)
- `DELETE /todos/:id` … 1件削除、204(存在しない id は 404)
- **ストア**: インメモリ(`server/src/data/store.ts`)
- **CORS**: `http://localhost:5173` 許可、ポート 3001
### テスト
- **フロント**: Vitest + React Testing Library … 4 ファイル・11 テスト、すべてパス
- App.test.tsx, TodoForm.test.tsx, TodoList.test.tsx, TodoItem.test.tsx
- **バックエンド**: Jest + Supertest … 1 ファイル・8 テスト、すべてパス
- server/src/__tests__/todos.test.ts
- **失敗したテスト**: なし(act の警告はフロントの App テストで出るがテストはパス)
---
## 起動方法
### フロントエンド
```bash
cd /develop/todo-app
npm install && npm run dev
```
→ http://localhost:5173
### バックエンド
```bash
cd /develop/todo-app/server
npm install && npm run dev
```
→ http://localhost:3001
### テスト
- フロント: ルートで `npm run test`
- バックエンド: `cd server && npm run test`
---
## ビルド
- フロント: `npm run build`
- バックエンド: `cd server && npm run build`
最後に
orchestratorが設計をし、frontend-agentとbackend-agentに指示をして、アプリを作成。
作成完了すると、test-agentにテストをさせるわけですね。
orchestrator.mdで以下のように記載しましたが、カスタムエージェント名を使ってTaskを起動したので、問題ありませんでした。
- `subagent_type` でカスタムエージェント名(frontend-agent / backend-agent)が使えない環境では、`subagent_type="generalPurpose"` とし、prompt で「`.cursor/agents/frontend-agent.md` の手順に従い……」とエージェント指定すること。
今回は動きを見たいのと、シンプルなアプリなので、エージェントの作成自体もAIに任せましたが、もう少し仕様を明確にし、orchestratorと相談をしながら作った方が良さそうです。
