ローカルAIエージェントを構築する
ローカルAIエージェントとは、自分のハードウェア上で完全に動作する自律ループのことです。オープンウェイトモデル(Ollama や LM Studio が提供)が何をすべきかを判断し、あなたが与えたツールを呼び出し、その結果を読み取り、タスクが完了するまで動き続けます — しかも何ひとつマシンの外に出ません。クラウドAPIなし、呼び出しごとの請求なし、インターネット不要。ただし注意点があります。ラップトップで動かせるほど小さいモデルは、難しい推論や長期的な計画立案においてフロンティアモデルより劣り、その信頼性と安全性はあなた自身が担うことになります。このページでは、ローカルエージェントを正直に評価した上での採用理由、最小限のアーキテクチャ、実際にローカルで動くもの、そして最初の1台を作るための現実的な道筋を扱います。
- なぜローカルで動くエージェントを構築するのか、そしてクラウドAPIエージェントと比べた正直なトレードオフを理解する
- 最小限のアーキテクチャを理解する: ローカルモデル + ツール呼び出しループ + ツール + ガードレール/停止条件
- 実際にツール利用やエージェント的な作業ができるローカルモデルを選ぶ
- ローカルエンドポイントを指すことでローカル動作するエージェントフレームワークを知る(LangGraph、CrewAI、OpenAI Agents SDK)
- ワンショットのツール呼び出しからガード付きループまで「シンプルに始める」道筋をたどる
- 自律ループが本当の損害を起こせないよう、エージェントをサンドボックス化し予算上限を設ける
なぜローカルエージェントを構築するのか(そしてしないべきとき)
通常のツール利用エージェントはクラウドモデルを呼び出します。ローカルエージェントは、そのクラウド呼び出しを自分のマシン上で動くモデルに置き換えます。ある程度の能力を手放し、いくらかの運用負担を引き受ける代わりに、他の方法では得がたい4つのものが手に入ります。
- プライバシー — プロンプト、ツール入力、ツール出力がマシンの外に出ることは一切ありません。規制対象、機密性が高い、あるいはエアギャップ環境のチームがローカルエージェントを構築する理由はまさにこれです。データが物理的に第三者へ渡りようがないのです。
- オフライン — インターネット不要、API依存なし、プロバイダーの障害なし。エージェントはディスク上のファイルであり、飛行機の中でもファイアウォールの背後でも動きます。
- 呼び出しごとのコストなし — エージェントループは1タスクあたり数十回のモデル呼び出しを行うことがあります。ローカルではそれらの呼び出しは「無料」です(トークンではなく電気代とハードウェアで支払います)。なのでメーターを気にせず反復させられます。
- 完全な制御 — 正確なモデルバージョンを固定し、挙動をカスタマイズし、レート制限や利用規約の突然の変更なしに動かせます。
正直なトレードオフ — コミットする前にこれらを冷静に見極めてください。
- 能力ギャップ。 エージェントで最も難しいのは推論です。多段階の作業を計画し、失敗したツール呼び出しから回復し、いつ止めるべきかを知ること。ラップトップで動かせるモデル(おおよそ1B〜14Bパラメータ)は、この点でフロンティアモデルより明らかに劣ります。シンプルで範囲の狭いループはローカルでもよく機能しますが、長期的でオープンエンドなタスクこそ、ローカルエージェントが最も脱線しやすい領域です。
- 信頼性と安全性はあなたの責任。 あなたのためにフィルタリング、監視、ガードレール設定をしてくれるプロバイダーはいません。エージェントが永遠にループしたり、間違ったツールを呼んだり、破壊的なアクションを取ったりしたら、それはあなたの設計の責任です。(下の警告を参照 — ここは人々が過小評価する部分です。)
- ハードウェアの制約。 より大きく賢いモデルは、ほとんどのマシンが持つよりも多くのRAM/VRAMを必要とします。たいていは存在する中で最良のモデルではなく、自分のハードウェアで動かせる中で最も能力の高いモデルを選ぶことになります。
確かな経験則: ローカルで始め、タスクが要求したときにエスカレーションする。 プライベート/オフライン/大規模でも安価な作業や、範囲の狭いループにはローカルエージェントを使い、タスクが本当に追加の推論を必要とするときにはフロンティアAPIエージェントに手を伸ばします。下のアーキテクチャはどちらでも同一です — 変わるのはエンドポイントだけ — なので、ローカルでプロトタイプを作り、後でモデルを差し替えられます。
最小限のアーキテクチャ
エージェントを核まで削ぎ落とすと、4つの部品があります。それ以外のすべては、これらの上に乗った便利機能です。
┌─────────────────────────────────────────────┐
│ │
│ 1. LOCAL MODEL ──► decides next action │
│ (Ollama / LM Studio, tool-capable) │
│ │ │
│ ▼ │
│ 2. TOOL-CALLING LOOP │
│ parse the model's tool request, │
│ run it, feed the result back │
│ │ │
│ ▼ │
│ 3. TOOLS ──► search / read file / │
│ run code / call an API (your code) │
│ │ │
│ ▼ │
│ 4. GUARDRAIL / STOP CONDITION │
│ max steps, budget, approval gate, │
│ "done" check ──► exit the loop │
│ │
└─────────────────────────────────────────────┘
- ツール呼び出しに対応したローカルモデル。 モデルは、単にチャットするだけでなく、ツールを呼び出すための構造化されたリクエスト(別名関数呼び出し)を出力できる必要があります。Ollama はこれを自身のAPIと、
http://localhost:11434/v1にあるOpenAI互換エンドポイントの両方を通じて公開しているため、OpenAI形式を話すフレームワークならどれでもローカルモデルを動かせます。 - ツール呼び出しループ。 エージェントの心臓部です。会話をモデルに送り、ツールを呼び出すよう求めてきたか確認し、そのツールを実行し、結果を追加し、繰り返します。モデルがツールを要求せずに回答したら、ループは終了します。
- ツール。 モデルに公開する単なる関数です — Web検索、ファイル読み取り、シェルコマンド実行、データベースへのクエリ、APIの呼び出し。各ツールには名前、説明、型付きの入力スキーマがあり、モデルはいつどう使えばよいかを知ります。
- ガードレール/停止条件。 自律性には必須です。最低限、ループが永遠に走れないようにする最大ステップ上限、そして — 書き込み、削除、支払い、送信を行うものすべてには — 承認ゲートかサンドボックスを設けます。これがなければ、それはエージェントではなく、ファイルアクセス権を持った無限ループです。
ステップ2のループは本当に小さなものです。ローカルの Ollama エンドポイントに対する Python の擬似コードで示すと、こうなります。
最小限のローカルエージェントループ(Python擬似コード、ローカルOllamaを指す)
from openai import OpenAI
# Point the OpenAI client at your LOCAL Ollama endpoint — nothing leaves the machine
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
tools = [{
"type": "function",
"function": {
"name": "read_file",
"description": "Read a UTF-8 text file and return its contents",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
},
}]
def run_tool(name, args):
if name == "read_file":
# GUARDRAIL: only allow reads inside a sandboxed directory
return safe_read(args["path"])
raise ValueError(f"unknown tool: {name}")
messages = [{"role": "user", "content": "Summarize ./notes/today.md"}]
for step in range(8): # GUARDRAIL: hard step cap
resp = client.chat.completions.create(
model="llama3.1", messages=messages, tools=tools,
)
msg = resp.choices[0].message
messages.append(msg)
if not msg.tool_calls: # STOP: model answered, we're done
print(msg.content)
break
for call in msg.tool_calls:
result = run_tool(call.function.name, json.loads(call.function.arguments))
messages.append({
"role": "tool", "tool_call_id": call.id, "content": str(result),
})
else:
print("Stopped: hit the step cap without finishing.")これがパターンのすべてです。フレームワークはこの上にメモリ、リトライ、マルチエージェントのオーケストレーション、トレーシング、構造化された状態を加えます — しかしそのどれもが、このループのより堅牢なバージョンにすぎません。
どのローカルモデルがエージェント的/ツール利用の作業に向くか
すべてのオープンウェイトモデルがエージェントを動かせるわけではありません。基準は信頼できるツール呼び出しです。モデルは整形式のツールリクエストを一貫して出力し、正しいツールを選び、引数を幻覚しないことが求められます。選ぶ際の2つのフィルター。
- ツール対応モデルでなければならない。 Ollama はこれらにタグを付けています — 思い込みではなく、Tools カテゴリで最新の一覧を見てください。確実なローカルツール利用でよく挙げられるモデルには Qwen と Llama の指示チューニング済みファミリーがありますが、最良の選択は四半期ごとに動きます。
- コンテキストの余裕を持ってハードウェアに収まらなければならない。 エージェントループは長いメッセージ履歴を蓄積します(すべてのツール結果が追加されます)。なので重みと潤沢なコンテキストウィンドウの両方がメモリに収まる必要があります。余裕を持って収まり高速に動く小さめのモデルは、ディスクにスワップしてループの途中で失速する大きめのモデルにしばしば勝ります。
決め手となる一手はベンチマークを読むことではありません — 自分のタスクの小さな評価(eval)を、候補となる2〜3個のモデルに対して実行することです。リーダーボードのトップを取るモデルでも、エージェントが必要とする特定のツールでは信頼できないことがあります。自分のループ上で測定しましょう。
ローカルで動作するフレームワーク
上のループを自前で組むこともでき、最初のエージェントにはそれが学ぶうえで素晴らしい方法です。実用的なものになると、フレームワークがリトライ、メモリ、マルチエージェント調整、トレーシングを提供してくれます。重要な事実: 人気のエージェントフレームワークはモデル非依存です — モデルがクラウドにあるか localhost にあるかを気にせず、正しいエンドポイントを指してさえいればよいのです。
- LangGraph — ステートフルなエージェントのための低レベルなオーケストレーションフレームワーク(永続的な実行、永続化、ヒューマン・イン・ザ・ループ)。モデル非依存で、LangChain の Ollama 連携を介して回避策なしにローカルモデルへ接続できます。エージェントの状態グラフを明示的に制御する必要があるときに適しています。
- CrewAI — 1つ以上のロールベースのエージェント(「クルー」)をオーケストレーションする高レベルなフレームワーク。LiteLLM を介してモデル非依存で、
LLM(model="ollama/llama3.1", base_url="http://localhost:11434")でエージェントをローカルモデルに向けられます。複数の協調するエージェントを素早く組み立てたいときに適しています。 - OpenAI Agents SDK — 軽量なマルチエージェントフレームワーク。名前に反してプロバイダー非依存です。LiteLLM 連携を介して、OpenAI のモデルではなくローカルの Ollama モデルへ向けられます。OpenAI のエージェントの使い心地をローカルバックエンドで得たいときに適しています。
3つすべてをつまみ食いするのではなく、1つのフレームワークを選んでよく学びましょう。概念(エージェント、ツール、ループ、状態)は転用できます。APIは細部にすぎません。
最初のローカルエージェントを構築する
現実的な道筋は、「ループがまったくない」状態から「ガード付き自律ループ」へ、意図的なステップで進みます。ステップ4に飛ばさないでください — ローカルエージェントで人々がぶつかる失敗のほとんどは、弱いモデルに早すぎる段階で自由を与えすぎることから来ます。
- Ollama をインストールし(「ローカルでモデルを動かす」を参照)、ツール用にタグ付けされたモデルをプルします。例: ollama pull llama3.1。http://localhost:11434 で提供され、ollama list に表示されることを確認します。まだエージェントはありません — ただ呼び出せるモデルがあるだけです。
- 1つのツールを定義した(例: get_time や read_file 関数)単一のリクエストを送り、モデルが本当に有効な引数を持つ整形式のツール呼び出しを返すか確認します。モデルがきれいなツール呼び出しを1回でも確実にできないなら、ループでは生き残れません — 後ではなく今、モデルを切り替えましょう。
- 上の PromptCard の「実行→結果を返す」ループを、ハードな最大ステップ上限(6〜8から開始)とともに追加します。読み取り専用ツールで、小さく範囲の狭いタスクを与えます。すべてのステップが出力されるのを見て、モデルの推論を確認し、ループしたりツールを誤用したりするのを捕まえられるようにします。
- ここで初めて、状態を変えるツール(ファイルを書く、コマンドを実行する、お金のかかるAPIを呼ぶ)を導入します。それぞれを承認プロンプトの背後に置くか、サンドボックス/コンテナで実行し、予算または実時間の上限を加えます。失敗モードを意図的にテストします: 完了できないタスクを与えて、きれいに停止することを確認してください。
- 自前のループが動いたら、ローカルエンドポイントを指す LangGraph、CrewAI、または OpenAI Agents SDK に移植します。リトライ、メモリ、マルチエージェントのオーケストレーションが無料で手に入り — モデルはあなたのマシン上の、まさにその場所にとどまります。
- ツールを持つローカルエージェントは、それでも本当のアクションを取れます — サンドボックス化し、破壊的なステップには承認を必須にし、ループ/予算に上限を設けてください。
理解度チェック
理解度チェック
0/4- ローカルエージェントは、クラウドモデルを自分のマシン上のオープンウェイトモデルに置き換えた標準のツール利用ループ — プライベートで、オフラインで、無料で反復できる。
- 最小限のアーキテクチャ = ツール対応のローカルモデル + ツール呼び出しループ + ツール + ガードレール/停止条件。ループそのものは小さい。
- Ollama の OpenAI互換エンドポイント(/v1)はツール呼び出しに対応しているため、OpenAI形式のフレームワークならどれでもローカルモデルを動かせる。
- LangGraph、CrewAI、OpenAI Agents SDK はモデル非依存 — クラウドの代わりにローカルエンドポイントに向ける。
- ハードウェアに収まるツール対応モデルを選び、リーダーボードではなく自分のタスクの小さな評価で決める。
- 能力ギャップについて正直になり、安全性を自分で担う: ループと予算に上限を設け、ツールをサンドボックス化し、破壊的なものすべてに承認を必須にする。
- シンプルに始める: きれいなツール呼び出し1回 → 境界付きの読み取り専用ループ → ガード付きの破壊的ツール →(任意で)フレームワーク。