AgenticWorkerz
記事一覧に戻る
マルチエージェントアーキテクチャ設計:3マシン構成の実践
アーキテクチャ11 min read2026-03-15

マルチエージェントアーキテクチャ設計:3マシン構成の実践

Mac Studio(Claude Code)+ STG VM(9エージェント)+ DEV VM(Strapi)の3マシン構成を設計・運用してわかった、オーケストレーターとワーカーの責務分離パターン。

S
Shintaku
AI Architect

なぜ3マシン構成なのか

「AIエージェントチーム」を設計するとき、最初に直面するのが「どこで何を動かすか」という問題です。全部同じマシンで動かすのがシンプルですが、実際に運用してみると責務の分離が重要だとわかりました。

現在の構成は以下の通りです:

  • Mac Studio(192.168.68.120): 制御端末。Claude Code がここで動作し、SSH で VM を遠隔操作
  • STG VM(192.168.68.72): Ubuntu 24.04。9体のエージェントが常駐し、RAGパイプラインを担う
  • DEV VM(192.168.68.210): Ubuntu 24.04。Strapi CMS・開発環境

オーケストレーター / ワーカーパターン

最も基本的なパターンは「指揮者(オーケストレーター)」と「実行者(ワーカー)」の分離です。

  • Aira(オーケストレーター): タスクを受け取り、分解し、適切なワーカーに委譲する
  • KIKI(モニター): システム全体の健全性を監視する
  • Haru(Reranker): 検索結果の品質評価に特化する
// オーケストレーターの基本構造(概念コード)
const orchestrator = new Agent({
  model: "claude-opus-4-6",
  systemPrompt: "タスクを受け取り、専門エージェントに委譲せよ",
  tools: [delegateToWorker, monitorProgress, collectResults],
});

// ワーカーへの委譲
async function delegateToWorker(workerName, task) {
  const workerUrl = AGENT_URLS[workerName];
  const res = await fetch(`${workerUrl}/api/task`, {
    method: 'POST',
    body: JSON.stringify({ taskId: uuid(), type: task.type, payload: task.payload })
  });
  return res.json();
}

エージェントの独立性設計

各エージェントは独立したLinuxユーザーアカウントと、独立した20GB VDIを持っています。これは「隣のエージェントのファイルを見ない」というルールを物理的に強制するためです。

/mnt/agent-aira/ 20GB ext4(Aira 専用)
/mnt/agent-kiki/ 20GB ext4(KIKI 専用)
/mnt/agent-riku/ 20GB ext4(Riku 専用)
# 各マウントポイントに code/ data/ logs/ workspace/ が存在

RAGパイプラインとしてのデータフロー

ユーザーのクエリは以下の順序で処理されます:

  1. Aira がクエリを受け取り、Sen に振り分け判断を依頼
  2. Sen がクエリの意図を解析し、「ベクトル検索が必要」と判断
  3. Sora がベクトルDBに対して類似検索を実行
  4. Haru が検索結果を再ランキングして品質を向上
  5. Tomo が回答候補の幻覚チェック(出典確認)を実行
  6. Niko が最終回答を生成(ストリーミング)

監視:KIKIのヘルスチェック

// kiki/health-check.js(抜粋)
const AGENTS = [
  { name: 'aira', port: 9101 },
  { name: 'riku', port: 9103 },
  // ... 9体分
];

async function checkAllAgents() {
  const results = await Promise.allSettled(
    AGENTS.map(async (agent) => {
      const res = await fetch(
        `http://localhost:${agent.port}/api/health`,
        { signal: AbortSignal.timeout(3000) }
      );
      return { ...agent, status: 'running', health: await res.json() };
    })
  );
  return results.map(r =>
    r.status === 'fulfilled' ? r.value : { name: r.reason.agent, status: 'down' }
  );
}

3週間の運用で学んだこと

  • エージェントの専門化は段階的に進める。最初は全員がAiraのコピーでも構わない
  • ログの肥大化は想定より深刻。AIエージェントはオペレーション数が多いため、ログローテーションは必須
  • 障害の局所化:VDIを分離しておくと、1エージェントが止まっても他は動き続ける
  • Dashboard(:8080) を作ることで、全体状態の把握コストが大幅に下がる
#マルチエージェント#アーキテクチャ#RAG#VirtualBox

関連記事