前書き
私は普段 Claude や Codex など、幾つかのサービスを契約して使っていますが、やっぱり料金が高いです。大学生のころ借りていたアパートの家賃より高いかもしれません![]()
コーディングが有料になっていくと、「AI がないと効率が悪い、でも AI がお金がかかる」という矛盾が出てきて、ちょっとモヤっとするんですよね![]()
![]()
そこで試してみたのが、ローカル LLM(Gemma 4)+ Ollama + Mastra Harness の組み合わせです。全部無料で使えて、自分のコーディングエージェント簡単に作れます。
コーディングエージェントの構成要素
まず何が必要かを整理します。
| 役割 | 選んだもの | 理由 |
|---|---|---|
| モデル | Gemma 4 12B | Google の OSS モデル、ローカル実行できるサイズ感 |
| ランタイム | Ollama | Mac でモデルをそのまま動かせる |
| エージェント基盤 | Mastra Harness | セッション管理・モード切替が組み込み済み |
| プロバイダー | ollama-ai-provider-v2 | Mastra の Agent から Ollama のモデルを呼ぶためのプロバイダー |
Gemma 4 は 2026 年 3 月に公開されたモデルで、今回使う 12B は 6 月に追加されたばかり。12B サイズならローカルでも動く、というのが大きかったです。
ちなみに今回の検証環境は MacBook Pro(Apple M4 、メモリ 24GB) です。
gemma4:12b はだいたい 7.6GB なので、メモリ 24GB なら余裕をもって動かせます。
逆に 26B以上のクラスはこのマシンだと厳しいので、まずは 12B から始めることにしました![]()
エージェントの部分は Mastra の Harness を使えば作れそうなので、この構成で行くことにしました。
Gemma 4 とは
Gemma 4 は Google が公開した OSS モデルです。E2B・E4B・12B・26B・31B と幅広いサイズ展開があって、12B ならそこそこのスペックの Mac でも動きます。
ライセンスは Apache 2.0 で、商用利用も OK です。
用途としては、テキスト生成だけでなく画像も扱える マルチモーダル対応で、推論やコーディング、長文の読み込み(12B は 256K トークンのコンテキスト)が得意です。
チャットボット、要約、コード補助、ドキュメント解析あたりが定番で、今回はこの中の「コード補助」を狙って、ローカルのコーディングエージェントの頭脳として使います。
Ollama のインストール
Ollama は ローカルで LLM を動かすためのランタイムです。Mac/Linux/Windows に対応しています。
インストールは Homebrew 一発でOKです。
brew install ollama
Homebrew を使わない場合は、https://ollama.com からインストーラーをダウンロードできます。
Homebrew で入れた場合は、モデルを操作する前に Ollama のサーバーを起動しておきます。別ターミナルで動かしっぱなしにしておくと楽です。
ollama serve
brew services start ollama でバックグラウンド起動にしてもOKです。公式インストーラーの macOS アプリ版を使っている場合は、アプリがサーバーを自動起動するのでこの手順は不要です。
サーバーが起動できたら、Gemma 4 のモデルをダウンロードします。12B は数 GB あるので、ダウンロードに少し時間がかかります。
ollama pull gemma4:12b
ダウンロード完了したら、まずターミナルで動作確認します。
ollama run gemma4:12b
ターミナル上でそのまま会話できるので、「こんにちは」と打ち込んでみてください。
返事が返ってきたら OK です![]()
通常の Mastra から Gemma を呼び出す
次は、Mastra エージェントから gemma4:12bを使ってみます。
Mastra は、TypeScript で AI エージェントやワークフローを作るためのフレームワークです
Mastra プロジェクトを作る
まずは Mastra の新規プロジェクトを用意します。
npm create mastra@latest
実行するといくつか設定を聞かれますが、今回の動作には影響しないため、すべてお好みで選択して問題ありません。![]()
プロジェクト初期化ができたら、そのディレクトリに入って、
Ollama とつなぐためのプロバイダー ollama-ai-provider-v2 を追加します。
npm install ollama-ai-provider-v2
エージェントを定義する
エージェントを新規作成して、 Agent の model に ollama('gemma4:12b') をセットします。
今回は会話履歴を覚えてもらうために Memory も持たせています。
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { ollama } from 'ollama-ai-provider-v2';
export const ollamaAgent = new Agent({
id: 'ollama-agent',
name: 'Ollama Agent',
instructions: '君はフレンドリーなアシスタントです。ユーザーの質問に対して、適切な回答を提供してください。常に正確で役立つ情報を提供するよう努めてください。',
model: ollama('gemma4:12b'),
memory: new Memory(),
});
あとは、作ったエージェントを Mastra インスタンスに登録します。
import { Mastra } from '@mastra/core/mastra';
import { ollamaAgent } from './agents/ollama-agent';
export const mastra = new Mastra({
agents: { ollamaAgent },
// storage / logger などは mastra create の雛形そのままでOK
});
Memory は会話履歴の保存にストレージを使いますが、mastra create の雛形が LibSQL ストレージを設定済みなので、そのまま動きます。
これだけで Mastra Studio(npm run dev → http://localhost:4111)から会話できるようになります。
Mastra の Harness でコーディングエージェントを作る
完成したリポジトリはこちらです。
Mastra Harness は、AIエージェントアプリケーションを作るためのセッションコントローラーです。
Agent クラスだけでチャット型のコーディングエージェントを作ろうとすると、会話ループ・会話履歴の永続化・モデルの切り替え・ツール実行前の承認…といった、「エージェント本体じゃない周辺の配線」を全部自前で書くことになります、地味に面倒です![]()
Harness は、その UI とエージェントループの間に挟まるランタイムの面倒ごとを、まるごと引き受けてくれるレイヤーです。
スレッド管理・モード切替・状態の永続化・ツール承認・サブエージェントの調整まで全部やってくれるので、こちらは「エージェントに何をさせるか」だけに集中できます。
| 機能 | 説明 |
|---|---|
| Session | 会話状態(モード・モデル・スレッド)をまとめて管理 |
| Modes | agent の指示・ツール・モデルを切り替えられるモード |
| Thread | 会話の永続化(リスタートしても続きから始められる) |
| Tool approvals | ツール実行前にユーザー承認を挟む HITL |
| Subagents | サブエージェントに特定タスクを委譲 |
「plan → build → review」のような複数フェーズを 1 セッションで切り替えながら進めるコーディングエージェントが作りたいときに向いています。
Mastra 公式のターミナル型コーディングエージェント Mastra Code が、まさにこの Harness の上で動いています。
マルチモデル対応・会話の永続化・plan→execute を備えたツールが、同じ仕組みで自分でも作れる、というわけです![]()
Harness は現在 Alpha 機能です。マイナーバージョンアップで API が変わる可能性があります。
セットアップ
さきほど作ったプロジェクトに、そのまま Harness を足していきます。
Harness は @mastra/core に含まれているので追加インストールは不要です。
ツールとワークスペースを用意する
コーディングエージェントには、ファイルを読み書きするツールが要ります。
ただ、AI に好き勝手ファイルを触らせるのは怖いので、操作できる範囲を 1 つのディレクトリ(ワークスペース)に閉じ込めるところから始めます。
まずはそのサンドボックスを定義します、WORKSPACE_ROOT の外に出るパスは弾くようにしておきます。
実行前に forge-workspace/ を作っておきます(無いと read_file などが ENOENT になります)。ここがエージェントの「作業部屋」になり、レビュー対象のコードもこの中に置きます。
つづいてツール本体です。ファイル操作は createTool で定義し、さきほどの resolveInWorkspace を通すことでサンドボックスの外に出られないようにします。read_file / list_dir / write_file / edit_file の 4 つを用意しています。
今回は「自前のサンドボックス + 自作ツール」で済ませていますが、Mastra には公式の Workspace 機能もあります。
エージェントに Filesystem と Sandbox を与えるための仕組みで、ローカルから S3・E2B などのプロバイダーまで選べます。
ファイル操作ツールを毎回自作したくない・コマンド実行までさせたい、という段階になったら、こちらに乗るのが本筋です。
Harness を組み立てる
Harness のキモは モードごとに違うエージェントを切り替えられることです。
今回は plan モードに 読み取り専用のエージェント、build モードに 読み書きできるエージェントを割り当てます。
まずは plan / build それぞれのエージェントを定義します。
planAgent は読み取り系ツールだけ、buildAgent は書き込み系も持たせます。
そして Harness を組み立てて、各モードにエージェントを割り当てます。
default: true が既定モード、memory を渡すと plan の調査結果が build に引き継がれます。
動かす
あとは Harness を初期化して、メッセージを送るだけです。
今回はターミナルで対話する REPL を repl.ts にしました(npm run forge で起動)。/plan /build でモードを切り替えながら進められます。
そして地味に気に入っているのが、起動時のバナーです
緑のハリネズミのマスコット(その名も「ハリネズミ Code」)と、いま開いている workspace・thread・モードがターミナルに出ます。
repl.ts の main() が起動直後に printBanner() を呼んでいるだけの、完全に趣味の部分です。
イベントの描画は render.ts に切り出しています。ポイントは、message_update が「その時点までの全文」を毎回返すので、すでに出力した分との 差分だけ を書き出すところです。
これで npm run forge を叩くと、バナーが出て plan モードで対話が始まります。
小さなコーディングエージェントが、ローカルで完全に動きます![]()
失敗談: Gemma 4 でツール呼び出しが空になる
最初は gemma4:12b をそのまま Harness に繋いで試したんですが、ツールを呼び出すとレスポンスが空になる問題が発生しました![]()
> ツールを呼び出し中...
> (レスポンスなし、タイムアウト)
調べてみると、ローカルモデル + ollama-ai-provider-v2 のツール呼び出しでは「レスポンスが空になる」問題が知られているようでした。
Ollama プロバイダーのドキュメントでも、ツール呼び出しの信頼性を求めるなら、もう一つのコミュニティプロバイダー ai-sdk-ollamaが選択肢として挙げられています。
モデル切り替えで解決
qwen3:14b に切り替えたところ、安定して動くようになりました![]()
ツール呼び出しはモデルの素の賢さがそれなりに要るようで、4B 系より 14B のほうが手堅かったです。
ollama pull qwen3:14b
直すのは agents.ts の model を ollama('gemma4:12b') から ollama('qwen3:14b') に変えるだけ。plan / build の両エージェントとも同じです。
ollama-ai-provider-v2 は qwen3 の hybrid reasoningを明示サポートしています。
ツール呼び出しが必要な場面では、qwen3 系の方が若干安定している印象です。
ただ、実際のところ快適とは言えません。
ワークスペースに Next.js プロジェクトを初期化して、img タグを削除してもらう——くらいのタスクでも結構つまずきます
とはいえ、ローカル LLM も PC のスペックもこれから進化していくはずなので、将来に期待です![]()
ローカルモデルでのツール呼び出しは、モデルによって相性があります。
まずはシンプルな会話から試して、ツール呼び出しが必要な場合は別モデルも検討してみてください。
最後に
ここまで触ってみての所感です。
- ローカルで動くのはやはり良いです。API コストゼロ、プライバシー安心
- Gemma 4 はモデルとしては優秀ですが、ツール呼び出しには qwen3 の方が今のところ安定している
- Mastra Harness はまだ Alpha ですが、「plan → build のモード切替」や「会話の永続化」が標準でついてくるのは便利
コーディングエージェントを作り込もうとすると、いずれ Claude や GPT クラスの高性能モデルが必要な場面は出てきます。
でも、チャットボットや文章作成、画像のようなマルチモーダルなメディア情報の読み取りといった用途なら、Gemma 4 で十分すぎるくらい使えます。





