
Claude Code の並列エージェント機能を試してみた
せーのでございます。
今日は Claude Code の並列エージェント(サブエージェント)を色々試してみましたので、共有します。
Claude Codeを使っていて「調査に時間がかかる」「コンテキストがすぐ膨らむ」と感じたことはありませんか? 私はあります。そこで色々調べたところ、サブエージェント機能というものが使えそうだとわかりました。
嘘です。サブエージェント自体は前から使っていたんですよ。
問題は「使い方」が多少違うかな、と感じたところにあります。
私は今までは
- タスクを処理するのに必要そうなエージェントを先読みする
- そのエージェントを先に作成する
- 必要そうなSkillsも一緒に作る
- エージェントからそのサブエージェントの叩き方を教え込む
- 作業開始
というような作り方でした。
ですが、もっと動的に、Claude Codeに任せてみたらどうなるだろう、ということで、色々なトリガーワードを折り込みながら、Claude Codeをより自律的に動かすとどのような動きをするのか、実験をしてみたくなりました。
では、実際に使ってみましょう。
並列エージェント(サブエージェント)とは(おさらい)
サブエージェントは、メインのClaude Code会話から独立した専門エージェントを起動できる仕組みです。
┌─────────────────────────────────────────┐
│ メインのClaude Code会話 │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ エージェント A │ │ エージェント B │ │ エージェント C │ │
│ │ (Explore) │ │ (Explore) │ │ (Bash) │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ ↓ ↓ ↓ │
│ 結果のみメインコンテキストに返却 │
└─────────────────────────────────────────┘
つまり、サブエージェントが裏で色々調べてくれて、結果だけをメインに報告してくれる、というわけです。
組み込みサブエージェント
Claude Codeには、最初から使えるサブエージェントが用意されています。
| タイプ | モデル | 用途 |
|---|---|---|
| Explore | Haiku | 高速なコードベース探索(読み取り専用) |
| Plan | 継承 | 計画モード時の調査 |
| General-purpose | 継承 | 複雑なマルチステップタスク |
| Bash | 継承 | コマンド実行専用 |
特にExploreは軽量モデル(Haiku)を使うため、高速かつ低コストで調査できます。
使うべき場面・使わないべき場面
使うべき場面
- 大量のファイルを調査する時
- 複数の独立した調査を並列で行いたい時
- 長時間かかる処理をバックグラウンドで実行したい時
使わないべき場面
- 単純で素早い修正(オーバーヘッドの方が大きい)
- ユーザーとの対話が必要な時(サブエージェントは対話不可)
実験用サンプルプロジェクト
実験のため、Pythonのタスク管理CLIツールを作成しました。
一言でいうと:ターミナルから「タスクを追加・一覧表示・作業開始・完了・削除」ができるツールです。データは ~/.task_cli/tasks.json にJSONで保存されます。
実際に動かすと、例えばこんな感じです。
# タスクを追加
python -m task_cli.main add "ブログの下書きを書く"
# → ✓ Created task [af3ee770]: ブログの下書きを書く
python -m task_cli.main add "スクリーンショットを撮る" -p high
python -m task_cli.main add "Claude Codeを試す" -d "Task機能の実験" -t experiment blog
# 一覧表示
python -m task_cli.main list
# → ○ [af3ee770] ブログの下書きを書く →
# ○ [f3f33bf2] スクリーンショットを撮る ↑
# ...
# 作業開始・完了・詳細表示
python -m task_cli.main start af3ee770 # → ✓ Started: ブログの下書きを書く
python -m task_cli.main done f3f33bf2 # → ✓ Completed: スクリーンショットを撮る
python -m task_cli.main show 18e9459f # → タスクの詳細(説明・タグ付き)
add / list / start / done / show / delete といったサブコマンドでタスクを扱い、内部では main.py(argparse)→ models.py(Task/TaskList)→ storage.py(JSON読み書き)という流れで動いています。
プロジェクト構造は次のとおりです。
experiment-project/
├── src/task_cli/
│ ├── __init__.py # パッケージ初期化
│ ├── main.py # CLIエントリポイント(argparse)
│ ├── models.py # Task/TaskListデータモデル
│ ├── storage.py # JSON永続化
│ └── formatters.py # ターミナル出力整形
├── tests/ # pytest テスト(41件)
├── pyproject.toml
└── requirements.txt
Python + pytestで構成された、約600行のプロジェクトです。このプロジェクトを使って、サブエージェントを試していきます。
やってみた1: 並列Exploreで一気に調査
まずは、3つのExploreエージェントを同時に起動してみます。
以下のプロンプトを入力しました。
このプロジェクトのアーキテクチャ、テストカバレッジ、依存関係を並列で調査して
なんということでしょう。Claude Codeは3つのExploreエージェントを同時に起動しました。
⏺ 3 Explore agents finished (ctrl+o to expand)
├─ アーキテクチャ調査 · 10 tool uses · 92.0k tokens
├─ テストカバレッジ調査 · 27 tool uses · 96.0k tokens
└─ 依存関係調査 · 16 tool uses · 82.4k tokens
約2分で3つの調査が完了。合計53回のツール呼び出しが並列で実行されています。これは便利です。
各エージェントの作業内容を確認する
ctrl+o を押すと、各エージェントが独立して何をしたかを詳しく見ることができます。
アーキテクチャ調査エージェントの作業例:
⏺ Explore(アーキテクチャ調査)
⎿ Prompt:
このプロジェクトのアーキテクチャを調査してください。以下を含めて報告してください:
1. ディレクトリ構造
2. 主要なモジュールとその責務
...
⎿ Bash(find . -type f -name "*.py" | head -20)
⎿ Bash(tree -L 3 ...)
⎿ Read(README.md)
⎿ Read(pyproject.toml)
⎿ Read(src/task_cli/main.py)
⎿ Read(src/task_cli/models.py)
⎿ Read(src/task_cli/storage.py)
⎿ Read(src/task_cli/formatters.py)
...
⎿ Response:
アーキテクチャ調査が完了しました。以下、詳細なレポートを報告します。
...
⎿ Done (10 tool uses · 93.0k tokens · 1m 3s)
きちんと自分でファイルを探して、読み込んで、分析しているようですね。
テストカバレッジ調査エージェントは27回もツールを呼び出していました。途中でMCPのアクセスエラーが発生しましたが、自動的にBashコマンドで代替手段を使って調査を続行。最終的に pytest --cov まで実行してカバレッジレポートを生成していました。
⏺ Explore(テストカバレッジ調査)
...
⎿ filesystem - list_directory (MCP)(path: "...")
⎿ Error: Access denied - path outside allowed directories
⎿ Bash(cd ... && find . -type f -name "*.py" | sort) # 代替手段で続行
...
⎿ Bash(python -m pytest tests/ --cov=src/task_cli --cov-report=term-missing)
⎿ Response:
テストカバレッジの詳細な分析が完了しました。
...
⎿ Done (27 tool uses · 96.6k tokens · 2m 57s)
エラーが発生しても自分で迷走せずに代替手段を見つけて続行する、というのは頼もしいですね。
調査結果
各エージェントから、構造化されたレポートが返ってきます。
| 調査項目 | 主な発見 |
|---|---|
| アーキテクチャ | 層構造アーキテクチャ、4モジュール構成、Factory/Command/Facadeパターン使用 |
| テストカバレッジ | 全体57%、main.pyが0%で未テストという重大な問題を発見 |
| 依存関係 | 本番依存ゼロ(標準ライブラリのみ)、開発依存はpytest/pytest-cov |
特に「main.pyが完全に未テスト」という指摘は、人間が見落としがちなポイントです。3つの視点から同時に分析することで、こういった問題が見つかりやすくなります。
ここでのポイント
この実験で重要なのは、各エージェントが独立したコンテキストで動作しているという点です。
┌─────────────────────────────────────────┐
│ メインのClaude Code会話 │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 10回 │ │ 27回 │ │ 16回 │ │
│ │ 操作 │ │ 操作 │ │ 操作 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ ↓ ↓ ↓ │
│ 結果のみ 結果のみ 結果のみ │
│ (要約) (要約) (要約) │
└─────────────────────────────────────────┘
53回分の詳細な操作履歴はメインコンテキストに持ち込まれず、要約結果だけが返却されます。これがコンテキストウィンドウの節約につながります。
やってみた2: バックグラウンドでテスト実行
次は、テストをバックグラウンドで実行しながら、別の作業を続けてみます。
pytest をバックグラウンドで実行してください。
実行中は別の作業を続けたいです。
すると、pytestがバックグラウンドで起動しました。
⏺ Bash(cd ... && python -m pytest ...)
⎿ Running in the background (↓ to manage)
テストが走っている間も、会話は普通に続けられます。すぐに別の依頼をしてみます。
テストが走っている間に、README.mdの内容を要約してください。
⏺ pytestをバックグラウンドで起動しました(タスクID: bfe8962)。
README.mdを確認します。
⏺ Read 1 file
⏺ README.md 要約
Task CLI - シンプルなタスク管理CLIツール(Claude Code サブエージェントの実験用)
主な機能
┌───────────────────┬────────────────────────────────────────────────┐
│ コマンド │ 説明 │
├───────────────────┼────────────────────────────────────────────────┤
│ task add │ タスク追加(優先度・タグ・詳細オプション付き) │
│ task list │ 一覧表示(フィルタ可能) │
│ task start/done │ ステータス変更 │
│ task delete/clear │ 削除操作 │
└───────────────────┴────────────────────────────────────────────────┘
テスト実行中でも、README.mdの要約がすぐに返ってきました。待ち時間ゼロ、というのはなかなか快適です。
しばらくすると、バックグラウンドのテストが完了します。
⏺ Background command "Run pytest with coverage in background" completed (exit code 0)
結果を確認してみます。
バックグラウンドで実行していたテストの結果を教えてください。
⏺ pytest 結果
✅ 41テスト すべてパス (0.09秒)
カバレッジ
┌───────────────┬────────────┬───────────────────────────────────────┐
│ モジュール │ カバレッジ │ 未テスト行 │
├───────────────┼────────────┼───────────────────────────────────────┤
│ __init__.py │ 100% │ - │
│ formatters.py │ 95% │ 84, 158-160 │
│ models.py │ 96% │ 76-77, 111 │
│ storage.py │ 83% │ 30, 57-58, 75-76, 88-89, 115-116, 133 │
│ main.py │ 0% │ 3-261(全行) │
│ 合計 │ 57% │ │
└───────────────┴────────────┴───────────────────────────────────────┘
& コマンドとの違い
ちなみに、従来からシェルの & コマンドでバックグラウンド実行はできました。その場合、それまでのチャット履歴(プロンプト)がWeb(claude.ai/code)上に移動し、移動が終わると同じセッションで続きのプロンプトをかけます。その時点でリポジトリがコミットされていなければ確認が入ります。なお、/task や claude --teleport はローカルで実行するコマンドです。このコマンドをローカルで叩くと、Webで動いていたセッションを、会話履歴ごとローカルで引き継ぐことができるわけですね。
違いを整理すると、& は「処理するプラットフォームを変える」もの(ローカル→Webへ移す)、サブエージェントのバックグラウンドは「同じセッション内で別プロセスを走らせる」もの、というイメージです。
サブエージェントのバックグラウンド実行は、セッションを離れずに別の作業ができるのがポイントです。
一方、& + Web移動方式はPCを閉じても処理が続くというメリットがあります。長時間かかるジョブなら従来の方式、すぐ終わるテストならサブエージェント、というように使い分けるのが良さそうです。
やってみた3: カスタムサブエージェントを作成
最後に、プロジェクト固有のカスタムエージェントを作成してみます。
まず、.claude/agents/ ディレクトリを作成し、以下の内容で code-reviewer.md を作成します。
---
name: code-reviewer
description: コードレビュー専門家
tools:
- Read
- Grep
- Glob
model: sonnet
---
# コードレビュー専門エージェント
あなたはシニアPythonエンジニアです。
以下の観点でコードレビューを行ってください:
1. セキュリティ上の問題
2. パフォーマンスの懸念
3. Pythonベストプラクティス(PEP 8、型ヒントなど)
4. コードスタイルの一貫性
ここで一点、ハマりどころがありました。作成したファイルの全行の先頭にスペースが入っていたため、フロントマターが正しく解釈されず、「code-reviewerというエージェントタイプは利用可能なリストに存在しません」と出てしまいました。色々調べたところ、YAMLのフロントマターは行頭から書く必要があるとのこと。行頭のスペースを削除し、Claude Codeで /agents を実行して読み込み直したら、無事に認識されました。
Claude Codeで次のように呼び出します。
code-reviewerエージェントで src/ をレビューしてください
約1分ほどで、レビュー結果が返ってきました。
⏺ code-reviewer(src/のコードレビュー実施)
⎿ Done (6 tool uses · 13.6k tokens · 1m 1s)
⏺ src/ ディレクトリのコードレビューが完了しました。
レビュー結果サマリー
重大な問題(高優先度)
┌────────────────────────┬──────────────────┬────────────────────────────┐
│ 問題 │ ファイル │ 内容 │
├────────────────────────┼──────────────────┼────────────────────────────┤
│ パストラバーサル脆弱性 │ storage.py:21-32 │ ユーザー指定パスの検証なし │
├────────────────────────┼──────────────────┼────────────────────────────┤
│ ファイル権限の不備 │ storage.py:73-74 │ 600権限で作成されない │
├────────────────────────┼──────────────────┼────────────────────────────┤
│ UUID衝突リスク │ models.py:32 │ 8文字のみ使用で衝突可能性 │
└────────────────────────┴──────────────────┴────────────────────────────┘
中程度の問題
- パフォーマンス: models.py の get() が O(n) の線形検索。インデックス化推奨
- 例外処理: IOError は OSError のエイリアス(冗長)、パス情報が不足
- 競合状態: 複数プロセス同時書き込み時のファイルロックなし
軽微な問題
- 型ヒントの不統一(list[str] vs List[str])
- マジックナンバー(return 130)の意味不明確
- 関数内import(storage.py:112 の import shutil)
- docstringスタイルの不統一
総評
コードは読みやすく構造化されていますが、セキュリティとデータ整合性の面で改善が必要です。
特にパストラバーサル脆弱性とファイル権限は早めに対応することを推奨します。
重大・中程度・軽微に分かれたフィードバックと総評が、きちんと返ってきました。プロジェクト固有のレビュー基準を事前に定義しておけば、毎回同じ観点でレビューしてもらえるわけです。
カスタムエージェントの活用例
他にも、こんなカスタムエージェントが考えられます。
- test-runner: テスト実行&結果解析
- security-auditor: セキュリティ監査
- doc-writer: ドキュメント自動生成
- refactor-helper: リファクタリング提案
チームで共有すれば、レビュー基準やドキュメントスタイルの統一にも使えそうですね。
まとめ
並列エージェント(サブエージェント)を使ってみて感じたのは、「調査」と「実行」を分離できるというのが地味に便利だということです。
特に:
- 並列実行で調査を高速化できる
- バックグラウンド実行で待ち時間をなくせる
- カスタムエージェントでプロジェクト固有のタスクを定型化できる
という3点が実用的でした。
大きなコードベースを扱う時や、複数の調査を同時に行いたい時に、ぜひ試してみてください。










