6月27日、Towards Data Scienceが「From Local LLM to Tool-Using Agent」と題した記事を公開した。ローカルLLMをツール使用エージェントに仕立てる実装パターンを、動作するコードと実行トレース付きで解説するチュートリアルだ。
ローカルでLLMを動かすだけなら、Ollamaとモデルをダウンロードすればすぐできる。だが「チャット以外に何ができるか?」という疑問はすぐにやってくる。この記事はその疑問に正面から答える。
使用するスタックは以下の4つ:
- **Gemma 4 E4B**(Googleのエッジ向けLLM)
- **Ollama**(ローカルLLMサーバー)
- **OpenAI Agents SDK**(エージェントランタイム)
- **Tavily**(LLMアプリ向け検索APIのMCPサーバー)
目標は「ウェブ検索・情報収集・引用付き回答生成」をこなすミニ深層調査エージェントの構築だ。

なぜGemma 4 E4Bか
Gemma 4にはいくつかのバリアントがある。記事ではVRAM約8GBのNVIDIA RTX 2000 Ada Laptop GPUを搭載したマシンでE4Bバリアントを使用している。名称の「4」はGemmaのバージョン4を、「E4B」はエッジ(Edge)向けに最適化された4Bパラメータ相当の量子化モデルであることを示している。エッジやローカルでのAgentic用途を想定して設計されており、このユースケースに適している。VRAMが少ない場合は軽量なE2Bバリアントも選択肢になる。
ollama pull gemma4:e4b # 通常はこちら
ollama pull gemma4:e2b # VRAMが少ない場合
エージェントの構成:3つのパーツ
1. モデルのラッピング
ここが実装の核心だ。openaiクライアントのベースURLをOllamaのローカルエンドポイントに向けることで、OpenAI Agents SDKがローカルモデルを使えるようになる。
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel
client = AsyncOpenAI(
api_key="ollama", # プレースホルダー。Ollamaには不要
base_url="http://localhost:11434/v1",
)
model = OpenAIChatCompletionsModel(
model="gemma4:e4b",
openai_client=client,
)
api_key="ollama"はダミー値で、SDKがフィールドを要求するために入れている。実際にOpenAIへ通信するわけではない。
2. エージェントの指示文(System Prompt)
エージェントの振る舞いを定義するプロンプトは、検索の開始・追加検索の判断・引用付き回答の生成といった一連の研究行動を記述している。時事性のある質問に対応するため、現在日付を動的に埋め込む点が実用的だ。
from datetime import datetime
CURRENT_DATE = datetime.now().strftime("%B %d, %Y")
RESEARCH_AGENT_INSTRUCTIONS = f"""
[Role]
You are a concise research assistant.
[Task]
Answer the user's question by turning it into a small web research task.
Use the current date when interpreting time-sensitive questions: {CURRENT_DATE}.
...
""".strip()
3. TavilyのMCPツール接続
MCP(Model Context Protocol)はツール接続の標準的なインターフェースとして普及しつつある。TavilyのMCPサーバーに接続することで、エージェントはウェブ検索ツールを自律的に呼び出せるようになる。
from agents.mcp import MCPServerStreamableHttp
async with MCPServerStreamableHttp(
name="tavily",
params={"url": TAVILY_MCP_URL},
) as tavily_server:
agent = Agent(
name="Local Research Agent",
instructions=RESEARCH_AGENT_INSTRUCTIONS,
model=model,
mcp_servers=[tavily_server],
mcp_config={"include_server_in_tool_names": True},
)
result = await Runner.run(agent, RESEARCH_QUESTION, max_turns=MAX_TURNS)
async withブロックの中でAgentを生成・実行している点に注意が必要だ。MCP接続はこのコンテキスト内でのみ有効なため、ブロック外でエージェントを動かすと接続が切れる。
mcp_config={"include_server_in_tool_names": True}を設定すると、ツール名がtavily_searchではなくmcp_tavily__tavily_searchとして記録され、トレース時にどのMCPサーバー経由の呼び出しかが明確になる。
実行例:ワールドカップの試合を調査させる
記事では以下の質問で動作確認している:
"Which June 23, 2026 World Cup match had the biggest group-stage stakes, and why?"
エージェントの実行トレースは以下の通りだ:
01 | ToolCallItem | function_call | {"query":"World Cup 2026 group stage matches June 23, 2026 stakes"} → mcp_tavily__tavily_search
02 | ToolCallOutputItem | | (検索結果)
03 | MessageOutputItem | message | (最終回答)
1回の検索で十分な証拠が集まったため、エージェントは追加検索なしで回答を生成した。エージェントが出力した最終回答の一部を示す:
The match with the biggest group-stage stakes on June 23, 2026, was Colombia vs. DR Congo.
...
- FIFA: https://digitalhub.fifa.com/...
- Yahoo Sports: https://sports.yahoo.com/...
引用付きで根拠を示す形式になっており、「記憶に頼らず、検索結果に基づいて回答する」というプロンプト設計が機能している。
スタックの代替選択肢
記事では「このスタックが唯一の選択肢ではない」と明記されている。各コンポーネントの代替として以下が挙げられている:
- Ollamaの代わりに:LM Studio、llama.cpp — GUIやより細かいモデル設定を好む場合の選択肢
- Gemma 4の代わりに:Qwenファミリー等 — ツール呼び出し対応であれば同じ構成で差し替えられる
- OpenAI Agents SDKの代わりに:Google、Anthropicのエージェントフレームワーク — ベンダーのエコシステムに合わせて選べる
- Tavilyの代わりに:MCP対応の他ツール — 検索以外のデータソースやAPIもMCP経由で接続できる
この実装パターンは「ローカルモデル × エージェントランタイム × 外部ツール」の汎用的な組み合わせとして再利用できる。Tavilyを別のMCPツールに差し替えれば、調査エージェント以外の用途にも展開できる設計だ。
※編集部の考察:この構成の最大の利点は、OpenAI Agents SDKのベースURLを切り替えるだけでローカルモデルを組み込める点にある。エージェントランタイム側のコードをほぼ変更せずにモデルを差し替えられるため、将来的にクラウドモデルへの移行や複数モデルの比較検証も容易になる。
詳細はFrom Local LLM to Tool-Using Agentを参照していただきたい。




