2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Codeで並列エージェントオーケストレーターを自作したら、調査が5.9倍速くなった

2
Last updated at Posted at 2026-04-08

Claude Codeを並列で動かしたら、直列70秒の処理が11.8秒で終わった。 この記事では、claude CLIを子プロセスで大量並列起動するオーケストレーターの作り方と、質問の重さに応じて自動で最適な実行方式を選ぶルーターの実装を紹介する。読んだ後、同じ仕組みを自分の環境で動かせるようになる。

背景:Claude Codeは1回1回が遅い

Claude Code(claude CLI)は強力だけど、1回の実行に平均10秒かかる。「SaaS企業20社を調べて」みたいなタスクだと、1社ずつ直列で回すと200秒(3分以上)。これを並列化すれば理論上は10秒で終わるはず。

やりたかったこと:

  • N個のタスクを同時実行して結果を統合
  • レート制限に引っかかったら自動リトライ
  • 質問の重さに応じてLIGHT/BATCH/DEEPを自動選択

構成:たった2ファイル

orchestrator/
  orchestrator.ts   ← 並列バッチエンジン(p-limit + spawn)
  smart.ts          ← 自動ルーター(LIGHT/BATCH/DEEP判定)
  package.json

依存は p-limit(並列数制御)と tsx(TypeScript実行)だけ。

Step 1: claude CLIを子プロセスで並列起動

最初にClaude Code SDKの query() を試したが、Node.js v25との互換性問題で動かなかった。結局 spawnclaude コマンドを直接叩く方式 が一番安定した。

import { spawn } from "node:child_process";

function runClaude(prompt: string, options: { timeout: number }): Promise<string> {
  return new Promise((resolve, reject) => {
    const child = spawn("/opt/homebrew/bin/claude", [
      "--output-format", "json",
      "--max-turns", "3",
      "-p", prompt,
    ], {
      stdio: ["ignore", "pipe", "pipe"],  // stdinをignoreにしないと3秒待ちが発生
    });

    let stdout = "";
    child.stdout.on("data", (d: Buffer) => { stdout += d.toString(); });

    const timer = setTimeout(() => {
      child.kill("SIGTERM");
      reject(new Error("TIMEOUT"));
    }, options.timeout);

    child.on("close", (code) => {
      clearTimeout(timer);
      if (code !== 0) { reject(new Error(`Exit ${code}`)); return; }
      const json = JSON.parse(stdout);
      resolve(json.result ?? stdout);
    });
  });
}

ポイントは stdio: ["ignore", "pipe", "pipe"]。これがないと claude がstdin待ちで3秒ハングする。

Step 2: p-limitで並列数を制御

Promise.all だけだと全タスクが同時に走ってAPIレート制限に引っかかる。p-limit で同時実行数を制御する。

import pLimit from "p-limit";

const limit = pLimit(10); // 同時10並列

const promises = tasks.map((task) =>
  limit(async () => {
    const result = await executeTask(task);
    completed++;
    showProgress(completed, total, task.id, result.status);
    return result;
  })
);

const results = await Promise.all(promises);

Step 3: 適応的並列度 + リトライ

concurrency 50で試したら全タスクがtimeoutした。APIレート制限を検知して自動で並列度を下げる AdaptiveLimiter を実装。

class AdaptiveLimiter {
  reportSuccess(): void {
    this.consecutiveSuccess++;
    // 10回連続成功で並列度UP
    if (this.consecutiveSuccess >= 10) {
      this.currentConcurrency = Math.min(this.currentConcurrency + 2, this.maxConcurrency);
    }
  }

  reportFailure(): void {
    this.consecutiveFailure++;
    // 3回連続失敗で並列度半減
    if (this.consecutiveFailure >= 3) {
      this.currentConcurrency = Math.max(Math.floor(this.currentConcurrency / 2), 2);
    }
  }
}

リトライは指数バックオフ(5秒→10秒→20秒)で実装。レート制限・タイムアウトのみリトライ対象にして、それ以外のエラーは即失敗にする。

Step 4: smart.ts — 質問の重さで自動ルーティング

毎回 npx tsx orchestrator.ts --input tasks.json とか打ちたくない。質問を投げるだけで自動判定する smart.ts を作った。

ユーザー入力
  ↓
[自動分類] Claude が LIGHT / BATCH / DEEP を判定
  ↓
┌─ LIGHT → そのまま回答(10秒)
├─ BATCH → tasks.json自動生成 → 並列実行(50秒)
└─ DEEP  → 質問分解 → 並列収集 → Opus統合(3分)

判定基準:

モード トリガー
LIGHT 単純な1問 「Reactとは」
BATCH 同種N件(N≧3) 「SaaS5社を調べて」
DEEP 多角的分析が必要 「物流SaaSの勝ち筋を徹底調査」

DEEPモードの核心は 分解→並列→統合 の3段パイプライン:

  1. Claudeが質問を10-30個の独立した調査タスクに分解
  2. orchestrator.tsで全タスクを並列実行
  3. 全結果をClaude Opus(最上位モデル)に渡して統合レポート生成

ベンチマーク結果

直列 vs 並列(6タスク)

