😺

Claude Codeのsub-agentsをバックグラウンド実行して並列開発フローを回してみた

に公開

この記事は PeopleX Advent Calendar 2025 の15日目の記事です。

はじめに

ClaudeCodeにはsub-agentsという機能があります。
https://code.claude.com/docs/ja/sub-agents

この機能を利用すると特定の種類の処理を特化したagentを定義することで、より効率的な処理を実行させることができます。

種類が特定された作業では、解決アプローチや作業の観点やツールの指定など決定できることが多いので、それらを指定することでより正確でブレの少ない作業を繰り返し実行させることができます。

また、メインの会話とは独立したコンテキストウィンドウを持つので、それぞれ別のコンテキストを維持させたまま作業を行えるのも大きな利点です。

筆者は普段はコードレビューやPRの概要説明の作成はsubagentを定義して作業をしています。

最近ClaudeCodeからのアナウンスで、agentがbackgroundで非同期に実行できるようになったことを知りました。

この記事ではこの機能を利用して、agentを並列に実行しての開発を試します。

バージョン情報

  • ClaudeCode: 2.0.69
  • 使用モデル: Opus4.5

注意事項

この記事ではAIを活用した実装の紹介はありますが、AI生成されたコードやモデル自体の品質を問う記事ではありません。
品質に関しては、どこまでしっかり設計して指示をしているかやコンテキスト(既存のソースコードやCLAUDE.md)、(人やAIを含む)レビュー結果の修正サイクルなどに左右される部分ですが、その部分に関しては考慮外です。
agentの作業の質に関してもagent.mdの質に左右されますが、これも検証範囲外です。
この記事はあくまでsubagentをbackgroundで実行した並列開発作業の筆者の体験を紹介するものです。

今回実装する(した)もの

個人的に最近は素振り(技術検証)のための最初の実装はClaudeCodeにやらせることが多いです。

執筆時点で2日前(2025/12/14)のNestJSのアップデートで、GraphQLの@oneOf inputに対応したということなので、これを試していきます。
https://github.com/nestjs/graphql/releases/tag/v13.2.3

プロジェクトの構成とアプリケーション仕様は先に定義しました。

リポジトリはこちら
https://github.com/joe-re/nestjs-graphql-oneof-example

agentの定義

今回定義するagentは以下の5つです。

  • backend-engineer: バックエンドAPI設計・実装・テスト
  • frontend-engineer: フロントエンドコンポーネント設計・実装
  • code-review-researcher: 最新のベストプラクティス・ライブラリ機能の調査
  • code-reviewer: コード品質・セキュリティ・パフォーマンスのレビュー
  • qa-engineer: QAテスト・動作検証・バグ調査(Chrome Dev Tool MCPを活用)

agentはClaudeCodeのwindow内で /agent コマンドから作っていきます。
今回はそれぞれ簡素な指示を与えて作成して、そのまま使います。

ex) qa-engineer: QAエンジニアです。backend-engineerやfrontend-engineerの修正を受けて動作検証を行います。作業にはChrome DevTools MCPを活用します。

CLAUDE.mdでそれぞれのagentの役割を明確にする

CLAUDE.md自体もClaudeCodeに書かせています。(その後修正はしています。)
指示はこんな感じ。

CLAUDE.mdを作成します。 以下の内容に沿って作成してください。

ここではプロジェクトの進め方を定義します。
このプロジェクトでは以下のagentが存在します。
  - backend-engineer
  - frontend-engineer
  - code-review-researcher
  - code-reviewer
  - qa-engineer

それぞれは .claude/agenets に定義されています。
agentはユーザの指示に従い、backgroundで処理を行います。
schema定義はbackend-engineerが作成し、frontend-engineerはそれに沿って実装を行います。
backend-engineerとfrontend-engineerは実装が完了したら、code-review-researcherとcode-reviewerにレビュー依頼を行います。
code-review-researcherとcode-reviewerはそれぞれの結果を話し合い、レビュー結果としてbackend-engineerとfrontend-engineerに伝えます。
backend-engineerとfrontend-engineerはその結果を元に修正を行います。

backend-engineerとfrontend-engineerの実装が完了したら、qa-engineerに確認を依頼します。
qa-engineerはテストを実施し、結果次第でbackend-engineerとfrontend-engineerに修正依頼を行います。

今回はagentの役割や開発ワークフローはCLAUDE.mdに書いてみました。
ある程度曖昧な指示からも想定した開発ワークフローに則ってくれることを期待しています。

例)

### Agent Rules

1. backend-engineerとfrontend-engineerは実装完了後、code-review-researcherとcode-reviewerにレビュー依頼をします。
2. backend-engineerとfrontend-engineerはレビュー結果を修正後、再度レビュー依頼をします。
3. レビュー結果が良好の場合、qa-engineerに動作確認を依頼します。
4. qa-engineerの報告で不具合が見つかった場合には、backend-engineerとfrontend-engineerは修正します。この段階で1に戻り、qa-engineerの結果がパスするまで繰り返します。

開発の様子

普段通り指示を与えて、開発していきます。
まず最初にセットアップを依頼しました。

実装を開始します。 @implementation-plan.md の内容を読み、リポジトリ構成と使うライブラリを理解してください。まだアプリケーションの実装はしません。
プロジェクトのセットアップを行ってください。
セットアップ後に簡単な疎通が行える実装を行い、qa-engineerに動作確認を依頼してください。

