マルチエージェント・オーケストレーションとは
単一のAIエージェントでは対応しきれない複雑なタスクを、複数の専門エージェントが連携して処理する仕組みがマルチエージェント・オーケストレーションです。Google の Antigravity エディタでは、エージェント機能を活用してタスクの分割・委任・統合をノーコードで構築できますが、より高度なユースケースではコードベースのオーケストレーション層が必要になります。
設計パターン1:ルーターパターン
ルーターパターンは、入力を解析して最適なエージェントに振り分ける方式です。カスタマーサポートのように、問い合わせ内容に応じて担当を切り替えるシナリオに適しています。
// router-agent.ts
// ルーターパターンの実装例 — 入力を分類して適切なエージェントに委任
interface AgentRoute {
name: string;
description: string;
handler: (input: string) => Promise<string>;
}
class RouterAgent {
private routes: AgentRoute[] = [];
addRoute(route: AgentRoute) {
this.routes.push(route);
}
async classify(input: string): Promise<string> {
// キーワードベースの簡易分類(本番では LLM による分類を推奨)
const keywords: Record<string, string[]> = {
"billing-agent": ["請求", "支払い", "料金", "プラン", "billing", "payment"],
"technical-agent": ["エラー", "バグ", "動かない", "設定", "error", "bug"],
"general-agent": ["質問", "使い方", "とは", "教えて", "how", "what"],
};
for (const [agentName, words] of Object.entries(keywords)) {
if (words.some((w) => input.toLowerCase().includes(w))) {
return agentName;
}
}
return "general-agent";
}
async route(input: string): Promise<string> {
const targetName = await this.classify(input);
const target = this.routes.find((r) => r.name === targetName);
if (!target) {
return `No handler found for: ${targetName}`;
}
console.log(`[Router] Routing to: ${target.name}`);
return target.handler(input);
}
}
// 使用例
const router = new RouterAgent();
router.addRoute({
name: "billing-agent",
description: "請求・支払い関連の問い合わせ",
handler: async (input) => `[Billing] Processing: ${input}`,
});
router.addRoute({
name: "technical-agent",
description: "技術的な問題の解決",
handler: async (input) => `[Tech] Investigating: ${input}`,
});
router.addRoute({
name: "general-agent",
description: "一般的な問い合わせ対応",
handler: async (input) => `[General] Responding to: ${input}`,
});
const result = await router.route("支払い方法を変更したい");
console.log(result);
// 期待出力: [Router] Routing to: billing-agent
// [Billing] Processing: 支払い方法を変更したいルーターパターンのポイントは、各エージェントの責務を明確に分離することです。ルーター自体はタスクを実行せず、振り分けのみを行います。
設計パターン2:パイプラインパターン
パイプラインパターンは、複数のエージェントが順次処理を行い、前のエージェントの出力を次のエージェントの入力として受け渡す方式です。データ変換やコンテンツ生成のワークフローに適しています。
// pipeline-agent.ts
// パイプラインパターン — エージェントを直列に接続して処理を連鎖
interface PipelineStage {
name: string;
process: (input: string, context: Record<string, unknown>) => Promise<string>;
}
class AgentPipeline {
private stages: PipelineStage[] = [];
addStage(stage: PipelineStage) {
this.stages.push(stage);
return this; // メソッドチェーン対応
}
async execute(input: string): Promise<{ result: string; log: string[] }> {
let current = input;
const context: Record<string, unknown> = {};
const log: string[] = [];
for (const stage of this.stages) {
const start = Date.now();
try {
current = await stage.process(current, context);
const elapsed = Date.now() - start;
log.push(`✓ ${stage.name} (${elapsed}ms)`);
} catch (error) {
log.push(`✗ ${stage.name}: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
return { result: current, log };
}
}
// コンテンツ生成パイプラインの例
const contentPipeline = new AgentPipeline();
contentPipeline
.addStage({
name: "research-agent",
process: async (topic, ctx) => {
// リサーチエージェント: トピックに関する情報を収集
ctx.sources = ["source1.com", "source2.com"];
return `Research findings for "${topic}": Key points A, B, C gathered from 2 sources.`;
},
})
.addStage({
name: "writing-agent",
process: async (research, ctx) => {
// ライティングエージェント: リサーチ結果から記事を生成
ctx.wordCount = 500;
return `Draft article based on: ${research}\n\n[500 words of content...]`;
},
})
.addStage({
name: "review-agent",
process: async (draft, ctx) => {
// レビューエージェント: 記事の品質チェックと修正
ctx.reviewScore = 0.92;
return draft.replace("[500 words of content...]", "[Reviewed and polished content]");
},
});
const output = await contentPipeline.execute("AIエージェントの最新動向");
console.log(output.log.join("\n"));
// 期待出力:
// ✓ research-agent (150ms)
// ✓ writing-agent (320ms)
// ✓ review-agent (180ms)パイプラインパターンでは context オブジェクトを共有することで、各ステージ間でメタデータを受け渡せます。エラーが発生した場合はその時点でパイプラインを停止し、ログに記録します。
設計パターン3:競合解決パターン
競合解決パターンは、同じタスクを複数のエージェントが並列で処理し、最も良い結果を採用する方式です。回答の精度が重要なシナリオや、異なるアプローチを比較したい場合に有効です。
// consensus-agent.ts
// 競合解決パターン — 複数エージェントの結果から最良を選択
interface CompetingAgent {
name: string;
solve: (task: string) => Promise<{ answer: string; confidence: number }>;
}
class ConsensusOrchestrator {
private agents: CompetingAgent[] = [];
addAgent(agent: CompetingAgent) {
this.agents.push(agent);
}
async resolveByConfidence(task: string): Promise<{
winner: string;
answer: string;
confidence: number;
allResults: { name: string; confidence: number }[];
}> {
// 全エージェントを並列実行
const results = await Promise.allSettled(
this.agents.map(async (agent) => {
const result = await agent.solve(task);
return { name: agent.name, ...result };
})
);
const successful = results
.filter((r): r is PromiseFulfilledResult<{ name: string; answer: string; confidence: number }> =>
r.status === "fulfilled"
)
.map((r) => r.value);
if (successful.length === 0) {
throw new Error("All agents failed");
}
// 最も高い信頼度の結果を採用
const best = successful.reduce((a, b) => (a.confidence > b.confidence ? a : b));
return {
winner: best.name,
answer: best.answer,
confidence: best.confidence,
allResults: successful.map((s) => ({ name: s.name, confidence: s.confidence })),
};
}
}
// 使用例
const orchestrator = new ConsensusOrchestrator();
orchestrator.addAgent({
name: "fast-agent",
solve: async (task) => ({
answer: `Quick analysis of: ${task}`,
confidence: 0.75,
}),
});
orchestrator.addAgent({
name: "thorough-agent",
solve: async (task) => ({
answer: `Detailed analysis of: ${task}`,
confidence: 0.95,
}),
});
const consensus = await orchestrator.resolveByConfidence("2026年のAI市場予測");
console.log(`Winner: ${consensus.winner} (confidence: ${consensus.confidence})`);
console.log(`All: ${JSON.stringify(consensus.allResults)}`);
// 期待出力:
// Winner: thorough-agent (confidence: 0.95)
// All: [{"name":"fast-agent","confidence":0.75},{"name":"thorough-agent","confidence":0.95}]Antigravity エディタとの統合
Antigravity のエージェント機能では、上記のパターンをビジュアルエディタ上で組み合わせることができます。エディタの「カスタムコード」ブロックに TypeScript を記述し、エージェント間のデータフローをノードベースで接続する方式です。
本番環境では以下の点に注意してください。
タイムアウト管理として、各エージェントに AbortSignal.timeout() を設定し、応答が返らない場合はフォールバックに切り替えます。リトライ戦略では、一時的なエラーに対して指数バックオフでリトライする仕組みを組み込みます。オブザーバビリティとして、各エージェントの実行時間・成功率・エラー率をログに記録し、ボトルネックを特定できるようにします。
実装のベストプラクティス
マルチエージェントシステムを構築する際に守るべき原則があります。
単一責任の原則: 1つのエージェントは1つの明確な役割のみを持つ設計にします。「何でもできるエージェント」は品質が低下しやすく、デバッグも困難です。
フェイルセーフ設計: 任意のエージェントが失敗してもシステム全体が停止しないよう、フォールバックパスを用意します。上記のパイプラインパターンでは try-catch でエラーをログに記録し、競合解決パターンでは Promise.allSettled で部分的な失敗を許容しています。
コンテキストの最小化: エージェント間で受け渡すデータは必要最小限にします。巨大なコンテキストオブジェクトはレイテンシを悪化させ、トークンコストも増加します。
全体を振り返って
マルチエージェント・オーケストレーションの3つの基本パターン(ルーター、パイプライン、競合解決)を紹介しました。Antigravity エディタのエージェント機能と組み合わせることで、ノーコードのビジュアル設計とコードベースの高度な制御を両立できます。
まずは単純なルーターパターンから始め、タスクの複雑さに応じてパイプラインや競合解決を追加していくアプローチがおすすめです。関連記事としてカスタムエージェント作成ガイドやWebスクレイピングエージェントも参考にしてください。