方式 所要時間 倍率
素のclaude CLI × 6回直列 70秒 基準
オーケストレーター直列 (c=1) 51.4秒 1.4倍
オーケストレーター並列 (c=6) 11.8秒 5.9倍

20タスクの実測

方式 所要時間
素CLI直列(推定) 約180秒
v1 (c=5) 76.7秒
v2 適応的並列 (c=20) 55.0秒

DEEPモード実測

「物流SaaSの今後の勝ち筋を徹底調査して」→ 8ソース並列収集 → Opus統合 → 163秒で完了。手動で同じことやったら数時間はかかる。

ハマりポイント

1. Claude Code SDKがNode.js v25で動かない

SDKバンドル版の cli.js 内部で Cannot read properties of undefined (reading 'prototype') エラー。spawn で直接 claude コマンドを叩く方式に切り替えて解決。

2. stdinを閉じないと3秒ハングする

execFile だとstdinがパイプのまま残り、claude が入力待ちで3秒停止する。spawn + stdio: ["ignore", "pipe", "pipe"] で解決。

3. concurrency 50で全timeout

APIレート制限。適応的並列度制御で解決。最初は5から始めて、成功が続いたら徐々にUPする方式が安定。

Step 5: スキル化 — 「徹底調査して」で自動発動

ここが一番大事。せっかくオーケストレーターを作っても、毎回 npx tsx smart.ts -p "..." と打つのは面倒すぎる。Claude Codeの スキル として登録すれば、普段の会話の中で「徹底調査して」と言うだけで自動発動する。

スキルファイルを作る

~/.claude/skills/smart-research/SKILL.md を作成する。

---
description: "質問の重さを自動判定し、LIGHT/BATCH/DEEPを切り替えて最適な方法で調査する"
---

# smart-research: 自動ルーティング調査エンジン

## 自動発動トリガー

| パターン | モード |
|----------|--------|
| 「N社調べて」「N個比較」「リスト化」 | BATCH |
| 「徹底調査」「深掘り」「100ソース」「多角的に」 | DEEP |
| 「市場調査」「競合分析」「業界分析」 | DEEP |
| 「〜について調べて」(単一対象) | LIGHT |

## 実行方法

### LIGHT(単純な質問)
そのまま回答する。

### BATCH(同種N件の並列調査)
1. 質問からタスクリストを自動生成
2. orchestrator.ts で並列実行
3. 結果を統合して報告

### DEEP(複雑な1問の徹底調査)
1. 質問を10-30個の独立した調査タスクに分解
2. orchestrator.ts で並列収集
3. 全結果を統合してレポート生成

team-leadのルーティングにも追加

既にカスタムsubagentでteam-leadを定義しているなら、ルーティングテーブルに1行追加するだけ。

| 「徹底調査」「N社調べて」「市場調査」「100ソース」 | smart-research スキル |

実際の使用感

これで普段の会話がこう変わる:

Before:

自分: 物流SaaSの競合を調べたい
Claude: [1社ずつ順番に検索... 5分経過]

After:

自分: 物流SaaSの競合を徹底調査して

  → [DEEP] 自動判定
  → 20個の調査タスクに分解
  → 20エージェントが同時にWeb検索
  → Opusが統合レポート生成
  → 3分で完了

何もコマンドを打っていない。 「徹底調査して」と言っただけ。裏側でオーケストレーターが勝手に動いて、分解→並列収集→統合をやってくれる。

これが最終的なゴール。CLIツールを作ること自体が目的じゃなく、普段の会話体験を変えることが目的だった。

全体アーキテクチャ

最終的にできた仕組みを図にするとこうなる。

「〜を徹底調査して」
      ↓
  [smart-research スキル] 自動発動
      ↓
  [分類] LIGHT / BATCH / DEEP を判定
      ↓
  [DEEP の場合]
      ↓
  Phase A: 質問を20個の調査タスクに分解
      ↓
  Phase B: orchestrator.ts で20並列実行
      ├── エージェント1: 競合調査 → Web検索
      ├── エージェント2: 市場規模 → Web検索
      ├── エージェント3: 技術動向 → Web検索
      ├── ...(同時20並列)
      └── エージェント20: 投資動向 → Web検索
      ↓
  Phase C: 全結果をOpusが統合レポートに
      ↓
  results/ にMarkdown保存 + 会話内で表示

ベンチマーク:この仕組みで何が変わったか

操作 Before After 改善
1社調査 10秒 10秒 変わらない
6社調査 70秒 11.8秒 5.9倍
20社調査 約180秒 55秒 3.3倍
複雑な1問の深掘り 手動で数時間 3分 桁違い

まとめ:明日から使えるアクションリスト

  • npm install p-limit tsx して orchestrator.ts をコピー
  • tasks.jsonに並列実行したいタスクを書く
  • npx tsx orchestrator.ts --input tasks.json --concurrency 10 で動作確認
  • smart.tsで自動ルーティングを追加
  • ~/.claude/skills/smart-research/SKILL.md を作ってスキル登録
  • 会話で「徹底調査して」と言うだけの世界へ

ツールを作って終わりじゃなく、普段の会話に溶け込むまで自動化するのがポイント。コマンドを打つ時点で負け。「調べて」と言ったら勝手に最適な方法で動く——それが自分にとっての理想形だった。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?