その結果が↓です。しっかりCLAUDE.mdを読み取って、backend-engineerとfrontend-engineerの並行開発、qa-engineerへのQA依頼が適用されていますね。

⏺ backend-engineerとfrontend-engineerをbackgroundで並行起動してセットアップを行います。

⏺ 2 agents launched (ctrl+o to expand)
   ├─ backend-api-engineer (Setup NestJS backend) · Running in background
   │  ⎿  Launched
   └─ frontend-component-architect (Setup NextJS frontend) · Running in background
      ⎿  Launched

⏺ backend-engineerとfrontend-engineerがbackgroundでセットアップ中です。進捗を確認します 。

  Task Output a8b28d5
  ⎿  Running PreToolUse hook…
  Setup NestJS backend
     Waiting for task (esc to give additional instructions)

∴ Thought for 1s (ctrl+o to show thinking)

✳ backend をセットアップ中… (esc to interrupt · ctrl+t to hide todos · 3m 40s ·
↓ 2.5k tokens)
  ⎿  ☒ pnpm workspaceの初期化
     ☐ backend (NestJS + GraphQL) のセットアップ
     ☐ frontend (NextJS) のセットアップ
     ☐ 疎通確認用のシンプルなQuery実装
     ☐ qa-engineerに動作確認を依頼

修正後のレビューまではCLAUDE.mdに含まれているものの、指示になかったからか実施されませんでした。この辺りはCLAUDE.mdに書くよりも、agent自体に書くなどの方法で自動化した方が良いかもしれません。

適当にレビュー依頼をすると、これも想定通り並列起動されました。

> reviewを依頼します。

● backend-engineerとfrontend-engineerの実装に対して、code-reviewerとcode-review-researcherにレビューを依頼します。

● 4 agents launched (ctrl+o to expand)
  ├─ code-reviewer (Code review for backend) · Running in background
  │  └ Launched
  ├─ code-reviewer (Code review for frontend) · Running in background
  │  └ Launched
  ├─ code-review-researcher (Research review for backend) · Running in background
  │  └ Launched
  └─ code-review-researcher (Research review for frontend) · Running in background
     └ Launched

● 4つのレビューエージェントがbackgroundで並行実行中です。結果を待ちます。

● Task Output a5c83e8
  └ Read output (ctrl+o to expand)

● Task Output a007b5d
  └ Read output (ctrl+o to expand)

● Task Output a9a79ce
  └ Read output (ctrl+o to expand)

● Task Output aead8a3
  └ Read output (ctrl+o to expand)

● 4つのレビューが完了しました。結果を統合します。

レビュー後の修正依頼

> レビュー指摘を修正してください                                                        │apps/frontend dev:  ✓ Compiled / in 429ms (523 modules)
                                                                                        │apps/frontend dev:  GET / 200 in 715ms
⏺ レビュー指摘事項の修正をbackend-engineerとfrontend-engineerに依頼します。             │apps/frontend dev:  GET / 200 in 63ms
                                                                                        │apps/frontend dev:  GET / 200 in 34ms
∴ Thought for 1s (ctrl+o to show thinking)                                              │^[[A^[[A^[[A^[[A^[[A^[[A
                                                                                        │
· Imagining… (esc to interrupt)

agentを並行起動して作業させることはできたので、あとは想定しているアプリケーション仕様通りに実装していきます。
今回は人はマネージャーに徹します。

そうこうしてできたもの

仕様通りにアプリケーションは実装完了しました。

しっかり @oneOf も使えてますね。

import { InputType, Field, ID, Directive } from '@nestjs/graphql';
import { IsOptional, IsString } from 'class-validator';
import { OneOf } from '../validators/one-of.decorator';

@InputType({ description: 'Specify item by one identifier (productId, sku, or barcode)' })
@OneOf()
@Directive('@oneOf')
export class AddToCartItemBy {
  @Field(() => ID, { nullable: true })
  @IsOptional()
  @IsString()
  productId?: string | null;

  @Field(() => String, { nullable: true })
  @IsOptional()
  @IsString()
  sku?: string | null;

  @Field(() => String, { nullable: true })
  @IsOptional()
  @IsString()
  barcode?: string | null;
}

感想

開発体験に関しては非常に良く、かなり有用な機能かなと思いました。
agentは特化した作業に向くので、どういうagentを使っていくかに左右される部分は大きいです。

例えばTDDアプローチで先にテストを書くなら、テストを書くための専用agentを作るのは、実装のコンテキストに左右されずに作業を行わせたいという意図に合っています。

今回のようにfront、backendで分けて並行開発は、効果は微妙かなとも思いました。
Opus4.5は賢いので、適切なコードベースと指示がある前提があれば、front/backendのベストプラクティスを実践して開発できます。

逆にレビュー観点はagenticなアプローチで少なくしていった方が精度が出るので、frontのコンポーネントの責務に関してレビューさせるagent、APIの設計に関してレビューさせるagentなどを細かく定義していくのは有用で、ここでは並列起動の利点がダイレクトに活かせそうです。

agentを育てていくのは育成ゲームみたいで面白さもありますね。
君だけの最強のagentを育成しよう。

PeopleXテックブログ

Discussion