本記事は OctoTools: An Agentic Framework with Extensible Tools for Complex Reasoning (arXiv:2502.18145) の解説記事です。
論文概要(Abstract)
OctoTools は、複雑な推論タスクにおける複数ツールの協調利用を効率化するエージェントフレームワークである。従来のエージェントシステムがツール呼び出しを固定的かつ直列に実行するのに対し、OctoTools は標準化された Tool Card によるツール定義と、DAG(有向非巡回グラフ)ベースの並列実行エンジンを提供する。著者らは 16 のベンチマークで評価を行い、並列実行モードが直列実行と同等の精度(68.1% vs 68.4%)を維持しながら推論時間を 47% 削減したと報告している。
この記事は Zenn記事: LangGraph×MCPツール呼び出しレイテンシ最適化:社内検索エージェントの応答を5倍速くする の深掘りです。
情報源
- arXiv ID: 2502.18145
- URL: https://arxiv.org/abs/2502.18145
- 発表年: 2025
- 分野: cs.AI, cs.CL
背景と動機(Background & Motivation)
LLM エージェントが複数のツールを協調利用するシナリオでは、2 つの根本的な課題が存在する。
課題1: ツール統合の硬直性
従来のフレームワーク(ReAct、Toolformer 等)では、ツールの追加・変更にフレームワーク本体のコード修正が必要であった。新しいデータソースや API を接続するたびにエージェントの実装を変更する運用は、MCP サーバが増加する環境ではスケールしない。
課題2: 直列実行による不要な待機
多くのエージェントはツール呼び出しを 1 つずつ直列に実行する。しかし、独立したツール呼び出し(例: Confluence 検索と Slack 検索)を並列に実行すれば、最も遅いツールの実行時間だけで済む。Zenn 記事では ToolNode の自動並列実行を活用して 5.2 秒→ 2.5 秒(52%削減)を達成しているが、OctoTools はこれをより体系的な DAG スケジューリングに拡張している。
主要な貢献(Key Contributions)
- 貢献1: Tool Card スキーマによるツール定義の標準化を提案し、コード変更なしでのツール追加を実現している
- 貢献2: LLM プランナーがツール呼び出し DAG を生成し、asyncio ベースの Executor が依存関係を解析して並列実行するアーキテクチャを設計している
- 貢献3: 16 のベンチマークにおいて、並列実行が直列実行と同等の精度を維持しつつ推論時間を 47% 削減することを実証している
技術的詳細(Technical Details)
Tool Card スキーマ
OctoTools のツール定義は JSON 形式の Tool Card で標準化される。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"tool_name": "confluence_search",
"description": "Confluenceの技術ドキュメントを検索する",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"max_results": {"type": "integer", "default": 5}
},
"required": ["query"]
},
"output_schema": {
"type": "array",
"items": {"type": "object"}
},
"dependencies": [],
"execution_mode": "parallel"
}
Tool Card は JSON ファイルとして管理され、フレームワークのコードを変更せずにツールの追加・削除が可能である。これは MCP サーバのツールスキーマ定義と類似した設計思想に基づいている。
DAGベースの並列実行エンジン
OctoTools の核心は、ツール呼び出しを DAG として表現し、依存関係のないノードを並列にディスパッチする Executor にある。
Planner(計画フェーズ)
LLM プランナーはタスクを分析し、ツール呼び出しの実行計画を DAG として出力する。
\[\text{DAG} = (V, E) \quad \text{where} \quad V = \{v_1, ..., v_n\} \text{ (ツール呼び出し)}, \quad E \subseteq V \times V \text{ (依存関係)}\]各ノード $v_i$ はツール名と引数を持ち、エッジ $(v_i, v_j)$ は「$v_i$ の結果が $v_j$ の入力に必要」という依存関係を表す。
Executor(実行フェーズ)
Executor は以下のアルゴリズムで DAG を実行する。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import asyncio
from collections import defaultdict
async def execute_dag(
dag: dict[str, list[str]], # node -> dependencies
tool_map: dict[str, callable],
args_map: dict[str, dict],
) -> dict[str, any]:
"""DAGの依存関係を解析し、並列実行可能なノードを同時ディスパッチ"""
results: dict[str, any] = {}
in_degree = defaultdict(int)
for node, deps in dag.items():
in_degree[node] = len(deps)
# 依存なしノード(ready)を特定
ready = [n for n in dag if in_degree[n] == 0]
while ready:
# 並列実行
tasks = [
_execute_tool(tool_map[n], args_map[n])
for n in ready
]
batch_results = await asyncio.gather(*tasks)
# 結果を記録し、依存関係を更新
for node, result in zip(ready, batch_results):
results[node] = result
for successor in _get_successors(dag, node):
in_degree[successor] -= 1
# 次の ready ノードを特定
ready = [
n for n in dag
if in_degree[n] == 0 and n not in results
]
return results
async def _execute_tool(tool_fn: callable, args: dict) -> any:
"""単一ツールの非同期実行"""
return await tool_fn(**args)
オフライン vs オンラインプランニング
| プランニング方式 | 説明 | 並列度 | 適用場面 |
|---|---|---|---|
| オフライン | タスク全体を事前に DAG 化 | 高い | タスク構造が予測可能 |
| オンライン | ステップごとに次の行動を決定 | 低い | 動的・対話的タスク |
並列実行のスピードアップモデル
$k$ 個の独立ツール呼び出しの各レイテンシを $l_1, l_2, …, l_k$ とすると、理論的なスピードアップは以下の通りである。
\[S = \frac{L_{\text{sequential}}}{L_{\text{parallel}}} = \frac{\sum_{i=1}^{k} l_i}{\max_{i=1}^{k} l_i}\]ツール間のレイテンシが均等($l_i = l$ for all $i$)の場合、$S = k$ となり、線形スピードアップが得られる。実測ではオーバーヘッド(asyncio ディスパッチ、結果集約)により $S \approx 0.85k$ 程度になると著者らは報告している。
実験結果(Results)
16ベンチマークでの評価
著者らは 16 の異なるベンチマークで OctoTools を評価している(論文 Table 3 より)。
| 手法 | 平均精度 | 平均推論時間 |
|---|---|---|
| GPT-4o(ツールなし) | 53.2% | 2.1s |
| ReAct(直列) | 61.8% | 18.4s |
| OctoTools(直列) | 68.4% | 16.2s |
| OctoTools(並列) | 68.1% | 9.7s |
OctoTools(並列)は ReAct に対して精度 +6.3%、推論時間 -47% を達成している。
アブレーション実験
著者らのアブレーション分析(論文 Table 4 より):
| 構成要素 | 除去時の精度変化 |
|---|---|
| Tool Card | -8.2% |
| Planner(DAG生成) | -5.4% |
| 並列→直列 | -0.3%(精度差なし) |
並列実行は精度に影響を与えず、純粋にレイテンシのみを改善していることが確認されている。一方、Tool Card と Planner は精度に大きく寄与しており、ツール定義の標準化と実行計画の品質が重要であることが示されている。
実装のポイント(Implementation)
レート制限への対応
並列実行時に API レート制限に抵触する場合がある。著者らは max_parallel_calls=8 をデフォルトとし、セマフォによる同時実行数制御を推奨している。
1
2
3
4
5
6
7
8
9
import asyncio
MAX_PARALLEL = 8
_semaphore = asyncio.Semaphore(MAX_PARALLEL)
async def rate_limited_execute(tool_fn, args):
"""セマフォでAPI並列呼び出し数を制限"""
async with _semaphore:
return await tool_fn(**args)
LangGraph との統合
OctoTools の DAG 実行モデルは LangGraph の StateGraph と自然に対応する。
- DAG ノード → LangGraph ノード
- DAG エッジ → LangGraph エッジ(conditional edges で依存関係を表現)
- 並列ディスパッチ → LangGraph の
SendAPI による fan-out
Zenn 記事の build_parallel_search_agent パターンは、OctoTools の Executor の簡略版と位置づけられる。OctoTools はさらに DAG レベルの依存関係解析を行い、より粒度の細かい並列化を実現している。
Structured Output の重要性
Planner が DAG を JSON 形式で出力する際、LLM の structured output 能力が重要になる。著者らは、構造化出力に対応しない LLM では DAG 生成の失敗率が高いことを報告しており、Claude Sonnet 4 や GPT-4o など、structured output を安定して生成できるモデルの使用を推奨している。
実運用への応用(Practical Applications)
社内検索エージェントへの適用: Zenn 記事の社内検索シナリオ(Confluence + Slack + ベクトルDB)において、OctoTools の DAG 実行を適用すると、3 つの独立検索を並列化するだけでなく、「検索結果の統合」や「追加検索の判断」といった後続ステップの依存関係も明示的にモデル化できる。
MCP サーバとの親和性: OctoTools の Tool Card は MCP のツールスキーマと構造が類似しており、MCP サーバのツール定義から Tool Card を自動生成するアダプタの実装が容易である。
制約: オフラインプランニングはタスク構造が予測可能な場合に限定される。対話的なタスクや中間結果に依存して計画が変わるタスクでは、オンラインプランニングへのフォールバックが必要である。
関連研究(Related Work)
- ReAct (arXiv:2210.03629): Reasoning と Acting を交互に行うフレームワークであり、直列実行が基本である。OctoTools は ReAct の精度を維持しつつ並列化を実現している
- Scaling Agentic Behaviors (arXiv:2502.08538): sequential/parallel/hierarchical の 3 パラダイムを比較した研究であり、ツール使用タスクでの並列化で 3.1 倍のスピードアップを報告している。OctoTools の実験結果と整合する
- ToolHop (arXiv:2501.07728): マルチホップツール使用のベンチマークであり、ホップ数増加に伴う精度低下を報告している。OctoTools の DAG プランニングはホップ間の依存関係を明示化し、不要な直列実行を排除する
まとめと今後の展望
OctoTools は、Tool Card によるツール標準化と DAG ベースの並列実行により、エージェントのツール使用を効率化するフレームワークである。16 ベンチマークでの評価により、並列実行は精度に影響を与えず推論時間を 47% 削減できることが実証されている。
Zenn 記事の ToolNode 並列実行パターンを更に発展させたい場合、OctoTools の DAG スケジューリングアプローチは有力な選択肢となる。特に、ツール間の依存関係が複雑な場合(例: 検索→リランキング→回答生成のパイプライン内での部分的並列化)に効果を発揮する。
参考文献
- arXiv: https://arxiv.org/abs/2502.18145
- Code: https://github.com/octotools/octotools (MIT License)
- Related Zenn article: https://zenn.dev/0h_n0/articles/2929e45a5bf12b